1 /* 2 * Copyright (C) 2009 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #ifndef Weak_h 27 #define Weak_h 28 29 #include "Assertions.h" 30 #include "Handle.h" 31 #include "HandleHeap.h" 32 #include "JSGlobalData.h" 33 34 namespace JSC { 35 36 // A weakly referenced handle that becomes 0 when the value it points to is garbage collected. 37 template <typename T> class Weak : public Handle<T> { 38 using Handle<T>::slot; 39 using Handle<T>::setSlot; 40 41 public: 42 typedef typename Handle<T>::ExternalType ExternalType; 43 44 Weak() 45 : Handle<T>() 46 { 47 } 48 49 Weak(JSGlobalData& globalData, ExternalType value = ExternalType(), WeakHandleOwner* weakOwner = 0, void* context = 0) 50 : Handle<T>(globalData.allocateGlobalHandle()) 51 { 52 HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context); 53 set(value); 54 } 55 56 Weak(const Weak& other) 57 : Handle<T>() 58 { 59 if (!other.slot()) 60 return; 61 setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot())); 62 } 63 64 template <typename U> Weak(const Weak<U>& other) 65 : Handle<T>() 66 { 67 if (!other.slot()) 68 return; 69 setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot())); 70 } 71 72 enum HashTableDeletedValueTag { HashTableDeletedValue }; 73 bool isHashTableDeletedValue() const { return slot() == hashTableDeletedValue(); } 74 Weak(HashTableDeletedValueTag) 75 : Handle<T>(hashTableDeletedValue()) 76 { 77 } 78 79 ~Weak() 80 { 81 clear(); 82 } 83 84 void swap(Weak& other) 85 { 86 Handle<T>::swap(other); 87 } 88 89 ExternalType get() const { return HandleTypes<T>::getFromSlot(slot()); } 90 91 void clear() 92 { 93 if (!slot()) 94 return; 95 HandleHeap::heapFor(slot())->deallocate(slot()); 96 setSlot(0); 97 } 98 99 void set(JSGlobalData& globalData, ExternalType value, WeakHandleOwner* weakOwner = 0, void* context = 0) 100 { 101 if (!slot()) { 102 setSlot(globalData.allocateGlobalHandle()); 103 HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context); 104 } 105 ASSERT(HandleHeap::heapFor(slot())->hasWeakOwner(slot(), weakOwner)); 106 set(value); 107 } 108 109 template <typename U> Weak& operator=(const Weak<U>& other) 110 { 111 clear(); 112 if (other.slot()) 113 setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot())); 114 return *this; 115 } 116 117 Weak& operator=(const Weak& other) 118 { 119 clear(); 120 if (other.slot()) 121 setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot())); 122 return *this; 123 } 124 125 private: 126 static HandleSlot hashTableDeletedValue() { return reinterpret_cast<HandleSlot>(-1); } 127 128 void set(ExternalType externalType) 129 { 130 ASSERT(slot()); 131 JSValue value = HandleTypes<T>::toJSValue(externalType); 132 ASSERT(!value || !value.isCell() || Heap::isMarked(value.asCell())); 133 HandleHeap::heapFor(slot())->writeBarrier(slot(), value); 134 *slot() = value; 135 } 136 }; 137 138 template<class T> inline void swap(Weak<T>& a, Weak<T>& b) 139 { 140 a.swap(b); 141 } 142 143 } // namespace JSC 144 145 namespace WTF { 146 147 template<typename T> struct VectorTraits<JSC::Weak<T> > : SimpleClassVectorTraits { 148 static const bool canCompareWithMemcmp = false; 149 }; 150 151 template<typename P> struct HashTraits<JSC::Weak<P> > : SimpleClassHashTraits<JSC::Weak<P> > { }; 152 153 } 154 155 #endif // Weak_h 156