1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
13 * Support for Persistent containers.
15 * C++11 embedders can use STL containers with Global values,
16 * but pre-C++11 does not support the required move semantic and hence
17 * may want these container classes.
21 typedef uintptr_t PersistentContainerValue;
22 static const uintptr_t kPersistentContainerNotFound = 0;
23 enum PersistentContainerCallbackType {
25 // These correspond to v8::WeakCallbackType
27 kWeakWithInternalFields,
28 kWeak = kWeakWithParameter // For backwards compatibility. Deprecate.
33 * A default trait implemenation for PersistentValueMap which uses std::map
36 * Users will have to implement their own weak callbacks & dispose traits.
38 template<typename K, typename V>
42 typedef std::map<K, PersistentContainerValue> Impl;
43 typedef typename Impl::iterator Iterator;
45 static bool Empty(Impl* impl) { return impl->empty(); }
46 static size_t Size(Impl* impl) { return impl->size(); }
47 static void Swap(Impl& a, Impl& b) { std::swap(a, b); } // NOLINT
48 static Iterator Begin(Impl* impl) { return impl->begin(); }
49 static Iterator End(Impl* impl) { return impl->end(); }
50 static K Key(Iterator it) { return it->first; }
51 static PersistentContainerValue Value(Iterator it) { return it->second; }
52 static PersistentContainerValue Set(Impl* impl, K key,
53 PersistentContainerValue value) {
54 std::pair<Iterator, bool> res = impl->insert(std::make_pair(key, value));
55 PersistentContainerValue old_value = kPersistentContainerNotFound;
57 old_value = res.first->second;
58 res.first->second = value;
62 static PersistentContainerValue Get(Impl* impl, K key) {
63 Iterator it = impl->find(key);
64 if (it == impl->end()) return kPersistentContainerNotFound;
67 static PersistentContainerValue Remove(Impl* impl, K key) {
68 Iterator it = impl->find(key);
69 if (it == impl->end()) return kPersistentContainerNotFound;
70 PersistentContainerValue value = it->second;
78 * A default trait implementation for PersistentValueMap, which inherits
79 * a std:map backing map from StdMapTraits and holds non-weak persistent
80 * objects and has no special Dispose handling.
82 * You should not derive from this class, since MapType depends on the
83 * surrounding class, and hence a subclass cannot simply inherit the methods.
85 template<typename K, typename V>
86 class DefaultPersistentValueMapTraits : public StdMapTraits<K, V> {
88 // Weak callback & friends:
89 static const PersistentContainerCallbackType kCallbackType = kNotWeak;
90 typedef PersistentValueMap<K, V, DefaultPersistentValueMapTraits<K, V> >
92 typedef void WeakCallbackDataType;
94 static WeakCallbackDataType* WeakCallbackParameter(
95 MapType* map, const K& key, Local<V> value) {
98 static MapType* MapFromWeakCallbackData(
99 const WeakCallbackData<V, WeakCallbackDataType>& data) {
102 static K KeyFromWeakCallbackData(
103 const WeakCallbackData<V, WeakCallbackDataType>& data) {
106 static void DisposeCallbackData(WeakCallbackDataType* data) { }
107 static void Dispose(Isolate* isolate, Global<V> value, K key) {}
111 template <typename K, typename V>
112 class DefaultGlobalMapTraits : public StdMapTraits<K, V> {
114 template <typename T>
115 struct RemovePointer;
118 // Weak callback & friends:
119 static const PersistentContainerCallbackType kCallbackType = kNotWeak;
120 typedef PersistentValueMap<K, V, DefaultGlobalMapTraits<K, V> > MapType;
121 typedef void WeakCallbackInfoType;
123 static WeakCallbackInfoType* WeakCallbackParameter(MapType* map, const K& key,
127 static MapType* MapFromWeakCallbackInfo(
128 const WeakCallbackInfo<WeakCallbackInfoType>& data) {
131 static K KeyFromWeakCallbackInfo(
132 const WeakCallbackInfo<WeakCallbackInfoType>& data) {
135 static void DisposeCallbackData(WeakCallbackInfoType* data) {}
136 static void Dispose(Isolate* isolate, Global<V> value, K key) {}
137 static void DisposeWeak(Isolate* isolate,
138 const WeakCallbackInfo<WeakCallbackInfoType>& data,
142 template <typename T>
143 struct RemovePointer<T*> {
150 * A map wrapper that allows using Global as a mapped value.
151 * C++11 embedders don't need this class, as they can use Global
152 * directly in std containers.
154 * The map relies on a backing map, whose type and accessors are described
155 * by the Traits class. The backing map will handle values of type
156 * PersistentContainerValue, with all conversion into and out of V8
157 * handles being transparently handled by this class.
159 template <typename K, typename V, typename Traits>
160 class PersistentValueMapBase {
162 Isolate* GetIsolate() { return isolate_; }
165 * Return size of the map.
167 size_t Size() { return Traits::Size(&impl_); }
170 * Return whether the map holds weak persistents.
172 bool IsWeak() { return Traits::kCallbackType != kNotWeak; }
175 * Get value stored in map.
177 Local<V> Get(const K& key) {
178 return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key)));
182 * Check whether a value is contained in the map.
184 bool Contains(const K& key) {
185 return Traits::Get(&impl_, key) != kPersistentContainerNotFound;
189 * Get value stored in map and set it in returnValue.
190 * Return true if a value was found.
192 bool SetReturnValue(const K& key,
193 ReturnValue<Value> returnValue) {
194 return SetReturnValueFromVal(&returnValue, Traits::Get(&impl_, key));
198 * Call Isolate::SetReference with the given parent and the map value.
200 void SetReference(const K& key,
201 const Persistent<Object>& parent) {
202 GetIsolate()->SetReference(
203 reinterpret_cast<internal::Object**>(parent.val_),
204 reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key))));
208 * Return value for key and remove it from the map.
210 Global<V> Remove(const K& key) {
211 return Release(Traits::Remove(&impl_, key)).Pass();
215 * Traverses the map repeatedly,
216 * in case side effects of disposal cause insertions.
219 typedef typename Traits::Iterator It;
220 HandleScope handle_scope(isolate_);
221 // TODO(dcarney): figure out if this swap and loop is necessary.
222 while (!Traits::Empty(&impl_)) {
223 typename Traits::Impl impl;
224 Traits::Swap(impl_, impl);
225 for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) {
226 Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(),
233 * Helper class for GetReference/SetWithReference. Do not use outside
236 class PersistentValueReference {
238 PersistentValueReference() : value_(kPersistentContainerNotFound) { }
239 PersistentValueReference(const PersistentValueReference& other)
240 : value_(other.value_) { }
242 Local<V> NewLocal(Isolate* isolate) const {
243 return Local<V>::New(isolate, FromVal(value_));
245 bool IsEmpty() const {
246 return value_ == kPersistentContainerNotFound;
249 bool SetReturnValue(ReturnValue<T> returnValue) {
250 return SetReturnValueFromVal(&returnValue, value_);
253 value_ = kPersistentContainerNotFound;
255 void operator=(const PersistentValueReference& other) {
256 value_ = other.value_;
260 friend class PersistentValueMapBase;
261 friend class PersistentValueMap<K, V, Traits>;
262 friend class GlobalValueMap<K, V, Traits>;
264 explicit PersistentValueReference(PersistentContainerValue value)
267 void operator=(PersistentContainerValue value) {
271 PersistentContainerValue value_;
275 * Get a reference to a map value. This enables fast, repeated access
276 * to a value stored in the map while the map remains unchanged.
278 * Careful: This is potentially unsafe, so please use with care.
279 * The value will become invalid if the value for this key changes
280 * in the underlying map, as a result of Set or Remove for the same
281 * key; as a result of the weak callback for the same key; or as a
282 * result of calling Clear() or destruction of the map.
284 PersistentValueReference GetReference(const K& key) {
285 return PersistentValueReference(Traits::Get(&impl_, key));
289 explicit PersistentValueMapBase(Isolate* isolate) : isolate_(isolate) {}
291 ~PersistentValueMapBase() { Clear(); }
293 Isolate* isolate() { return isolate_; }
294 typename Traits::Impl* impl() { return &impl_; }
296 static V* FromVal(PersistentContainerValue v) {
297 return reinterpret_cast<V*>(v);
300 static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
301 V* v = persistent->val_;
302 persistent->val_ = 0;
303 return reinterpret_cast<PersistentContainerValue>(v);
306 static PersistentContainerValue Leak(Global<V>* persistent) {
307 return reinterpret_cast<PersistentContainerValue>(persistent->val_);
311 * Return a container value as Global and make sure the weak
312 * callback is properly disposed of. All remove functionality should go
315 static Global<V> Release(PersistentContainerValue v) {
318 if (Traits::kCallbackType != kNotWeak && p.IsWeak()) {
319 Traits::DisposeCallbackData(
320 p.template ClearWeak<typename Traits::WeakCallbackDataType>());
325 void RemoveWeak(const K& key) {
327 p.val_ = FromVal(Traits::Remove(&impl_, key));
332 PersistentValueMapBase(PersistentValueMapBase&);
333 void operator=(PersistentValueMapBase&);
335 static bool SetReturnValueFromVal(ReturnValue<Value>* returnValue,
336 PersistentContainerValue value) {
337 bool hasValue = value != kPersistentContainerNotFound;
339 returnValue->SetInternal(
340 *reinterpret_cast<internal::Object**>(FromVal(value)));
346 typename Traits::Impl impl_;
350 template <typename K, typename V, typename Traits>
351 class PersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
353 explicit PersistentValueMap(Isolate* isolate)
354 : PersistentValueMapBase<K, V, Traits>(isolate) {}
357 typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
358 PersistentValueReference;
361 * Put value into map. Depending on Traits::kIsWeak, the value will be held
362 * by the map strongly or weakly.
363 * Returns old value as Global.
365 Global<V> Set(const K& key, Local<V> value) {
366 Global<V> persistent(this->isolate(), value);
367 return SetUnique(key, &persistent);
371 * Put value into map, like Set(const K&, Local<V>).
373 Global<V> Set(const K& key, Global<V> value) {
374 return SetUnique(key, &value);
378 * Put the value into the map, and set the 'weak' callback when demanded
379 * by the Traits class.
381 Global<V> SetUnique(const K& key, Global<V>* persistent) {
382 if (Traits::kCallbackType != kNotWeak) {
383 Local<V> value(Local<V>::New(this->isolate(), *persistent));
384 persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
385 Traits::WeakCallbackParameter(this, key, value), WeakCallback);
387 PersistentContainerValue old_value =
388 Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
389 return this->Release(old_value).Pass();
393 * Put a value into the map and update the reference.
394 * Restrictions of GetReference apply here as well.
396 Global<V> Set(const K& key, Global<V> value,
397 PersistentValueReference* reference) {
398 *reference = this->Leak(&value);
399 return SetUnique(key, &value);
403 static void WeakCallback(
404 const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) {
405 if (Traits::kCallbackType != kNotWeak) {
406 PersistentValueMap<K, V, Traits>* persistentValueMap =
407 Traits::MapFromWeakCallbackData(data);
408 K key = Traits::KeyFromWeakCallbackData(data);
409 Traits::Dispose(data.GetIsolate(),
410 persistentValueMap->Remove(key).Pass(), key);
411 Traits::DisposeCallbackData(data.GetParameter());
417 template <typename K, typename V, typename Traits>
418 class GlobalValueMap : public PersistentValueMapBase<K, V, Traits> {
420 explicit GlobalValueMap(Isolate* isolate)
421 : PersistentValueMapBase<K, V, Traits>(isolate) {}
424 typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
425 PersistentValueReference;
428 * Put value into map. Depending on Traits::kIsWeak, the value will be held
429 * by the map strongly or weakly.
430 * Returns old value as Global.
432 Global<V> Set(const K& key, Local<V> value) {
433 Global<V> persistent(this->isolate(), value);
434 return SetUnique(key, &persistent);
438 * Put value into map, like Set(const K&, Local<V>).
440 Global<V> Set(const K& key, Global<V> value) {
441 return SetUnique(key, &value);
445 * Put the value into the map, and set the 'weak' callback when demanded
446 * by the Traits class.
448 Global<V> SetUnique(const K& key, Global<V>* persistent) {
449 if (Traits::kCallbackType != kNotWeak) {
450 WeakCallbackType callback_type =
451 Traits::kCallbackType == kWeakWithInternalFields
452 ? WeakCallbackType::kInternalFields
453 : WeakCallbackType::kParameter;
454 Local<V> value(Local<V>::New(this->isolate(), *persistent));
455 persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
456 Traits::WeakCallbackParameter(this, key, value), WeakCallback,
459 PersistentContainerValue old_value =
460 Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
461 return this->Release(old_value).Pass();
465 * Put a value into the map and update the reference.
466 * Restrictions of GetReference apply here as well.
468 Global<V> Set(const K& key, Global<V> value,
469 PersistentValueReference* reference) {
470 *reference = this->Leak(&value);
471 return SetUnique(key, &value);
475 static void WeakCallback(
476 const WeakCallbackInfo<typename Traits::WeakCallbackDataType>& data) {
477 if (Traits::kCallbackType != kNotWeak) {
478 GlobalValueMap<K, V, Traits>* persistentValueMap =
479 Traits::MapFromWeakCallbackInfo(data);
480 K key = Traits::KeyFromWeakCallbackInfo(data);
481 persistentValueMap->RemoveWeak(key);
482 Traits::DisposeWeak(data.GetIsolate(), data, key);
489 * A map that uses Global as value and std::map as the backing
490 * implementation. Persistents are held non-weak.
492 * C++11 embedders don't need this class, as they can use
493 * Global directly in std containers.
495 template<typename K, typename V,
496 typename Traits = DefaultPersistentValueMapTraits<K, V> >
497 class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> {
499 explicit StdPersistentValueMap(Isolate* isolate)
500 : PersistentValueMap<K, V, Traits>(isolate) {}
504 class DefaultPersistentValueVectorTraits {
506 typedef std::vector<PersistentContainerValue> Impl;
508 static void Append(Impl* impl, PersistentContainerValue value) {
509 impl->push_back(value);
511 static bool IsEmpty(const Impl* impl) {
512 return impl->empty();
514 static size_t Size(const Impl* impl) {
517 static PersistentContainerValue Get(const Impl* impl, size_t i) {
518 return (i < impl->size()) ? impl->at(i) : kPersistentContainerNotFound;
520 static void ReserveCapacity(Impl* impl, size_t capacity) {
521 impl->reserve(capacity);
523 static void Clear(Impl* impl) {
530 * A vector wrapper that safely stores Global values.
531 * C++11 embedders don't need this class, as they can use Global
532 * directly in std containers.
534 * This class relies on a backing vector implementation, whose type and methods
535 * are described by the Traits class. The backing map will handle values of type
536 * PersistentContainerValue, with all conversion into and out of V8
537 * handles being transparently handled by this class.
539 template<typename V, typename Traits = DefaultPersistentValueVectorTraits>
540 class PersistentValueVector {
542 explicit PersistentValueVector(Isolate* isolate) : isolate_(isolate) { }
544 ~PersistentValueVector() {
549 * Append a value to the vector.
551 void Append(Local<V> value) {
552 Global<V> persistent(isolate_, value);
553 Traits::Append(&impl_, ClearAndLeak(&persistent));
557 * Append a persistent's value to the vector.
559 void Append(Global<V> persistent) {
560 Traits::Append(&impl_, ClearAndLeak(&persistent));
564 * Are there any values in the vector?
566 bool IsEmpty() const {
567 return Traits::IsEmpty(&impl_);
571 * How many elements are in the vector?
573 size_t Size() const {
574 return Traits::Size(&impl_);
578 * Retrieve the i-th value in the vector.
580 Local<V> Get(size_t index) const {
581 return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, index)));
585 * Remove all elements from the vector.
588 size_t length = Traits::Size(&impl_);
589 for (size_t i = 0; i < length; i++) {
591 p.val_ = FromVal(Traits::Get(&impl_, i));
593 Traits::Clear(&impl_);
597 * Reserve capacity in the vector.
598 * (Efficiency gains depend on the backing implementation.)
600 void ReserveCapacity(size_t capacity) {
601 Traits::ReserveCapacity(&impl_, capacity);
605 static PersistentContainerValue ClearAndLeak(Global<V>* persistent) {
606 V* v = persistent->val_;
607 persistent->val_ = 0;
608 return reinterpret_cast<PersistentContainerValue>(v);
611 static V* FromVal(PersistentContainerValue v) {
612 return reinterpret_cast<V*>(v);
616 typename Traits::Impl impl_;