7a91cedf063e9516b0566318fbabc7d9ef172506
[WebKit-https.git] / Source / WebCore / platform / TreeShared.h
1 /*
2  * Copyright (C) 2006, 2007, 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 TreeShared_h
22 #define TreeShared_h
23
24 #include <wtf/Assertions.h>
25 #include <wtf/MainThread.h>
26 #include <wtf/Noncopyable.h>
27
28 namespace WebCore {
29
30 #ifndef NDEBUG
31 template<typename T> class TreeShared;
32 template<typename T> void adopted(TreeShared<T>*);
33 #endif
34
35 class ContainerNode;
36 class SVGElementInstance;
37 template<typename T> class TreeShared;
38
39 // All classes that inherit TreeShared need to define
40 // callRemovedLastRef(TreeShared<T>*). This is necessary
41 // to kill all virtual methods from TreeShared, by which
42 // we can save 8 byte for a virtual method table pointer.
43 void callRemovedLastRef(TreeShared<ContainerNode>*);
44 void callRemovedLastRef(TreeShared<SVGElementInstance>*);
45
46 template<typename T> class TreeShared {
47     WTF_MAKE_NONCOPYABLE(TreeShared);
48 public:
49     TreeShared()
50         : m_parent(0)
51         , m_refCount(1)
52 #ifndef NDEBUG
53         , m_adoptionIsRequired(true)
54 #endif
55     {
56         ASSERT(isMainThread());
57 #ifndef NDEBUG
58         m_deletionHasBegun = false;
59         m_inRemovedLastRefFunction = false;
60 #endif
61     }
62
63 #ifndef NDEBUG
64     virtual ~TreeShared()
65     {
66         ASSERT(isMainThread());
67         ASSERT(!m_refCount);
68         ASSERT(m_deletionHasBegun);
69         ASSERT(!m_adoptionIsRequired);
70     }
71 #endif
72
73     void ref()
74     {
75         ASSERT(isMainThread());
76         ASSERT(!m_deletionHasBegun);
77         ASSERT(!m_inRemovedLastRefFunction);
78         ASSERT(!m_adoptionIsRequired);
79         ++m_refCount;
80     }
81
82     void deref()
83     {
84         ASSERT(isMainThread());
85         ASSERT(m_refCount >= 0);
86         ASSERT(!m_deletionHasBegun);
87         ASSERT(!m_inRemovedLastRefFunction);
88         ASSERT(!m_adoptionIsRequired);
89         if (--m_refCount <= 0 && !m_parent) {
90 #ifndef NDEBUG
91             m_inRemovedLastRefFunction = true;
92             m_deletionHasBegun = true;
93 #endif
94             callRemovedLastRef(this);
95         }
96     }
97
98     bool hasOneRef() const
99     {
100         ASSERT(!m_deletionHasBegun);
101         ASSERT(!m_inRemovedLastRefFunction);
102         return m_refCount == 1;
103     }
104
105     int refCount() const
106     {
107         return m_refCount;
108     }
109
110     void setParent(T* parent)
111     { 
112         ASSERT(isMainThread());
113         m_parent = parent; 
114     }
115
116     T* parent() const
117     {
118         ASSERT(isMainThreadOrGCThread());
119         return m_parent;
120     }
121
122 #ifndef NDEBUG
123     bool m_deletionHasBegun;
124     bool m_inRemovedLastRefFunction;
125 #endif
126
127 private:
128     // Never called. removedLastRef() must be implemented in all the classes
129     // that inherit TreeShared.
130     void removedLastRef() { ASSERT(0); }
131
132 #ifndef NDEBUG
133     friend void adopted<>(TreeShared<T>*);
134 #endif
135
136     T* m_parent;
137     int m_refCount;
138
139 #ifndef NDEBUG
140     bool m_adoptionIsRequired;
141 #endif
142 };
143
144 #ifndef NDEBUG
145
146 template<typename T> inline void adopted(TreeShared<T>* object)
147 {
148     if (!object)
149         return;
150     ASSERT(!object->m_deletionHasBegun);
151     ASSERT(!object->m_inRemovedLastRefFunction);
152     object->m_adoptionIsRequired = false;
153 }
154
155 #endif
156
157 }
158
159 #endif // TreeShared.h