Unreviewed, rolling out r234489.
[WebKit-https.git] / Source / WTF / wtf / RefCounted.h
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2013 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 #pragma once
22
23 #include <wtf/Assertions.h>
24 #include <wtf/FastMalloc.h>
25 #include <wtf/Noncopyable.h>
26
27 namespace WTF {
28
29 #if defined(NDEBUG) && !ENABLE(SECURITY_ASSERTIONS)
30 #define CHECK_REF_COUNTED_LIFECYCLE 0
31 #else
32 #define CHECK_REF_COUNTED_LIFECYCLE 1
33 #endif
34
35 // This base class holds the non-template methods and attributes.
36 // The RefCounted class inherits from it reducing the template bloat
37 // generated by the compiler (technique called template hoisting).
38 class RefCountedBase {
39 public:
40     void ref() const
41     {
42 #if CHECK_REF_COUNTED_LIFECYCLE
43         ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);
44         ASSERT(!m_adoptionIsRequired);
45 #endif
46         ++m_refCount;
47     }
48
49     bool hasOneRef() const
50     {
51 #if CHECK_REF_COUNTED_LIFECYCLE
52         ASSERT(!m_deletionHasBegun);
53 #endif
54         return m_refCount == 1;
55     }
56
57     unsigned refCount() const
58     {
59         return m_refCount;
60     }
61
62     void relaxAdoptionRequirement()
63     {
64 #if CHECK_REF_COUNTED_LIFECYCLE
65         ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);
66         ASSERT(m_adoptionIsRequired);
67         m_adoptionIsRequired = false;
68 #endif
69     }
70
71 protected:
72     RefCountedBase()
73         : m_refCount(1)
74 #if CHECK_REF_COUNTED_LIFECYCLE
75         , m_deletionHasBegun(false)
76         , m_adoptionIsRequired(true)
77 #endif
78     {
79     }
80
81     ~RefCountedBase()
82     {
83 #if CHECK_REF_COUNTED_LIFECYCLE
84         ASSERT(m_deletionHasBegun);
85         ASSERT(!m_adoptionIsRequired);
86 #endif
87     }
88
89     // Returns whether the pointer should be freed or not.
90     bool derefBase() const
91     {
92 #if CHECK_REF_COUNTED_LIFECYCLE
93         ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);
94         ASSERT(!m_adoptionIsRequired);
95 #endif
96
97         ASSERT(m_refCount);
98         unsigned tempRefCount = m_refCount - 1;
99         if (!tempRefCount) {
100 #if CHECK_REF_COUNTED_LIFECYCLE
101             m_deletionHasBegun = true;
102 #endif
103             return true;
104         }
105         m_refCount = tempRefCount;
106         return false;
107     }
108
109 #if CHECK_REF_COUNTED_LIFECYCLE
110     bool deletionHasBegun() const
111     {
112         return m_deletionHasBegun;
113     }
114 #endif
115
116 private:
117
118 #if CHECK_REF_COUNTED_LIFECYCLE
119     friend void adopted(RefCountedBase*);
120 #endif
121
122     mutable unsigned m_refCount;
123 #if CHECK_REF_COUNTED_LIFECYCLE
124     mutable bool m_deletionHasBegun;
125     mutable bool m_adoptionIsRequired;
126 #endif
127 };
128
129 #if CHECK_REF_COUNTED_LIFECYCLE
130 inline void adopted(RefCountedBase* object)
131 {
132     if (!object)
133         return;
134     ASSERT_WITH_SECURITY_IMPLICATION(!object->m_deletionHasBegun);
135     object->m_adoptionIsRequired = false;
136 }
137 #endif
138
139 template<typename T> class RefCounted : public RefCountedBase {
140     WTF_MAKE_NONCOPYABLE(RefCounted); WTF_MAKE_FAST_ALLOCATED;
141 public:
142     void deref() const
143     {
144         if (derefBase())
145             delete static_cast<const T*>(this);
146     }
147
148 protected:
149     RefCounted() { }
150     ~RefCounted()
151     {
152     }
153 };
154
155 } // namespace WTF
156
157 using WTF::RefCounted;