//
//===----------------------------------------------------------------------===//
//
-// This file defines the ValueMap class.
+// This file defines the ValueMap class. ValueMap maps Value* or any subclass
+// to an arbitrary other type. It provides the DenseMap interface but updates
+// itself to remain safe when keys are RAUWed or deleted. By default, when a
+// key is RAUWed from V1 to V2, the old mapping V1->target is removed, and a new
+// mapping V2->target is added. If V2 already existed, its old target is
+// overwritten. When a key is deleted, its mapping is removed.
+//
+// You can override a ValueMap's Config parameter to control exactly what
+// happens on RAUW and destruction and to get called back on each event. It's
+// legal to call back into the ValueMap from a Config's callbacks. Config
+// parameters should inherit from ValueMapConfig<KeyT> to get default
+// implementations of all the methods ValueMap uses. See ValueMapConfig for
+// documentation of the functions you can override.
//
//===----------------------------------------------------------------------===//
template<typename DenseMapT, typename KeyT>
class ValueMapConstIterator;
+/// This class defines the default behavior for configurable aspects of
+/// ValueMap<>. User Configs should inherit from this class to be as compatible
+/// as possible with future versions of ValueMap.
template<typename KeyT>
struct ValueMapConfig {
/// If FollowRAUW is true, the ValueMap will update mappings on RAUW. If it's
struct ExtraData {};
template<typename ExtraDataT>
- static void onRAUW(const ExtraDataT &Data, KeyT Old, KeyT New) {}
+ static void onRAUW(const ExtraDataT & /*Data*/, KeyT /*Old*/, KeyT /*New*/) {}
template<typename ExtraDataT>
- static void onDeleted(const ExtraDataT &Data, KeyT Old) {}
+ static void onDelete(const ExtraDataT &/*Data*/, KeyT /*Old*/) {}
/// Returns a mutex that should be acquired around any changes to the map.
/// This is only acquired from the CallbackVH (and held around calls to onRAUW
- /// and onDeleted) and not inside other ValueMap methods. NULL means that no
+ /// and onDelete) and not inside other ValueMap methods. NULL means that no
/// mutex is necessary.
template<typename ExtraDataT>
- static sys::Mutex *getMutex(const ExtraDataT &Data) { return NULL; }
+ static sys::Mutex *getMutex(const ExtraDataT &/*Data*/) { return NULL; }
};
-/// ValueMap maps Value* or any subclass to an arbitrary other
-/// type. It provides the DenseMap interface. When the key values are
-/// deleted or RAUWed, ValueMap relies on the Config to decide what to
-/// do. Config parameters should inherit from ValueMapConfig<KeyT> to
-/// get default implementations of all the methods ValueMap uses.
-///
-/// By default, when a key is RAUWed from V1 to V2, the old mapping
-/// V1->target is removed, and a new mapping V2->target is added. If
-/// V2 already existed, its old target is overwritten. When a key is
-/// deleted, its mapping is removed. You can override Config to get
-/// called back on each event.
+/// See the file comment.
template<typename KeyT, typename ValueT, typename Config = ValueMapConfig<KeyT>,
typename ValueInfoT = DenseMapInfo<ValueT> >
class ValueMap {
typedef typename Config::ExtraData ExtraData;
MapT Map;
ExtraData Data;
+ ValueMap(const ValueMap&); // DO NOT IMPLEMENT
+ ValueMap& operator=(const ValueMap&); // DO NOT IMPLEMENT
public:
typedef KeyT key_type;
typedef ValueT mapped_type;
typedef std::pair<KeyT, ValueT> value_type;
- ValueMap(const ValueMap& Other) : Map(Other.Map), Data(Other.Data) {}
-
explicit ValueMap(unsigned NumInitBuckets = 64)
: Map(NumInitBuckets), Data() {}
explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64)
bool erase(const KeyT &Val) {
return Map.erase(Wrap(Val));
}
- bool erase(iterator I) {
+ void erase(iterator I) {
return Map.erase(I.base());
}
return Map[Wrap(Key)];
}
- ValueMap& operator=(const ValueMap& Other) {
- Map = Other.Map;
- Data = Other.Data;
- return *this;
- }
-
/// isPointerIntoBucketsArray - Return true if the specified pointer points
/// somewhere into the ValueMap's array of buckets (i.e. either to a key or
/// value in the ValueMap).
}
private:
+ // Takes a key being looked up in the map and wraps it into a
+ // ValueMapCallbackVH, the actual key type of the map. We use a helper
+ // function because ValueMapCVH is constructed with a second parameter.
ValueMapCVH Wrap(KeyT key) const {
// The only way the resulting CallbackVH could try to modify *this (making
// the const_cast incorrect) is if it gets inserted into the map. But then
}
};
+// This CallbackVH updates its ValueMap when the contained Value changes,
+// according to the user's preferences expressed through the Config object.
template<typename KeyT, typename ValueT, typename Config, typename ValueInfoT>
class ValueMapCallbackVH : public CallbackVH {
friend class ValueMap<KeyT, ValueT, Config, ValueInfoT>;
- friend class DenseMapInfo<ValueMapCallbackVH>;
- typedef ValueMap<KeyT, ValueT, Config, ValueInfoT> ValueMap;
+ friend struct DenseMapInfo<ValueMapCallbackVH>;
+ typedef ValueMap<KeyT, ValueT, Config, ValueInfoT> ValueMapT;
typedef typename llvm::remove_pointer<KeyT>::type KeySansPointerT;
- ValueMap *Map;
+ ValueMapT *Map;
- ValueMapCallbackVH(KeyT Key, ValueMap *Map)
+ ValueMapCallbackVH(KeyT Key, ValueMapT *Map)
: CallbackVH(const_cast<Value*>(static_cast<const Value*>(Key))),
Map(Map) {}
sys::Mutex *M = Config::getMutex(Copy.Map->Data);
if (M)
M->acquire();
- Config::onDeleted(Copy.Map->Data, Copy.Unwrap()); // May destroy *this.
+ Config::onDelete(Copy.Map->Data, Copy.Unwrap()); // May destroy *this.
Copy.Map->Map.erase(Copy); // Definitely destroys *this.
if (M)
M->release();
// Can destroy *this:
Config::onRAUW(Copy.Map->Data, Copy.Unwrap(), typed_new_key);
if (Config::FollowRAUW) {
- typename ValueMap::MapT::iterator I = Copy.Map->Map.find(Copy);
+ typename ValueMapT::MapT::iterator I = Copy.Map->Map.find(Copy);
// I could == Copy.Map->Map.end() if the onRAUW callback already
// removed the old mapping.
if (I != Copy.Map->Map.end()) {
static bool isEqual(const VH &LHS, const VH &RHS) {
return LHS == RHS;
}
- static bool isPod() { return false; }
};
struct ValueTypeProxy {
const KeyT first;
ValueT& second;
- ValueTypeProxy *operator->() { return this; }
+ ValueTypeProxy *operator->() { return this; }
operator std::pair<KeyT, ValueT>() const {
return std::make_pair(first, second);
}
return I != RHS.I;
}
- inline ValueMapIterator& operator++() { // Preincrement
+ inline ValueMapIterator& operator++() { // Preincrement
++I;
return *this;
}
- ValueMapIterator operator++(int) { // Postincrement
+ ValueMapIterator operator++(int) { // Postincrement
ValueMapIterator tmp = *this; ++*this; return tmp;
}
};
struct ValueTypeProxy {
const KeyT first;
const ValueT& second;
- ValueTypeProxy *operator->() { return this; }
+ ValueTypeProxy *operator->() { return this; }
operator std::pair<KeyT, ValueT>() const {
return std::make_pair(first, second);
}
return I != RHS.I;
}
- inline ValueMapConstIterator& operator++() { // Preincrement
+ inline ValueMapConstIterator& operator++() { // Preincrement
++I;
return *this;
}
- ValueMapConstIterator operator++(int) { // Postincrement
+ ValueMapConstIterator operator++(int) { // Postincrement
ValueMapConstIterator tmp = *this; ++*this; return tmp;
}
};