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
Weak()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
Weak(const Weak & other)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
Weak(const Weak<U> & other)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 };
isHashTableDeletedValue()73 bool isHashTableDeletedValue() const { return slot() == hashTableDeletedValue(); }
Weak(HashTableDeletedValueTag)74 Weak(HashTableDeletedValueTag)
75 : Handle<T>(hashTableDeletedValue())
76 {
77 }
78
~Weak()79 ~Weak()
80 {
81 clear();
82 }
83
swap(Weak & other)84 void swap(Weak& other)
85 {
86 Handle<T>::swap(other);
87 }
88
get()89 ExternalType get() const { return HandleTypes<T>::getFromSlot(slot()); }
90
clear()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:
hashTableDeletedValue()126 static HandleSlot hashTableDeletedValue() { return reinterpret_cast<HandleSlot>(-1); }
127
set(ExternalType externalType)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
swap(Weak<T> & a,Weak<T> & b)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