You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
5.5 KiB
244 lines
5.5 KiB
/*
|
|
* 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 <feng.yuan@intel.com>
|
|
*/
|
|
#ifndef XCAM_SMARTPTR_H
|
|
#define XCAM_SMARTPTR_H
|
|
|
|
#include <base/xcam_defs.h>
|
|
#include <stdint.h>
|
|
|
|
#include <atomic>
|
|
#include <cassert>
|
|
#include <iostream>
|
|
#include <type_traits>
|
|
|
|
namespace XCam {
|
|
|
|
#ifndef M_Assert
|
|
#ifndef NDEBUG
|
|
# define M_Assert(Expr, Msg) \
|
|
__M_Assert(#Expr, Expr, __FILE__, __LINE__, Msg)
|
|
#else
|
|
# define M_Assert(Expr, Msg) ;
|
|
#endif
|
|
#endif
|
|
|
|
static void __M_Assert(const char* expr_str, bool expr, const char* file, int line, const char* msg)
|
|
{
|
|
if (!expr)
|
|
{
|
|
std::cerr << "Assert failed:\t" << msg << "\n"
|
|
<< "Expected:\t" << expr_str << "\n"
|
|
<< "Source:\t\t" << file << ", line " << line << "\n";
|
|
abort();
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
M_Assert(obj != nullptr, "smartptr generate_ref_count failed\n");
|
|
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();
|
|
M_Assert(_ptr != nullptr, "smartptr copy from pointer failed\n");
|
|
}
|
|
}
|
|
|
|
template <typename ObjDerive>
|
|
SmartPtr (const SmartPtr<ObjDerive> &obj)
|
|
: _ptr(obj._ptr), _ref(obj._ref)
|
|
{
|
|
if (_ref) {
|
|
_ref->ref();
|
|
M_Assert(_ptr != nullptr, "smartptr copy from derived pointer failed\n");
|
|
}
|
|
}
|
|
|
|
~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;
|
|
|
|
M_Assert(_ref != nullptr, "smartptr release ref failed\n");
|
|
if (!_ref->unref()) {
|
|
if (!_ref->is_a_object ()) {
|
|
M_Assert(dynamic_cast<RefCount*>(_ref), "smartptr release dcast obj failed\n");
|
|
delete _ref;
|
|
} else {
|
|
M_Assert(dynamic_cast<Obj*>(_ref) == _ptr, "smartptr release dcast obj failed\n");
|
|
}
|
|
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());
|
|
M_Assert(_ref != nullptr, "smartptr init_ref failed\n");
|
|
}
|
|
|
|
private:
|
|
Obj *_ptr;
|
|
mutable RefObj *_ref;
|
|
};
|
|
|
|
} // end namespace
|
|
#endif //XCAM_SMARTPTR_H
|