| /* |
| * xcam_SmartPtr.h - start pointer |
| * |
| * Copyright (c) 2014 Intel Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| * Author: Wind Yuan <[email protected]> |
| */ |
| #ifndef XCAM_SMARTPTR_H |
| #define XCAM_SMARTPTR_H |
| |
| #include <stdint.h> |
| #include <atomic> |
| #include <type_traits> |
| #include <base/xcam_defs.h> |
| |
| namespace XCam { |
| |
| class RefCount; |
| |
| class RefObj { |
| friend class RefCount; |
| public: |
| RefObj (): _ref_count(0) {} // derived class must set to SmartPtr at birth |
| virtual ~RefObj () {} |
| |
| void ref() const { |
| ++_ref_count; |
| } |
| uint32_t unref() const { |
| return --_ref_count; |
| } |
| virtual bool is_a_object () const { |
| return true; |
| } |
| |
| private: |
| explicit RefObj (uint32_t i) : _ref_count (i) {} |
| XCAM_DEAD_COPY (RefObj); |
| |
| private: |
| mutable std::atomic<uint32_t> _ref_count; |
| }; |
| |
| class RefCount |
| : public RefObj |
| { |
| public: |
| RefCount () : RefObj (1) {} |
| virtual bool is_a_object () const { |
| return false; |
| } |
| }; |
| |
| template<typename Obj> |
| RefObj* generate_ref_count (Obj *obj, std::true_type) |
| { |
| XCAM_ASSERT (obj); |
| obj->ref (); |
| return obj; |
| } |
| |
| template<typename Obj> |
| RefCount* generate_ref_count (Obj *, std::false_type) |
| { |
| return new RefCount; |
| } |
| |
| template <typename Obj> |
| class SmartPtr { |
| private: |
| template<typename ObjDerive> friend class SmartPtr; |
| public: |
| SmartPtr (Obj *obj = NULL) |
| : _ptr (obj), _ref(NULL) |
| { |
| if (obj) |
| init_ref (obj); |
| } |
| |
| template <typename ObjDerive> |
| SmartPtr (ObjDerive *obj) |
| : _ptr (obj), _ref(NULL) |
| { |
| if (obj) |
| init_ref (obj); |
| } |
| |
| // copy from pointer |
| SmartPtr (const SmartPtr<Obj> &obj) |
| : _ptr(obj._ptr), _ref(obj._ref) |
| { |
| if (_ref) { |
| _ref->ref(); |
| XCAM_ASSERT (_ptr); |
| } |
| } |
| |
| template <typename ObjDerive> |
| SmartPtr (const SmartPtr<ObjDerive> &obj) |
| : _ptr(obj._ptr), _ref(obj._ref) |
| { |
| if (_ref) { |
| _ref->ref(); |
| XCAM_ASSERT (_ptr); |
| } |
| } |
| |
| ~SmartPtr () { |
| release(); |
| } |
| |
| /* operator = */ |
| SmartPtr<Obj> & operator = (Obj *obj) { |
| release (); |
| set_pointer (obj, NULL); |
| return *this; |
| } |
| |
| template <typename ObjDerive> |
| SmartPtr<Obj> & operator = (ObjDerive *obj) { |
| release (); |
| set_pointer (obj, NULL); |
| return *this; |
| } |
| |
| SmartPtr<Obj> & operator = (const SmartPtr<Obj> &obj) { |
| release (); |
| set_pointer (obj._ptr, obj._ref); |
| return *this; |
| } |
| |
| template <typename ObjDerive> |
| SmartPtr<Obj> & operator = (const SmartPtr<ObjDerive> &obj) { |
| release (); |
| set_pointer (obj._ptr, obj._ref); |
| return *this; |
| } |
| |
| Obj *operator -> () const { |
| return _ptr; |
| } |
| |
| Obj *ptr() const { |
| return _ptr; |
| } |
| |
| void release() { |
| if (!_ptr) |
| return; |
| |
| XCAM_ASSERT (_ref); |
| if (!_ref->unref()) { |
| if (!_ref->is_a_object ()) { |
| XCAM_ASSERT (dynamic_cast<RefCount*>(_ref)); |
| delete _ref; |
| } else { |
| XCAM_ASSERT (dynamic_cast<Obj*>(_ref) == _ptr); |
| } |
| delete _ptr; |
| } |
| _ptr = NULL; |
| _ref = NULL; |
| } |
| |
| template <typename ObjDerive> |
| SmartPtr<ObjDerive> dynamic_cast_ptr () const { |
| SmartPtr<ObjDerive> ret(NULL); |
| ObjDerive *obj_derive(NULL); |
| if (!_ref) |
| return ret; |
| obj_derive = dynamic_cast<ObjDerive*>(_ptr); |
| if (!obj_derive) |
| return ret; |
| ret.set_pointer (obj_derive, _ref); |
| return ret; |
| } |
| |
| private: |
| template <typename ObjD> |
| void set_pointer (ObjD *obj, RefObj *ref) { |
| if (!obj) |
| return; |
| |
| _ptr = obj; |
| if (ref) { |
| _ref = ref; |
| _ref->ref(); |
| } else { |
| init_ref (obj); |
| } |
| } |
| |
| template <typename ObjD> |
| void init_ref (ObjD *obj) |
| { |
| // consider is_base_of or dynamic_cast ? |
| typedef std::is_base_of<RefObj, ObjD> BaseCheck; |
| _ref = generate_ref_count (obj, BaseCheck()); |
| XCAM_ASSERT (_ref); |
| } |
| |
| private: |
| Obj *_ptr; |
| mutable RefObj *_ref; |
| }; |
| |
| }; // end namespace |
| #endif //XCAM_SMARTPTR_H |