Index: include/v8-util.h |
diff --git a/include/v8-util.h b/include/v8-util.h |
index 3f8cc6d269d0a6598944720980771210de49b73c..219fe76aae6b328381b0f4e02d062c362a365335 100644 |
--- a/include/v8-util.h |
+++ b/include/v8-util.h |
@@ -42,6 +42,10 @@ namespace v8 { |
typedef uintptr_t PersistentContainerValue; |
static const uintptr_t kPersistentContainerNotFound = 0; |
+enum PersistentContainerCallbackType { |
+ kNotWeak, |
+ kWeak |
+}; |
/** |
@@ -92,38 +96,34 @@ class StdMapTraits { |
/** |
* A default trait implementation for PersistentValueMap, which inherits |
* a std:map backing map from StdMapTraits and holds non-weak persistent |
- * objects. |
+ * objects and has no special Dispose handling. |
* |
- * Users have to implement their own dispose trait. |
+ * You should not derive from this class, since MapType depends on the |
+ * surrounding class, and hence a subclass cannot simply inherit the methods. |
*/ |
template<typename K, typename V> |
-class StrongMapTraits : public StdMapTraits<K, V> { |
+class DefaultPersistentValueMapTraits : public StdMapTraits<K, V> { |
public: |
// Weak callback & friends: |
- static const bool kIsWeak = false; |
- typedef typename StdMapTraits<K, V>::Impl Impl; |
+ static const PersistentContainerCallbackType kCallbackType = kNotWeak; |
+ typedef PersistentValueMap<K, V, DefaultPersistentValueMapTraits<K, V> > |
+ MapType; |
typedef void WeakCallbackDataType; |
+ |
static WeakCallbackDataType* WeakCallbackParameter( |
- Impl* impl, const K& key, Local<V> value); |
- static Impl* ImplFromWeakCallbackData( |
- const WeakCallbackData<V, WeakCallbackDataType>& data); |
+ MapType* map, const K& key, Local<V> value) { |
+ return NULL; |
+ } |
+ static MapType* MapFromWeakCallbackData( |
+ const WeakCallbackData<V, WeakCallbackDataType>& data) { |
+ return NULL; |
+ } |
static K KeyFromWeakCallbackData( |
- const WeakCallbackData<V, WeakCallbackDataType>& data); |
- static void DisposeCallbackData(WeakCallbackDataType* data); |
-}; |
- |
- |
-/** |
- * A default trait implementation for PersistentValueMap, with a std::map |
- * backing map, non-weak persistents as values, and no special dispose |
- * handling. Can be used as-is. |
- */ |
-template<typename K, typename V> |
-class DefaultPersistentValueMapTraits : public StrongMapTraits<K, V> { |
- public: |
- typedef typename StrongMapTraits<K, V>::Impl Impl; |
- static void Dispose(Isolate* isolate, UniquePersistent<V> value, |
- Impl* impl, K key) { } |
+ const WeakCallbackData<V, WeakCallbackDataType>& data) { |
+ return K(); |
+ } |
+ static void DisposeCallbackData(WeakCallbackDataType* data) { } |
+ static void Dispose(Isolate* isolate, UniquePersistent<V> value, K key) { } |
}; |
@@ -154,7 +154,7 @@ class PersistentValueMap { |
/** |
* Return whether the map holds weak persistents. |
*/ |
- V8_INLINE bool IsWeak() { return Traits::kIsWeak; } |
+ V8_INLINE bool IsWeak() { return Traits::kCallbackType != kNotWeak; } |
/** |
* Get value stored in map. |
@@ -167,7 +167,7 @@ class PersistentValueMap { |
* Check whether a value is contained in the map. |
*/ |
V8_INLINE bool Contains(const K& key) { |
- return Traits::Get(&impl_, key) != 0; |
+ return Traits::Get(&impl_, key) != kPersistentContainerNotFound; |
} |
/** |
@@ -175,14 +175,8 @@ class PersistentValueMap { |
* Return true if a value was found. |
*/ |
V8_INLINE bool SetReturnValue(const K& key, |
- ReturnValue<Value>& returnValue) { |
- PersistentContainerValue value = Traits::Get(&impl_, key); |
- bool hasValue = value != 0; |
- if (hasValue) { |
- returnValue.SetInternal( |
- *reinterpret_cast<internal::Object**>(FromVal(value))); |
- } |
- return hasValue; |
+ ReturnValue<Value> returnValue) { |
+ return SetReturnValueFromVal(returnValue, Traits::Get(&impl_, key)); |
} |
/** |
@@ -231,12 +225,76 @@ class PersistentValueMap { |
typename Traits::Impl impl; |
Traits::Swap(impl_, impl); |
for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) { |
- Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(), &impl, |
- Traits::Key(i)); |
+ Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(), |
+ Traits::Key(i)); |
} |
} |
} |
+ /** |
+ * Helper class for GetReference/SetWithReference. Do not use outside |
+ * that context. |
+ */ |
+ class PersistentValueReference { |
+ public: |
+ PersistentValueReference() : value_(kPersistentContainerNotFound) { } |
+ PersistentValueReference(const PersistentValueReference& other) |
+ : value_(other.value_) { } |
+ |
+ Local<V> NewLocal(Isolate* isolate) const { |
+ return Local<V>::New(isolate, FromVal(value_)); |
+ } |
+ bool IsEmpty() const { |
+ return value_ == kPersistentContainerNotFound; |
+ } |
+ template<typename T> |
+ bool SetReturnValue(ReturnValue<T> returnValue) { |
+ return SetReturnValueFromVal(returnValue, value_); |
+ } |
+ void Reset() { |
+ value_ = kPersistentContainerNotFound; |
+ } |
+ void operator=(const PersistentValueReference& other) { |
+ value_ = other.value_; |
+ } |
+ |
+ private: |
+ friend class PersistentValueMap; |
+ |
+ explicit PersistentValueReference(PersistentContainerValue value) |
+ : value_(value) { } |
+ |
+ void operator=(PersistentContainerValue value) { |
+ value_ = value; |
+ } |
+ |
+ PersistentContainerValue value_; |
+ }; |
+ |
+ /** |
+ * Get a reference to a map value. This enables fast, repeated access |
+ * to a value stored in the map while the map remains unchanged. |
+ * |
+ * Careful: This is potentially unsafe, so please use with care. |
+ * The value will become invalid if the value for this key changes |
+ * in the underlying map, as a result of Set or Remove for the same |
+ * key; as a result of the weak callback for the same key; or as a |
+ * result of calling Clear() or destruction of the map. |
+ */ |
+ V8_INLINE PersistentValueReference GetReference(const K& key) { |
+ return PersistentValueReference(Traits::Get(&impl_, key)); |
+ } |
+ |
+ /** |
+ * Put a value into the map and update the reference. |
+ * Restrictions of GetReference apply here as well. |
+ */ |
+ UniquePersistent<V> Set(const K& key, UniquePersistent<V> value, |
+ PersistentValueReference* reference) { |
+ *reference = Leak(&value); |
+ return SetUnique(key, &value); |
+ } |
+ |
private: |
PersistentValueMap(PersistentValueMap&); |
void operator=(PersistentValueMap&); |
@@ -246,10 +304,10 @@ class PersistentValueMap { |
* by the Traits class. |
*/ |
UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) { |
- if (Traits::kIsWeak) { |
+ if (Traits::kCallbackType != kNotWeak) { |
Local<V> value(Local<V>::New(isolate_, *persistent)); |
persistent->template SetWeak<typename Traits::WeakCallbackDataType>( |
- Traits::WeakCallbackParameter(&impl_, key, value), WeakCallback); |
+ Traits::WeakCallbackParameter(this, key, value), WeakCallback); |
} |
PersistentContainerValue old_value = |
Traits::Set(&impl_, key, ClearAndLeak(persistent)); |
@@ -258,11 +316,12 @@ class PersistentValueMap { |
static void WeakCallback( |
const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) { |
- if (Traits::kIsWeak) { |
- typename Traits::Impl* impl = Traits::ImplFromWeakCallbackData(data); |
+ if (Traits::kCallbackType != kNotWeak) { |
+ PersistentValueMap<K, V, Traits>* persistentValueMap = |
+ Traits::MapFromWeakCallbackData(data); |
K key = Traits::KeyFromWeakCallbackData(data); |
- PersistentContainerValue value = Traits::Remove(impl, key); |
- Traits::Dispose(data.GetIsolate(), Release(value).Pass(), impl, key); |
+ Traits::Dispose(data.GetIsolate(), |
+ persistentValueMap->Remove(key).Pass(), key); |
} |
} |
@@ -270,6 +329,16 @@ class PersistentValueMap { |
return reinterpret_cast<V*>(v); |
} |
+ V8_INLINE static bool SetReturnValueFromVal( |
+ ReturnValue<Value>& returnValue, PersistentContainerValue value) { |
+ bool hasValue = value != kPersistentContainerNotFound; |
+ if (hasValue) { |
+ returnValue.SetInternal( |
+ *reinterpret_cast<internal::Object**>(FromVal(value))); |
+ } |
+ return hasValue; |
+ } |
+ |
V8_INLINE static PersistentContainerValue ClearAndLeak( |
UniquePersistent<V>* persistent) { |
V* v = persistent->val_; |
@@ -277,6 +346,11 @@ class PersistentValueMap { |
return reinterpret_cast<PersistentContainerValue>(v); |
} |
+ V8_INLINE static PersistentContainerValue Leak( |
+ UniquePersistent<V>* persistent) { |
+ return reinterpret_cast<PersistentContainerValue>(persistent->val_); |
+ } |
+ |
/** |
* Return a container value as UniquePersistent and make sure the weak |
* callback is properly disposed of. All remove functionality should go |
@@ -285,7 +359,7 @@ class PersistentValueMap { |
V8_INLINE static UniquePersistent<V> Release(PersistentContainerValue v) { |
UniquePersistent<V> p; |
p.val_ = FromVal(v); |
- if (Traits::kIsWeak && !p.IsEmpty()) { |
+ if (Traits::kCallbackType != kNotWeak && !p.IsEmpty()) { |
Traits::DisposeCallbackData( |
p.template ClearWeak<typename Traits::WeakCallbackDataType>()); |
} |
@@ -312,44 +386,6 @@ class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> { |
: PersistentValueMap<K, V, Traits>(isolate) {} |
}; |
- |
-/** |
- * Empty default implementations for StrongTraits methods. |
- * |
- * These should not be necessary, since they're only used in code that |
- * is surrounded by if(Traits::kIsWeak), which for StrongMapTraits is |
- * compile-time false. Most compilers can live without them; however |
- * the compiler we use from 64-bit Win differs. |
- * |
- * TODO(vogelheim): Remove these once they're no longer necessary. |
- */ |
-template<typename K, typename V> |
-typename StrongMapTraits<K, V>::WeakCallbackDataType* |
- StrongMapTraits<K, V>::WeakCallbackParameter( |
- Impl* impl, const K& key, Local<V> value) { |
- return NULL; |
-} |
- |
- |
-template<typename K, typename V> |
-typename StrongMapTraits<K, V>::Impl* |
- StrongMapTraits<K, V>::ImplFromWeakCallbackData( |
- const WeakCallbackData<V, WeakCallbackDataType>& data) { |
- return NULL; |
-} |
- |
- |
-template<typename K, typename V> |
-K StrongMapTraits<K, V>::KeyFromWeakCallbackData( |
- const WeakCallbackData<V, WeakCallbackDataType>& data) { |
- return K(); |
-} |
- |
- |
-template<typename K, typename V> |
-void StrongMapTraits<K, V>::DisposeCallbackData(WeakCallbackDataType* data) { |
-} |
- |
} // namespace v8 |
#endif // V8_UTIL_H_ |