xref: /OK3568_Linux_fs/external/camera_engine_rkaiq/rkaiq/xcore/smartptr.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 <base/xcam_defs.h>
24 #include <stdint.h>
25 
26 #include <atomic>
27 #include <cassert>
28 #include <iostream>
29 #include <type_traits>
30 
31 namespace XCam {
32 
33 #ifndef M_Assert
34 #ifndef NDEBUG
35 #   define M_Assert(Expr, Msg) \
36     __M_Assert(#Expr, Expr, __FILE__, __LINE__, Msg)
37 #else
38 #   define M_Assert(Expr, Msg) ;
39 #endif
40 #endif
41 
__M_Assert(const char * expr_str,bool expr,const char * file,int line,const char * msg)42 static void __M_Assert(const char* expr_str, bool expr, const char* file, int line, const char* msg)
43 {
44     if (!expr)
45     {
46         std::cerr << "Assert failed:\t" << msg << "\n"
47             << "Expected:\t" << expr_str << "\n"
48             << "Source:\t\t" << file << ", line " << line << "\n";
49         abort();
50     }
51 }
52 
53 class RefCount;
54 
55 class RefObj {
56     friend class RefCount;
57 public:
RefObj()58     RefObj (): _ref_count(0) {} // derived class must set to SmartPtr at birth
~RefObj()59     virtual ~RefObj () {}
60 
ref()61     void ref() const {
62         ++_ref_count;
63     }
unref()64     uint32_t unref() const {
65         return --_ref_count;
66     }
is_a_object()67     virtual bool is_a_object () const {
68         return true;
69     }
70 
71 private:
RefObj(uint32_t i)72     explicit RefObj (uint32_t i) : _ref_count (i) {}
73     XCAM_DEAD_COPY (RefObj);
74 
75 private:
76     mutable std::atomic<uint32_t>  _ref_count;
77 };
78 
79 class RefCount
80     : public RefObj
81 {
82 public:
RefCount()83     RefCount () : RefObj (1) {}
is_a_object()84     virtual bool is_a_object () const {
85         return false;
86     }
87 };
88 
89 template<typename Obj>
generate_ref_count(Obj * obj,std::true_type)90 RefObj* generate_ref_count (Obj *obj, std::true_type)
91 {
92     M_Assert(obj != nullptr, "smartptr generate_ref_count failed\n");
93     obj->ref ();
94     return obj;
95 }
96 
97 template<typename Obj>
generate_ref_count(Obj *,std::false_type)98 RefCount* generate_ref_count (Obj *, std::false_type)
99 {
100     return new RefCount;
101 }
102 
103 template <typename Obj>
104 class SmartPtr {
105 private:
106     template<typename ObjDerive> friend class SmartPtr;
107 public:
108     SmartPtr (Obj *obj = NULL)
_ptr(obj)109         : _ptr (obj), _ref(NULL)
110     {
111         if (obj)
112             init_ref (obj);
113     }
114 
115     template <typename ObjDerive>
SmartPtr(ObjDerive * obj)116     SmartPtr (ObjDerive *obj)
117         : _ptr (obj), _ref(NULL)
118     {
119         if (obj)
120             init_ref (obj);
121     }
122 
123     // copy from pointer
SmartPtr(const SmartPtr<Obj> & obj)124     SmartPtr (const SmartPtr<Obj> &obj)
125         : _ptr(obj._ptr), _ref(obj._ref)
126     {
127         if (_ref) {
128             _ref->ref();
129             M_Assert(_ptr != nullptr, "smartptr copy from pointer failed\n");
130         }
131     }
132 
133     template <typename ObjDerive>
SmartPtr(const SmartPtr<ObjDerive> & obj)134     SmartPtr (const SmartPtr<ObjDerive> &obj)
135         : _ptr(obj._ptr), _ref(obj._ref)
136     {
137         if (_ref) {
138             _ref->ref();
139             M_Assert(_ptr != nullptr, "smartptr copy from derived pointer failed\n");
140         }
141     }
142 
~SmartPtr()143     ~SmartPtr () {
144         release();
145     }
146 
147     /* operator = */
148     SmartPtr<Obj> & operator = (Obj *obj) {
149         release ();
150         set_pointer (obj, NULL);
151         return *this;
152     }
153 
154     template <typename ObjDerive>
155     SmartPtr<Obj> & operator = (ObjDerive *obj) {
156         release ();
157         set_pointer (obj, NULL);
158         return *this;
159     }
160 
161     SmartPtr<Obj> & operator = (const SmartPtr<Obj> &obj) {
162         release ();
163         set_pointer (obj._ptr, obj._ref);
164         return *this;
165     }
166 
167     template <typename ObjDerive>
168     SmartPtr<Obj> & operator = (const SmartPtr<ObjDerive> &obj) {
169         release ();
170         set_pointer (obj._ptr, obj._ref);
171         return *this;
172     }
173 
174     Obj *operator -> () const {
175         return _ptr;
176     }
177 
ptr()178     Obj *ptr() const {
179         return _ptr;
180     }
181 
release()182     void release() {
183         if (!_ptr)
184             return;
185 
186         M_Assert(_ref != nullptr, "smartptr release ref failed\n");
187         if (!_ref->unref()) {
188             if (!_ref->is_a_object ()) {
189                 M_Assert(dynamic_cast<RefCount*>(_ref), "smartptr release dcast obj failed\n");
190                 delete _ref;
191             } else {
192                 M_Assert(dynamic_cast<Obj*>(_ref) == _ptr, "smartptr release dcast obj failed\n");
193             }
194             delete _ptr;
195         }
196         _ptr = NULL;
197         _ref = NULL;
198     }
199 
200     template <typename ObjDerive>
dynamic_cast_ptr()201     SmartPtr<ObjDerive> dynamic_cast_ptr () const {
202         SmartPtr<ObjDerive> ret(NULL);
203         ObjDerive *obj_derive(NULL);
204         if (!_ref)
205             return ret;
206         obj_derive = dynamic_cast<ObjDerive*>(_ptr);
207         if (!obj_derive)
208             return ret;
209         ret.set_pointer (obj_derive, _ref);
210         return ret;
211     }
212 
213     template <typename ObjDerive>
get_cast_ptr()214     ObjDerive* get_cast_ptr () const {
215         ObjDerive *obj_derive(NULL);
216         if (!_ref)
217             return NULL;
218         obj_derive = dynamic_cast<ObjDerive*>(_ptr);
219         if (!obj_derive)
220             return NULL;
221         return obj_derive;
222     }
223 
224 private:
225     template <typename ObjD>
set_pointer(ObjD * obj,RefObj * ref)226     void set_pointer (ObjD *obj, RefObj *ref) {
227         if (!obj)
228             return;
229 
230         _ptr = obj;
231         if (ref) {
232             _ref = ref;
233             _ref->ref();
234         } else {
235             init_ref (obj);
236         }
237     }
238 
239     template <typename ObjD>
init_ref(ObjD * obj)240     void init_ref (ObjD *obj)
241     {
242         // consider is_base_of or dynamic_cast ?
243         typedef std::is_base_of<RefObj, ObjD> BaseCheck;
244         _ref = generate_ref_count (obj, BaseCheck());
245         M_Assert(_ref != nullptr, "smartptr init_ref failed\n");
246     }
247 
248 private:
249     Obj              *_ptr;
250     mutable RefObj   *_ref;
251 };
252 
253 } // end namespace
254 #endif //XCAM_SMARTPTR_H
255