merge with master
[platform/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 <stddef.h>
29 #include <dpl/assert.h>
30
31 namespace DPL {
32 struct StaticPointerCastTag {};
33 struct ConstPointerCastTag {};
34 struct DynamicPointerCastTag {};
35
36 struct SharedCounter
37 {
38     SharedCounter() :
39         ref(1)
40     {}
41
42     Atomic ref;
43 };
44
45 template<typename Class>
46 class EnableSharedFromThis;
47
48 template<typename Other>
49 inline void _Internal_AcceptSharedPtr(SharedCounter *counter,
50                                       Other *other,
51                                       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 inline void _Internal_AcceptSharedPtr(SharedCounter *, AnyPointer, AnyPointer)
64 {}
65
66 template<typename Class>
67 class SharedPtr
68 {
69   public:
70     typedef Class ValueType;
71     typedef SharedPtr<Class> ThisType;
72
73   private:
74     SharedCounter *m_counter;
75     Class *m_ptr;
76
77     void AttachCounter(const SharedCounter *counter)
78     {
79         // Attention: R-Value const cast
80         m_counter = const_cast<SharedCounter *>(counter);
81
82         if (m_counter != NULL) {
83             ++m_counter->ref;
84         }
85     }
86
87     void DetachCounter()
88     {
89         if (m_counter) {
90             if (!--m_counter->ref) {
91                 delete m_ptr;
92                 delete m_counter;
93             }
94
95             m_counter = NULL;
96             m_ptr = NULL;
97         }
98     }
99
100   public:
101     SharedPtr() :
102         m_counter(NULL),
103         m_ptr(NULL)
104     {}
105
106     explicit SharedPtr(Class *ptr) :
107         m_counter(NULL),
108         m_ptr(ptr)
109     {
110         if (m_ptr != NULL) {
111             m_counter = new SharedCounter();
112             _Internal_AcceptSharedPtr(m_counter, m_ptr, m_ptr);
113         }
114     }
115
116     SharedPtr(const SharedPtr &other) :
117         m_counter(NULL),
118         m_ptr(other.m_ptr)
119     {
120         AttachCounter(other.m_counter);
121     }
122
123     SharedPtr(SharedCounter *counter, Class *ptr) :
124         m_counter(NULL),
125         m_ptr(ptr)
126     {
127         AttachCounter(counter);
128     }
129
130     template<typename Other>
131     friend class SharedPtr;
132
133     template<typename Other>
134     SharedPtr(const SharedPtr<Other> &other, const StaticPointerCastTag &) :
135         m_counter(NULL),
136         m_ptr(NULL)
137     {
138         m_ptr = static_cast<Class *>(other.m_ptr);
139         AttachCounter(other.m_counter);
140     }
141
142     template<typename Other>
143     SharedPtr(const SharedPtr<Other> &other, const ConstPointerCastTag &) :
144         m_counter(NULL),
145         m_ptr(NULL)
146     {
147         m_ptr = const_cast<Class *>(other.m_ptr);
148         AttachCounter(other.m_counter);
149     }
150
151     template<typename Other>
152     SharedPtr(const SharedPtr<Other> &other, const DynamicPointerCastTag &) :
153         m_counter(NULL),
154         m_ptr(NULL)
155     {
156         Class *ptr = dynamic_cast<Class *>(other.Get());
157
158         if (ptr == NULL) {
159             return;
160         }
161
162         m_ptr = ptr;
163         AttachCounter(other.m_counter);
164     }
165
166     virtual ~SharedPtr()
167     {
168         DetachCounter();
169     }
170
171     Class *Get() const
172     {
173         return m_counter == NULL ? NULL : m_ptr;
174     }
175
176     Class *operator->() const
177     {
178         Assert(m_counter != NULL && "Dereference of shared NULL pointer!");
179         return m_ptr;
180     }
181
182     Class &operator *() const
183     {
184         Assert(m_counter != NULL && "Dereference of shared NULL pointer!");
185         return *m_ptr;
186     }
187
188     void Reset(Class *ptr = NULL)
189     {
190         DetachCounter();
191
192         if (ptr != NULL) {
193             m_ptr = ptr;
194             m_counter = new SharedCounter();
195             _Internal_AcceptSharedPtr(m_counter, m_ptr, m_ptr);
196         }
197     }
198
199     SharedPtr &operator=(const SharedPtr &other)
200     {
201         if (this != &other) {
202             DetachCounter();
203             m_ptr = other.m_ptr;
204             AttachCounter(other.m_counter);
205         }
206
207         return *this;
208     }
209
210     Atomic::ValueType GetUseCount() const
211     {
212         if (m_counter == NULL) {
213             return Atomic::ValueType(0);
214         }
215
216         return m_counter->ref;
217     }
218
219     DPL_IMPLEMENT_BOOL_OPERATOR(ValueType, ThisType, m_counter, m_ptr)
220 };
221
222 template<typename Target, typename Source>
223 SharedPtr<Target> StaticPointerCast(const SharedPtr<Source> &ptr)
224 {
225     return SharedPtr<Target>(ptr, StaticPointerCastTag());
226 }
227
228 template<typename Target, typename Source>
229 SharedPtr<Target> ConstPointerCast(const SharedPtr<Source> &ptr)
230 {
231     return SharedPtr<Target>(ptr, ConstPointerCastTag());
232 }
233
234 template<typename Target, typename Source>
235 SharedPtr<Target> DynamicPointerCast(const SharedPtr<Source> &ptr)
236 {
237     return SharedPtr<Target>(ptr, DynamicPointerCastTag());
238 }
239
240 template<typename First, typename Second>
241 inline bool operator ==(const SharedPtr<First> &first,
242                         const SharedPtr<Second> &second)
243 {
244     return first.Get() == second.Get();
245 }
246
247 template<typename First, typename Second>
248 inline bool operator !=(const SharedPtr<First> &first,
249                         const SharedPtr<Second> &second)
250 {
251     return first.Get() != second.Get();
252 }
253
254 template<typename First, typename Second>
255 inline bool operator <(const SharedPtr<First> &first,
256                        const SharedPtr<Second> &second)
257 {
258     return first.Get() < second.Get();
259 }
260 template<typename First, typename Second>
261 inline bool operator >(const SharedPtr<First> &first,
262                        const SharedPtr<Second> &second)
263 {
264     return first.Get() > second.Get();
265 }
266
267 template<typename First, typename Second>
268 inline bool operator <=(const SharedPtr<First> &first,
269                         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,
276                         const SharedPtr<Second> &second)
277 {
278     return first.Get() >= second.Get();
279 }
280 } // namespace DPL
281
282 #endif // DPL_SHARED_PTR_H