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 UniquePersistent 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 {
30 * A default trait implemenation for PersistentValueMap which uses std::map
33 * Users will have to implement their own weak callbacks & dispose traits.
35 template<typename K, typename V>
39 typedef std::map<K, PersistentContainerValue> Impl;
40 typedef typename Impl::iterator Iterator;
42 static bool Empty(Impl* impl) { return impl->empty(); }
43 static size_t Size(Impl* impl) { return impl->size(); }
44 static void Swap(Impl& a, Impl& b) { std::swap(a, b); } // NOLINT
45 static Iterator Begin(Impl* impl) { return impl->begin(); }
46 static Iterator End(Impl* impl) { return impl->end(); }
47 static K Key(Iterator it) { return it->first; }
48 static PersistentContainerValue Value(Iterator it) { return it->second; }
49 static PersistentContainerValue Set(Impl* impl, K key,
50 PersistentContainerValue value) {
51 std::pair<Iterator, bool> res = impl->insert(std::make_pair(key, value));
52 PersistentContainerValue old_value = kPersistentContainerNotFound;
54 old_value = res.first->second;
55 res.first->second = value;
59 static PersistentContainerValue Get(Impl* impl, K key) {
60 Iterator it = impl->find(key);
61 if (it == impl->end()) return kPersistentContainerNotFound;
64 static PersistentContainerValue Remove(Impl* impl, K key) {
65 Iterator it = impl->find(key);
66 if (it == impl->end()) return kPersistentContainerNotFound;
67 PersistentContainerValue value = it->second;
75 * A default trait implementation for PersistentValueMap, which inherits
76 * a std:map backing map from StdMapTraits and holds non-weak persistent
77 * objects and has no special Dispose handling.
79 * You should not derive from this class, since MapType depends on the
80 * surrounding class, and hence a subclass cannot simply inherit the methods.
82 template<typename K, typename V>
83 class DefaultPersistentValueMapTraits : public StdMapTraits<K, V> {
85 // Weak callback & friends:
86 static const PersistentContainerCallbackType kCallbackType = kNotWeak;
87 typedef PersistentValueMap<K, V, DefaultPersistentValueMapTraits<K, V> >
89 typedef void WeakCallbackDataType;
91 static WeakCallbackDataType* WeakCallbackParameter(
92 MapType* map, const K& key, Local<V> value) {
95 static MapType* MapFromWeakCallbackData(
96 const WeakCallbackData<V, WeakCallbackDataType>& data) {
99 static K KeyFromWeakCallbackData(
100 const WeakCallbackData<V, WeakCallbackDataType>& data) {
103 static void DisposeCallbackData(WeakCallbackDataType* data) { }
104 static void Dispose(Isolate* isolate, UniquePersistent<V> value, K key) { }
108 template <typename K, typename V>
109 class DefaultPhantomPersistentValueMapTraits : public StdMapTraits<K, V> {
111 template <typename T>
112 struct RemovePointer;
115 // Weak callback & friends:
116 static const PersistentContainerCallbackType kCallbackType = kNotWeak;
117 typedef PersistentValueMap<
118 K, V, DefaultPhantomPersistentValueMapTraits<K, V> > MapType;
119 typedef void PhantomCallbackDataType;
121 static PhantomCallbackDataType* PhantomCallbackParameter(MapType* map,
126 static MapType* MapFromPhantomCallbackData(
127 const PhantomCallbackData<PhantomCallbackDataType>& data) {
130 static K KeyFromPhantomCallbackData(
131 const PhantomCallbackData<PhantomCallbackDataType>& data) {
134 static void DisposeCallbackData(PhantomCallbackDataType* data) {}
135 static void Dispose(Isolate* isolate, UniquePersistent<V> value, K key) {}
138 template <typename T>
139 struct RemovePointer<T*> {
146 * A map wrapper that allows using UniquePersistent as a mapped value.
147 * C++11 embedders don't need this class, as they can use UniquePersistent
148 * directly in std containers.
150 * The map relies on a backing map, whose type and accessors are described
151 * by the Traits class. The backing map will handle values of type
152 * PersistentContainerValue, with all conversion into and out of V8
153 * handles being transparently handled by this class.
155 template <typename K, typename V, typename Traits>
156 class PersistentValueMapBase {
158 Isolate* GetIsolate() { return isolate_; }
161 * Return size of the map.
163 size_t Size() { return Traits::Size(&impl_); }
166 * Return whether the map holds weak persistents.
168 bool IsWeak() { return Traits::kCallbackType != kNotWeak; }
171 * Get value stored in map.
173 Local<V> Get(const K& key) {
174 return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, key)));
178 * Check whether a value is contained in the map.
180 bool Contains(const K& key) {
181 return Traits::Get(&impl_, key) != kPersistentContainerNotFound;
185 * Get value stored in map and set it in returnValue.
186 * Return true if a value was found.
188 bool SetReturnValue(const K& key,
189 ReturnValue<Value> returnValue) {
190 return SetReturnValueFromVal(&returnValue, Traits::Get(&impl_, key));
194 * Call Isolate::SetReference with the given parent and the map value.
196 void SetReference(const K& key,
197 const Persistent<Object>& parent) {
198 GetIsolate()->SetReference(
199 reinterpret_cast<internal::Object**>(parent.val_),
200 reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key))));
204 * Return value for key and remove it from the map.
206 UniquePersistent<V> Remove(const K& key) {
207 return Release(Traits::Remove(&impl_, key)).Pass();
211 * Traverses the map repeatedly,
212 * in case side effects of disposal cause insertions.
215 typedef typename Traits::Iterator It;
216 HandleScope handle_scope(isolate_);
217 // TODO(dcarney): figure out if this swap and loop is necessary.
218 while (!Traits::Empty(&impl_)) {
219 typename Traits::Impl impl;
220 Traits::Swap(impl_, impl);
221 for (It i = Traits::Begin(&impl); i != Traits::End(&impl); ++i) {
222 Traits::Dispose(isolate_, Release(Traits::Value(i)).Pass(),
229 * Helper class for GetReference/SetWithReference. Do not use outside
232 class PersistentValueReference {
234 PersistentValueReference() : value_(kPersistentContainerNotFound) { }
235 PersistentValueReference(const PersistentValueReference& other)
236 : value_(other.value_) { }
238 Local<V> NewLocal(Isolate* isolate) const {
239 return Local<V>::New(isolate, FromVal(value_));
241 bool IsEmpty() const {
242 return value_ == kPersistentContainerNotFound;
245 bool SetReturnValue(ReturnValue<T> returnValue) {
246 return SetReturnValueFromVal(&returnValue, value_);
249 value_ = kPersistentContainerNotFound;
251 void operator=(const PersistentValueReference& other) {
252 value_ = other.value_;
256 friend class PersistentValueMapBase;
257 friend class PersistentValueMap<K, V, Traits>;
258 friend class PhantomPersistentValueMap<K, V, Traits>;
260 explicit PersistentValueReference(PersistentContainerValue value)
263 void operator=(PersistentContainerValue value) {
267 PersistentContainerValue value_;
271 * Get a reference to a map value. This enables fast, repeated access
272 * to a value stored in the map while the map remains unchanged.
274 * Careful: This is potentially unsafe, so please use with care.
275 * The value will become invalid if the value for this key changes
276 * in the underlying map, as a result of Set or Remove for the same
277 * key; as a result of the weak callback for the same key; or as a
278 * result of calling Clear() or destruction of the map.
280 PersistentValueReference GetReference(const K& key) {
281 return PersistentValueReference(Traits::Get(&impl_, key));
285 explicit PersistentValueMapBase(Isolate* isolate) : isolate_(isolate) {}
287 ~PersistentValueMapBase() { Clear(); }
289 Isolate* isolate() { return isolate_; }
290 typename Traits::Impl* impl() { return &impl_; }
292 static V* FromVal(PersistentContainerValue v) {
293 return reinterpret_cast<V*>(v);
296 static PersistentContainerValue ClearAndLeak(
297 UniquePersistent<V>* persistent) {
298 V* v = persistent->val_;
299 persistent->val_ = 0;
300 return reinterpret_cast<PersistentContainerValue>(v);
303 static PersistentContainerValue Leak(UniquePersistent<V>* persistent) {
304 return reinterpret_cast<PersistentContainerValue>(persistent->val_);
308 * Return a container value as UniquePersistent and make sure the weak
309 * callback is properly disposed of. All remove functionality should go
312 static UniquePersistent<V> Release(PersistentContainerValue v) {
313 UniquePersistent<V> p;
315 if (Traits::kCallbackType != kNotWeak && p.IsWeak()) {
316 Traits::DisposeCallbackData(
317 p.template ClearWeak<typename Traits::WeakCallbackDataType>());
323 PersistentValueMapBase(PersistentValueMapBase&);
324 void operator=(PersistentValueMapBase&);
326 static bool SetReturnValueFromVal(ReturnValue<Value>* returnValue,
327 PersistentContainerValue value) {
328 bool hasValue = value != kPersistentContainerNotFound;
330 returnValue->SetInternal(
331 *reinterpret_cast<internal::Object**>(FromVal(value)));
337 typename Traits::Impl impl_;
341 template <typename K, typename V, typename Traits>
342 class PersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
344 explicit PersistentValueMap(Isolate* isolate)
345 : PersistentValueMapBase<K, V, Traits>(isolate) {}
348 typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
349 PersistentValueReference;
352 * Put value into map. Depending on Traits::kIsWeak, the value will be held
353 * by the map strongly or weakly.
354 * Returns old value as UniquePersistent.
356 UniquePersistent<V> Set(const K& key, Local<V> value) {
357 UniquePersistent<V> persistent(this->isolate(), value);
358 return SetUnique(key, &persistent);
362 * Put value into map, like Set(const K&, Local<V>).
364 UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) {
365 return SetUnique(key, &value);
369 * Put the value into the map, and set the 'weak' callback when demanded
370 * by the Traits class.
372 UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) {
373 if (Traits::kCallbackType != kNotWeak) {
374 Local<V> value(Local<V>::New(this->isolate(), *persistent));
375 persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
376 Traits::WeakCallbackParameter(this, key, value), WeakCallback);
378 PersistentContainerValue old_value =
379 Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
380 return this->Release(old_value).Pass();
384 * Put a value into the map and update the reference.
385 * Restrictions of GetReference apply here as well.
387 UniquePersistent<V> Set(const K& key, UniquePersistent<V> value,
388 PersistentValueReference* reference) {
389 *reference = this->Leak(&value);
390 return SetUnique(key, &value);
394 static void WeakCallback(
395 const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) {
396 if (Traits::kCallbackType != kNotWeak) {
397 PersistentValueMap<K, V, Traits>* persistentValueMap =
398 Traits::MapFromWeakCallbackData(data);
399 K key = Traits::KeyFromWeakCallbackData(data);
400 Traits::Dispose(data.GetIsolate(),
401 persistentValueMap->Remove(key).Pass(), key);
402 Traits::DisposeCallbackData(data.GetParameter());
408 template <typename K, typename V, typename Traits>
409 class PhantomPersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
411 explicit PhantomPersistentValueMap(Isolate* isolate)
412 : PersistentValueMapBase<K, V, Traits>(isolate) {}
415 typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
416 PersistentValueReference;
419 * Put value into map. Depending on Traits::kIsWeak, the value will be held
420 * by the map strongly or weakly.
421 * Returns old value as UniquePersistent.
423 UniquePersistent<V> Set(const K& key, Local<V> value) {
424 UniquePersistent<V> persistent(this->isolate(), value);
425 return SetUnique(key, &persistent);
429 * Put value into map, like Set(const K&, Local<V>).
431 UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) {
432 return SetUnique(key, &value);
436 * Put the value into the map, and set the 'weak' callback when demanded
437 * by the Traits class.
439 UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) {
440 if (Traits::kCallbackType != kNotWeak) {
441 Local<V> value(Local<V>::New(this->isolate(), *persistent));
442 persistent->template SetPhantom<typename Traits::WeakCallbackDataType>(
443 Traits::WeakCallbackParameter(this, key, value), WeakCallback, 0, 1);
445 PersistentContainerValue old_value =
446 Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
447 return this->Release(old_value).Pass();
451 * Put a value into the map and update the reference.
452 * Restrictions of GetReference apply here as well.
454 UniquePersistent<V> Set(const K& key, UniquePersistent<V> value,
455 PersistentValueReference* reference) {
456 *reference = this->Leak(&value);
457 return SetUnique(key, &value);
461 static void WeakCallback(
462 const PhantomCallbackData<typename Traits::WeakCallbackDataType>& data) {
463 if (Traits::kCallbackType != kNotWeak) {
464 PhantomPersistentValueMap<K, V, Traits>* persistentValueMap =
465 Traits::MapFromPhantomCallbackData(data);
466 K key = Traits::KeyFromPhantomCallbackData(data);
467 Traits::Dispose(data.GetIsolate(), persistentValueMap->Remove(key).Pass(),
469 Traits::DisposeCallbackData(data.GetParameter());
476 * A map that uses UniquePersistent as value and std::map as the backing
477 * implementation. Persistents are held non-weak.
479 * C++11 embedders don't need this class, as they can use
480 * UniquePersistent directly in std containers.
482 template<typename K, typename V,
483 typename Traits = DefaultPersistentValueMapTraits<K, V> >
484 class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> {
486 explicit StdPersistentValueMap(Isolate* isolate)
487 : PersistentValueMap<K, V, Traits>(isolate) {}
491 class DefaultPersistentValueVectorTraits {
493 typedef std::vector<PersistentContainerValue> Impl;
495 static void Append(Impl* impl, PersistentContainerValue value) {
496 impl->push_back(value);
498 static bool IsEmpty(const Impl* impl) {
499 return impl->empty();
501 static size_t Size(const Impl* impl) {
504 static PersistentContainerValue Get(const Impl* impl, size_t i) {
505 return (i < impl->size()) ? impl->at(i) : kPersistentContainerNotFound;
507 static void ReserveCapacity(Impl* impl, size_t capacity) {
508 impl->reserve(capacity);
510 static void Clear(Impl* impl) {
517 * A vector wrapper that safely stores UniquePersistent values.
518 * C++11 embedders don't need this class, as they can use UniquePersistent
519 * directly in std containers.
521 * This class relies on a backing vector implementation, whose type and methods
522 * are described by the Traits class. The backing map will handle values of type
523 * PersistentContainerValue, with all conversion into and out of V8
524 * handles being transparently handled by this class.
526 template<typename V, typename Traits = DefaultPersistentValueVectorTraits>
527 class PersistentValueVector {
529 explicit PersistentValueVector(Isolate* isolate) : isolate_(isolate) { }
531 ~PersistentValueVector() {
536 * Append a value to the vector.
538 void Append(Local<V> value) {
539 UniquePersistent<V> persistent(isolate_, value);
540 Traits::Append(&impl_, ClearAndLeak(&persistent));
544 * Append a persistent's value to the vector.
546 void Append(UniquePersistent<V> persistent) {
547 Traits::Append(&impl_, ClearAndLeak(&persistent));
551 * Are there any values in the vector?
553 bool IsEmpty() const {
554 return Traits::IsEmpty(&impl_);
558 * How many elements are in the vector?
560 size_t Size() const {
561 return Traits::Size(&impl_);
565 * Retrieve the i-th value in the vector.
567 Local<V> Get(size_t index) const {
568 return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, index)));
572 * Remove all elements from the vector.
575 size_t length = Traits::Size(&impl_);
576 for (size_t i = 0; i < length; i++) {
577 UniquePersistent<V> p;
578 p.val_ = FromVal(Traits::Get(&impl_, i));
580 Traits::Clear(&impl_);
584 * Reserve capacity in the vector.
585 * (Efficiency gains depend on the backing implementation.)
587 void ReserveCapacity(size_t capacity) {
588 Traits::ReserveCapacity(&impl_, capacity);
592 static PersistentContainerValue ClearAndLeak(
593 UniquePersistent<V>* persistent) {
594 V* v = persistent->val_;
595 persistent->val_ = 0;
596 return reinterpret_cast<PersistentContainerValue>(v);
599 static V* FromVal(PersistentContainerValue v) {
600 return reinterpret_cast<V*>(v);
604 typename Traits::Impl impl_;