|
1 /* |
|
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. |
|
3 * |
|
4 * This library is free software; you can redistribute it and/or |
|
5 * modify it under the terms of the GNU Library General Public |
|
6 * License as published by the Free Software Foundation; either |
|
7 * version 2 of the License, or (at your option) any later version. |
|
8 * |
|
9 * This library is distributed in the hope that it will be useful, |
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 * Library General Public License for more details. |
|
13 * |
|
14 * You should have received a copy of the GNU Library General Public License |
|
15 * along with this library; see the file COPYING.LIB. If not, write to |
|
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
17 * Boston, MA 02110-1301, USA. |
|
18 * |
|
19 */ |
|
20 |
|
21 #ifndef RefCounted_h |
|
22 #define RefCounted_h |
|
23 |
|
24 #include "Assertions.h" |
|
25 #include "Noncopyable.h" |
|
26 |
|
27 namespace WTF { |
|
28 |
|
29 // This base class holds the non-template methods and attributes. |
|
30 // The RefCounted class inherits from it reducing the template bloat |
|
31 // generated by the compiler (technique called template hoisting). |
|
32 class RefCountedBase { |
|
33 public: |
|
34 void ref() |
|
35 { |
|
36 ASSERT(!m_deletionHasBegun); |
|
37 ASSERT(!m_adoptionIsRequired); |
|
38 ++m_refCount; |
|
39 } |
|
40 |
|
41 bool hasOneRef() const |
|
42 { |
|
43 ASSERT(!m_deletionHasBegun); |
|
44 return m_refCount == 1; |
|
45 } |
|
46 |
|
47 int refCount() const |
|
48 { |
|
49 return m_refCount; |
|
50 } |
|
51 |
|
52 void relaxAdoptionRequirement() |
|
53 { |
|
54 #ifndef NDEBUG |
|
55 ASSERT(!m_deletionHasBegun); |
|
56 ASSERT(m_adoptionIsRequired); |
|
57 m_adoptionIsRequired = false; |
|
58 #endif |
|
59 } |
|
60 |
|
61 protected: |
|
62 RefCountedBase() |
|
63 : m_refCount(1) |
|
64 #ifndef NDEBUG |
|
65 , m_deletionHasBegun(false) |
|
66 , m_adoptionIsRequired(true) |
|
67 #endif |
|
68 { |
|
69 } |
|
70 |
|
71 ~RefCountedBase() |
|
72 { |
|
73 ASSERT(m_deletionHasBegun); |
|
74 ASSERT(!m_adoptionIsRequired); |
|
75 } |
|
76 |
|
77 // Returns whether the pointer should be freed or not. |
|
78 bool derefBase() |
|
79 { |
|
80 ASSERT(!m_deletionHasBegun); |
|
81 ASSERT(!m_adoptionIsRequired); |
|
82 |
|
83 ASSERT(m_refCount > 0); |
|
84 if (m_refCount == 1) { |
|
85 #ifndef NDEBUG |
|
86 m_deletionHasBegun = true; |
|
87 #endif |
|
88 return true; |
|
89 } |
|
90 |
|
91 --m_refCount; |
|
92 return false; |
|
93 } |
|
94 |
|
95 // Helper for generating JIT code. Please do not use for non-JIT purposes. |
|
96 int* addressOfCount() |
|
97 { |
|
98 return &m_refCount; |
|
99 } |
|
100 |
|
101 #ifndef NDEBUG |
|
102 bool deletionHasBegun() const |
|
103 { |
|
104 return m_deletionHasBegun; |
|
105 } |
|
106 #endif |
|
107 |
|
108 private: |
|
109 template<typename T> friend class CrossThreadRefCounted; |
|
110 |
|
111 #ifndef NDEBUG |
|
112 friend void adopted(RefCountedBase*); |
|
113 #endif |
|
114 |
|
115 int m_refCount; |
|
116 #ifndef NDEBUG |
|
117 bool m_deletionHasBegun; |
|
118 bool m_adoptionIsRequired; |
|
119 #endif |
|
120 }; |
|
121 |
|
122 #ifndef NDEBUG |
|
123 |
|
124 inline void adopted(RefCountedBase* object) |
|
125 { |
|
126 if (!object) |
|
127 return; |
|
128 ASSERT(!object->m_deletionHasBegun); |
|
129 object->m_adoptionIsRequired = false; |
|
130 } |
|
131 |
|
132 #endif |
|
133 |
|
134 template<typename T> class RefCounted : public RefCountedBase, public Noncopyable { |
|
135 public: |
|
136 void deref() |
|
137 { |
|
138 if (derefBase()) |
|
139 delete static_cast<T*>(this); |
|
140 } |
|
141 |
|
142 protected: |
|
143 ~RefCounted() |
|
144 { |
|
145 } |
|
146 }; |
|
147 |
|
148 template<typename T> class RefCountedCustomAllocated : public RefCountedBase, public NoncopyableCustomAllocated { |
|
149 public: |
|
150 void deref() |
|
151 { |
|
152 if (derefBase()) |
|
153 delete static_cast<T*>(this); |
|
154 } |
|
155 |
|
156 protected: |
|
157 ~RefCountedCustomAllocated() |
|
158 { |
|
159 } |
|
160 }; |
|
161 |
|
162 } // namespace WTF |
|
163 |
|
164 using WTF::RefCounted; |
|
165 using WTF::RefCountedCustomAllocated; |
|
166 |
|
167 #endif // RefCounted_h |