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 (at) 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: 35 RefObj (): _ref_count(0) {} // derived class must set to SmartPtr at birth 36 virtual ~RefObj () {} 37 38 void ref() const { 39 ++_ref_count; 40 } 41 uint32_t unref() const { 42 return --_ref_count; 43 } 44 virtual bool is_a_object () const { 45 return true; 46 } 47 48 private: 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: 60 RefCount () : RefObj (1) {} 61 virtual bool is_a_object () const { 62 return false; 63 } 64 }; 65 66 template<typename Obj> 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> 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) 86 : _ptr (obj), _ref(NULL) 87 { 88 if (obj) 89 init_ref (obj); 90 } 91 92 template <typename ObjDerive> 93 SmartPtr (ObjDerive *obj) 94 : _ptr (obj), _ref(NULL) 95 { 96 if (obj) 97 init_ref (obj); 98 } 99 100 // copy from pointer 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> 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 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 155 Obj *ptr() const { 156 return _ptr; 157 } 158 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> 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> 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> 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