tizen beta release
[framework/web/wrt-commons.git] / modules / core / include / dpl / shared_ptr.h
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file        shared_ptr.h
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version     1.0
20  * @brief       This file is the implementation file of shared pointer RAII
21  */
22 #ifndef DPL_SHARED_PTR_H
23 #define DPL_SHARED_PTR_H
24
25 #include <dpl/noncopyable.h>
26 #include <dpl/atomic.h>
27 #include <dpl/bool_operator.h>
28 #include <cstddef>
29 #include <dpl/assert.h>
30
31 namespace DPL
32 {
33 struct StaticPointerCastTag {};
34 struct ConstPointerCastTag {};
35 struct DynamicPointerCastTag {};
36
37 struct SharedCounter
38 {
39     SharedCounter()
40         : ref(1)
41     {
42     }
43
44     Atomic ref;
45 };
46
47 template<typename Class>
48 class EnableSharedFromThis;
49
50 template<typename Other>
51 inline void _Internal_AcceptSharedPtr(SharedCounter *counter, Other *other, EnableSharedFromThis<Other> *otherBase)
52 {
53     otherBase->_Internal_AcceptSharedPtr(counter, other);
54 }
55
56 struct AnyPointer
57 {
58     template<typename Other>
59     AnyPointer(Other *)
60     {        
61     }
62 };
63
64 inline void _Internal_AcceptSharedPtr(SharedCounter *, AnyPointer, AnyPointer)
65 {
66 }
67
68 template<typename Class>
69 class SharedPtr
70 {
71 public:
72     typedef Class ValueType;
73     typedef SharedPtr<Class> ThisType;
74
75 private:
76     SharedCounter *m_counter;
77     Class *m_ptr;
78
79     void AttachCounter(const SharedCounter *counter)
80     {
81         // Attention: R-Value const cast
82         m_counter = const_cast<SharedCounter *>(counter);
83
84         if (m_counter != NULL)
85             ++m_counter->ref;
86     }
87
88     void DetachCounter()
89     {
90         if (m_counter)
91         {
92             if (!--m_counter->ref)
93             {
94                 delete m_ptr;
95                 delete m_counter;
96             }
97
98             m_counter = NULL;
99             m_ptr = NULL;
100         }
101     }
102
103 public:
104     SharedPtr()
105         : m_counter(NULL),
106           m_ptr(NULL)
107     {
108     }
109
110     explicit SharedPtr(Class *ptr)
111         : m_counter(NULL),
112           m_ptr(ptr)
113     {
114         if (m_ptr != NULL)
115         {
116             m_counter = new SharedCounter();
117             _Internal_AcceptSharedPtr(m_counter, m_ptr, m_ptr);
118         }
119     }
120
121     SharedPtr(const SharedPtr &other)
122         : m_counter(NULL),
123           m_ptr(other.m_ptr)
124     {
125         AttachCounter(other.m_counter);
126     }
127
128     SharedPtr(SharedCounter *counter, Class *ptr)
129         : m_counter(NULL),
130           m_ptr(ptr)
131     {
132         AttachCounter(counter);
133     }
134
135     template<typename Other>
136     friend class SharedPtr;
137
138     template<typename Other>
139     SharedPtr(const SharedPtr<Other> &other, const StaticPointerCastTag &)
140         : m_counter(NULL),
141           m_ptr(NULL)
142     {
143         m_ptr = static_cast<Class *>(other.m_ptr);
144         AttachCounter(other.m_counter);
145     }
146
147     template<typename Other>
148     SharedPtr(const SharedPtr<Other> &other, const ConstPointerCastTag &)
149         : m_counter(NULL),
150           m_ptr(NULL)
151     {
152         m_ptr = const_cast<Class *>(other.m_ptr);
153         AttachCounter(other.m_counter);
154     }
155
156     template<typename Other>
157     SharedPtr(const SharedPtr<Other> &other, const DynamicPointerCastTag &)
158         : m_counter(NULL),
159           m_ptr(NULL)
160     {
161         Class *ptr = dynamic_cast<Class *>(other.Get());
162
163         if (ptr == NULL)
164             return;
165
166         m_ptr = ptr;
167         AttachCounter(other.m_counter);
168     }
169
170     virtual ~SharedPtr()
171     {
172         DetachCounter();
173     }
174
175     Class *Get() const
176     {
177         return m_counter == NULL ? NULL : m_ptr;
178     }
179
180     Class *operator->() const
181     {
182         Assert(m_counter != NULL && "Dereference of shared NULL pointer!");
183         return m_ptr;
184     }
185
186     Class &operator *() const
187     {
188         Assert(m_counter != NULL && "Dereference of shared NULL pointer!");
189         return *m_ptr;
190     }
191
192     void Reset(Class *ptr = NULL)
193     {
194         DetachCounter();
195
196         if (ptr != NULL)
197         {
198             m_ptr = ptr;
199             m_counter = new SharedCounter();
200             _Internal_AcceptSharedPtr(m_counter, m_ptr, m_ptr);
201         }
202     }
203
204     SharedPtr &operator=(const SharedPtr &other)
205     {
206         if (this != &other)
207         {
208             DetachCounter();
209             m_ptr = other.m_ptr;
210             AttachCounter(other.m_counter);
211         }
212
213         return *this;
214     }
215
216     Atomic::ValueType GetUseCount() const
217     {
218         if (m_counter == NULL)
219             return Atomic::ValueType(0);
220
221         return m_counter->ref;
222     }
223
224     DPL_IMPLEMENT_BOOL_OPERATOR(ValueType, ThisType, m_counter, m_ptr)
225 };
226
227 template<typename Target, typename Source>
228 SharedPtr<Target> StaticPointerCast(const SharedPtr<Source> &ptr)
229 {
230     return SharedPtr<Target>(ptr, StaticPointerCastTag());
231 }
232
233 template<typename Target, typename Source>
234 SharedPtr<Target> ConstPointerCast(const SharedPtr<Source> &ptr)
235 {
236     return SharedPtr<Target>(ptr, ConstPointerCastTag());
237 }
238
239 template<typename Target, typename Source>
240 SharedPtr<Target> DynamicPointerCast(const SharedPtr<Source> &ptr)
241 {
242     return SharedPtr<Target>(ptr, DynamicPointerCastTag());
243 }
244
245 template<typename First, typename Second>
246 inline bool operator ==(const SharedPtr<First> &first, const SharedPtr<Second> &second)
247 {
248     return first.Get() == second.Get();
249 }
250
251 template<typename First, typename Second>
252 inline bool operator !=(const SharedPtr<First> &first, const SharedPtr<Second> &second)
253 {
254     return first.Get() != second.Get();
255 }
256
257 template<typename First, typename Second>
258 inline bool operator <(const SharedPtr<First> &first, const SharedPtr<Second> &second)
259 {
260     return first.Get() < second.Get();
261 }
262 template<typename First, typename Second>
263 inline bool operator >(const SharedPtr<First> &first, const SharedPtr<Second> &second)
264 {
265     return first.Get() > second.Get();
266 }
267
268 template<typename First, typename Second>
269 inline bool operator <=(const SharedPtr<First> &first, const SharedPtr<Second> &second)
270 {
271     return first.Get() <= second.Get();
272 }
273
274 template<typename First, typename Second>
275 inline bool operator >=(const SharedPtr<First> &first, const SharedPtr<Second> &second)
276 {
277     return first.Get() >= second.Get();
278 }
279
280 } // namespace DPL
281
282 #endif // DPL_SHARED_PTR_H