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.
209 lines
4.3 KiB
209 lines
4.3 KiB
//////////////////////////////////////////////////////////////////// |
|
// SharedPtr.h |
|
// |
|
// Copyright 2007 cDc@seacave |
|
// Distributed under the Boost Software License, Version 1.0 |
|
// (See http://www.boost.org/LICENSE_1_0.txt) |
|
|
|
#ifndef __SEACAVE_SHAREDPTR_H__ |
|
#define __SEACAVE_SHAREDPTR_H__ |
|
|
|
|
|
// I N C L U D E S ///////////////////////////////////////////////// |
|
|
|
|
|
|
|
// D E F I N E S /////////////////////////////////////////////////// |
|
|
|
|
|
namespace SEACAVE { |
|
|
|
// S T R U C T S /////////////////////////////////////////////////// |
|
|
|
/************************************************************************************** |
|
* CSharedPtr template |
|
* --------------- |
|
* shared smart pointer |
|
**************************************************************************************/ |
|
|
|
template<class TYPE> |
|
struct SharedRef { |
|
typedef TYPE TYPE_REF; |
|
|
|
#ifdef SEACAVE_NO_MULTITHREAD |
|
TYPE_REF val; |
|
#else |
|
volatile TYPE_REF val; |
|
#endif |
|
|
|
inline SharedRef() {} |
|
inline SharedRef(TYPE_REF v) : val(v) {} |
|
|
|
inline TYPE_REF Inc() { |
|
#ifdef SEACAVE_NO_MULTITHREAD |
|
ASSERT(val >= 0); |
|
return ++val; |
|
#else |
|
return Thread::safeInc(val); |
|
#endif |
|
} |
|
inline TYPE_REF Dec() { |
|
#ifdef SEACAVE_NO_MULTITHREAD |
|
ASSERT(val > 0); |
|
return --val; |
|
#else |
|
return Thread::safeDec(val); |
|
#endif |
|
} |
|
|
|
#ifdef _USE_BOOST |
|
// serialize |
|
template <class Archive> |
|
void serialize(Archive& ar, const unsigned int /*version*/) { |
|
#ifdef SEACAVE_NO_MULTITHREAD |
|
ar & val; |
|
#else |
|
ar & (TYPE_REF&)val; |
|
#endif |
|
} |
|
#endif |
|
}; |
|
/*----------------------------------------------------------------*/ |
|
|
|
|
|
template<class TYPE> |
|
class CSharedPtr |
|
{ |
|
protected: |
|
typedef SharedRef<int32_t> TYPE_REF; |
|
typedef TYPE* TYPE_PTR; |
|
|
|
public: |
|
inline CSharedPtr() : m_pointer(NULL), m_pNoRef(NULL) |
|
{ // empty construct |
|
} |
|
|
|
inline explicit CSharedPtr(TYPE_PTR _Ptr) : m_pointer(_Ptr), m_pNoRef(_Ptr ? new TYPE_REF(1) : NULL) |
|
{ // construct from object pointer |
|
} |
|
|
|
inline CSharedPtr(const CSharedPtr& _Right) : m_pointer(_Right.m_pointer), m_pNoRef(_Right.m_pNoRef) |
|
{ // construct by assuming pointer from _Right CSharedPtr |
|
IncRef(); |
|
} |
|
|
|
inline ~CSharedPtr() |
|
{ // destroy the object |
|
DecRef(); |
|
} |
|
|
|
CSharedPtr& operator=(const CSharedPtr& _Right) |
|
{ // assign compatible _Right (assume pointer) |
|
if (this != &_Right) |
|
{ |
|
ASSERT(m_pointer != _Right.m_pointer || m_pNoRef == _Right.m_pNoRef); |
|
DecRef(); |
|
m_pointer = _Right.m_pointer; |
|
m_pNoRef = _Right.m_pNoRef; |
|
IncRef(); |
|
} |
|
return (*this); |
|
} |
|
|
|
CSharedPtr& operator=(TYPE_PTR _Ptr) |
|
{ // assign compatible _Right (assume pointer) |
|
if (m_pointer != _Ptr) |
|
{ |
|
DecRef(); |
|
m_pointer = _Ptr; |
|
m_pNoRef = (_Ptr ? new TYPE_REF(1) : NULL); |
|
} |
|
return (*this); |
|
} |
|
|
|
inline TYPE& operator*() const |
|
{ // return designated value |
|
ASSERT(m_pointer); |
|
return (*m_pointer); |
|
} |
|
|
|
inline TYPE* operator->() const |
|
{ // return pointer to class object |
|
ASSERT(m_pointer); |
|
return m_pointer; |
|
} |
|
|
|
inline operator TYPE_PTR() const |
|
{ // return pointer to class object |
|
return m_pointer; |
|
} |
|
|
|
inline bool operator==(const CSharedPtr& _Right) const |
|
{ // return pointer to class object |
|
return (m_pointer == _Right.m_pointer); |
|
} |
|
|
|
inline bool operator!=(const CSharedPtr& _Right) const |
|
{ // return pointer to class object |
|
return (m_pointer != _Right.m_pointer); |
|
} |
|
|
|
inline bool operator==(const void* _Right) const |
|
{ // return pointer to class object |
|
return (m_pointer == _Right); |
|
} |
|
|
|
inline bool operator!=(const void* _Right) const |
|
{ // return pointer to class object |
|
return (m_pointer != _Right); |
|
} |
|
|
|
void Release() |
|
{ // release pointer |
|
DecRef(); |
|
m_pointer = NULL; |
|
m_pNoRef = NULL; |
|
} |
|
|
|
protected: |
|
inline void IncRef() |
|
{ |
|
if (m_pointer == NULL) |
|
return; |
|
ASSERT(m_pNoRef); |
|
m_pNoRef->Inc(); |
|
} |
|
|
|
inline void DecRef() |
|
{ |
|
if (m_pointer == NULL) |
|
return; |
|
ASSERT(m_pNoRef); |
|
if (m_pNoRef->Dec() == 0) |
|
{ |
|
delete m_pointer; |
|
m_pointer = NULL; |
|
delete m_pNoRef; |
|
m_pNoRef = NULL; |
|
} |
|
} |
|
|
|
TYPE_PTR m_pointer; // the wrapped object pointer |
|
TYPE_REF* m_pNoRef; // number of references to this pointer |
|
|
|
#ifdef _USE_BOOST |
|
protected: |
|
// implement BOOST serialization |
|
friend class boost::serialization::access; |
|
template <class Archive> |
|
void serialize(Archive& ar, const unsigned int /*version*/) { |
|
ar & m_pointer; |
|
ar & m_pNoRef; |
|
} |
|
#endif |
|
}; |
|
/*----------------------------------------------------------------*/ |
|
|
|
} // namespace SEACAVE |
|
|
|
#endif // __SEACAVE_SHAREDPTR_H__
|
|
|