• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * xcam_SmartPtr.h - start pointer
3  *
4  *  Copyright (c) 2014 Intel Corporation
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Author: Wind Yuan <feng.yuan@intel.com>
19  */
20 #ifndef XCAM_SMARTPTR_H
21 #define XCAM_SMARTPTR_H
22 
23 #include <stdint.h>
24 #include <atomic>
25 #include <type_traits>
26 #include <base/xcam_defs.h>
27 
28 namespace XCam {
29 
30 class RefCount;
31 
32 class RefObj {
33     friend class RefCount;
34 public:
RefObj()35     RefObj (): _ref_count(0) {} // derived class must set to SmartPtr at birth
~RefObj()36     virtual ~RefObj () {}
37 
ref()38     void ref() const {
39         ++_ref_count;
40     }
unref()41     uint32_t unref() const {
42         return --_ref_count;
43     }
is_a_object()44     virtual bool is_a_object () const {
45         return true;
46     }
47 
48 private:
RefObj(uint32_t i)49     explicit RefObj (uint32_t i) : _ref_count (i) {}
50     XCAM_DEAD_COPY (RefObj);
51 
52 private:
53     mutable std::atomic<uint32_t>  _ref_count;
54 };
55 
56 class RefCount
57     : public RefObj
58 {
59 public:
RefCount()60     RefCount () : RefObj (1) {}
is_a_object()61     virtual bool is_a_object () const {
62         return false;
63     }
64 };
65 
66 template<typename Obj>
generate_ref_count(Obj * obj,std::true_type)67 RefObj* generate_ref_count (Obj *obj, std::true_type)
68 {
69     XCAM_ASSERT (obj);
70     obj->ref ();
71     return obj;
72 }
73 
74 template<typename Obj>
generate_ref_count(Obj *,std::false_type)75 RefCount* generate_ref_count (Obj *, std::false_type)
76 {
77     return new RefCount;
78 }
79 
80 template <typename Obj>
81 class SmartPtr {
82 private:
83     template<typename ObjDerive> friend class SmartPtr;
84 public:
85     SmartPtr (Obj *obj = NULL)
_ptr(obj)86         : _ptr (obj), _ref(NULL)
87     {
88         if (obj)
89             init_ref (obj);
90     }
91 
92     template <typename ObjDerive>
SmartPtr(ObjDerive * obj)93     SmartPtr (ObjDerive *obj)
94         : _ptr (obj), _ref(NULL)
95     {
96         if (obj)
97             init_ref (obj);
98     }
99 
100     // copy from pointer
SmartPtr(const SmartPtr<Obj> & obj)101     SmartPtr (const SmartPtr<Obj> &obj)
102         : _ptr(obj._ptr), _ref(obj._ref)
103     {
104         if (_ref) {
105             _ref->ref();
106             XCAM_ASSERT (_ptr);
107         }
108     }
109 
110     template <typename ObjDerive>
SmartPtr(const SmartPtr<ObjDerive> & obj)111     SmartPtr (const SmartPtr<ObjDerive> &obj)
112         : _ptr(obj._ptr), _ref(obj._ref)
113     {
114         if (_ref) {
115             _ref->ref();
116             XCAM_ASSERT (_ptr);
117         }
118     }
119 
~SmartPtr()120     ~SmartPtr () {
121         release();
122     }
123 
124     /* operator = */
125     SmartPtr<Obj> & operator = (Obj *obj) {
126         release ();
127         set_pointer (obj, NULL);
128         return *this;
129     }
130 
131     template <typename ObjDerive>
132     SmartPtr<Obj> & operator = (ObjDerive *obj) {
133         release ();
134         set_pointer (obj, NULL);
135         return *this;
136     }
137 
138     SmartPtr<Obj> & operator = (const SmartPtr<Obj> &obj) {
139         release ();
140         set_pointer (obj._ptr, obj._ref);
141         return *this;
142     }
143 
144     template <typename ObjDerive>
145     SmartPtr<Obj> & operator = (const SmartPtr<ObjDerive> &obj) {
146         release ();
147         set_pointer (obj._ptr, obj._ref);
148         return *this;
149     }
150 
151     Obj *operator -> () const {
152         return _ptr;
153     }
154 
ptr()155     Obj *ptr() const {
156         return _ptr;
157     }
158 
release()159     void release() {
160         if (!_ptr)
161             return;
162 
163         XCAM_ASSERT (_ref);
164         if (!_ref->unref()) {
165             if (!_ref->is_a_object ()) {
166                 XCAM_ASSERT (dynamic_cast<RefCount*>(_ref));
167                 delete _ref;
168             } else {
169                 XCAM_ASSERT (dynamic_cast<Obj*>(_ref) == _ptr);
170             }
171             delete _ptr;
172         }
173         _ptr = NULL;
174         _ref = NULL;
175     }
176 
177     template <typename ObjDerive>
dynamic_cast_ptr()178     SmartPtr<ObjDerive> dynamic_cast_ptr () const {
179         SmartPtr<ObjDerive> ret(NULL);
180         ObjDerive *obj_derive(NULL);
181         if (!_ref)
182             return ret;
183         obj_derive = dynamic_cast<ObjDerive*>(_ptr);
184         if (!obj_derive)
185             return ret;
186         ret.set_pointer (obj_derive, _ref);
187         return ret;
188     }
189 
190 private:
191     template <typename ObjD>
set_pointer(ObjD * obj,RefObj * ref)192     void set_pointer (ObjD *obj, RefObj *ref) {
193         if (!obj)
194             return;
195 
196         _ptr = obj;
197         if (ref) {
198             _ref = ref;
199             _ref->ref();
200         } else {
201             init_ref (obj);
202         }
203     }
204 
205     template <typename ObjD>
init_ref(ObjD * obj)206     void init_ref (ObjD *obj)
207     {
208         // consider is_base_of or dynamic_cast ?
209         typedef std::is_base_of<RefObj, ObjD> BaseCheck;
210         _ref = generate_ref_count (obj, BaseCheck());
211         XCAM_ASSERT (_ref);
212     }
213 
214 private:
215     Obj              *_ptr;
216     mutable RefObj   *_ref;
217 };
218 
219 }; // end namespace
220 #endif //XCAM_SMARTPTR_H