"L. Spiro Engine"
|
00001 00016 #ifndef __LSTL_SHAREDPTR_H__ 00017 #define __LSTL_SHAREDPTR_H__ 00018 00019 #include "../LSTLib.h" 00020 #include "../Allocator/LSTLAllocator.h" 00021 00022 namespace lstl { 00023 00024 // == Enumerations. 00028 enum LSSTL_SHARED_PTR { 00029 LSSTL_SP_MAKE_NEW 00030 }; 00031 00038 template <typename _tType> 00039 class CSharedPtr { 00040 public : 00041 // == Various constructors. 00042 LSE_CALLCTOR CSharedPtr() : 00043 m_pcCont( NULL ), 00044 m_ptDirect( NULL ) { 00045 } 00046 explicit LSE_CALLCTOR CSharedPtr( LSSTL_SHARED_PTR /*_spFlag*/ ) { 00047 // Create a new object with a 1 reference count. 00048 m_pcCont = static_cast<CSharedPtr<_tType>::LSSTL_CONTAINER *>(CMemLib::MNew( NULL, LSSTL_CONTAINER )); 00049 if ( !m_pcCont ) { throw LSSTD_E_OUTOFMEMORY; } 00050 m_pcCont->paAllocator = NULL; 00051 m_pcCont->ui32RefCount = 1UL; 00052 m_ptDirect = &m_pcCont->tObj; 00053 } 00054 explicit LSE_CALLCTOR CSharedPtr( CAllocator * _paAllocator ) { 00055 // Create a new object with a 1 reference count. 00056 m_pcCont = static_cast<CSharedPtr<_tType>::LSSTL_CONTAINER *>(CMemLib::MNew( _paAllocator ? _paAllocator->GetAllocator() : NULL, LSSTL_CONTAINER )); 00057 if ( !m_pcCont ) { throw LSSTD_E_OUTOFMEMORY; } 00058 m_pcCont->paAllocator = _paAllocator; 00059 m_pcCont->ui32RefCount = 1UL; 00060 m_ptDirect = &m_pcCont->tObj; 00061 } 00062 LSE_CALLCTOR CSharedPtr( const CSharedPtr<_tType> &_spOther ) { 00063 // Reference the object to which it points. 00064 m_pcCont = _spOther.m_pcCont; 00065 m_ptDirect = _spOther.m_ptDirect; 00066 if ( m_pcCont ) { 00067 ++m_pcCont->ui32RefCount; 00068 } 00069 } 00070 template <typename _tCastType> 00071 LSE_CALLCTOR CSharedPtr( const CSharedPtr<_tCastType> &_spOther ) { 00072 // Reference the object to which it points. 00073 m_pcCont = const_cast<LSSTL_CONTAINER *>(reinterpret_cast<const LSSTL_CONTAINER *>(_spOther.GetContainer())); 00074 m_ptDirect = const_cast<_tType *>(static_cast<const _tType *>(_spOther.Get())); 00075 if ( m_pcCont ) { 00076 ++m_pcCont->ui32RefCount; 00077 } 00078 } 00079 LSE_CALLCTOR ~CSharedPtr() { 00080 Reset(); 00081 } 00082 00083 00084 // == Types. 00088 typedef struct LSSTL_CONTAINER { 00093 CAllocator * paAllocator; 00094 00098 LSUINT32 ui32RefCount; 00099 00103 _tType tObj; 00104 } * LPLSSTL_CONTAINER, * const LPCLSSTL_CONTAINER; 00105 00106 00107 // == Operators. 00114 CSharedPtr<_tType> & LSE_CALL operator = ( const CSharedPtr<_tType> &_spOther ) { 00115 if ( _spOther.m_pcCont ) { 00116 // Increase their reference count before decreasing ours. 00117 ++_spOther.m_pcCont->ui32RefCount; 00118 } 00119 Reset(); 00120 m_pcCont = _spOther.m_pcCont; 00121 m_ptDirect = _spOther.m_ptDirect; 00122 return (*this); 00123 } 00124 00130 _tType & LSE_CALL operator * () { 00131 return (*Get()); 00132 } 00133 00139 const _tType & LSE_CALL operator * () const { 00140 return (*Get()); 00141 } 00142 00148 _tType * LSE_CALL operator -> () { 00149 return Get(); 00150 } 00151 00157 const _tType * LSE_CALL operator -> () const { 00158 return Get(); 00159 } 00160 00166 LSE_CALL operator LSUINTPTR() const { 00167 return reinterpret_cast<LSUINTPTR>(Get()); 00168 } 00169 00170 00171 // == Functions. 00179 LSBOOL LSE_CALL New() { 00180 CAllocator * paAllocator = NULL; 00181 if ( m_pcCont ) { 00182 paAllocator = m_pcCont->paAllocator; 00183 } 00184 Reset(); 00185 m_pcCont = static_cast<CSharedPtr<_tType>::LSSTL_CONTAINER *>(CMemLib::MNew( paAllocator ? paAllocator->GetAllocator() : NULL, LSSTL_CONTAINER )); 00186 if ( !m_pcCont ) { return false; } 00187 m_pcCont->paAllocator = paAllocator; 00188 m_pcCont->ui32RefCount = 1UL; 00189 m_ptDirect = &m_pcCont->tObj; 00190 return true; 00191 } 00192 00198 _tType * LSE_CALL Get() { 00199 return m_ptDirect; 00200 } 00201 00207 const _tType * LSE_CALL Get() const { 00208 return m_ptDirect; 00209 } 00210 00218 LSUINT32 LSE_CALL RefCount() const { 00219 return m_pcCont ? m_pcCont->ui32RefCount : 0UL; 00220 } 00221 00227 LSBOOL LSE_CALL Valid() const { 00228 return m_pcCont != NULL; 00229 } 00230 00235 LSVOID LSE_CALL Reset() { 00236 if ( m_pcCont ) { 00237 if ( --m_pcCont->ui32RefCount == 0UL ) { 00238 // Delete it. Use the direct pointer to call the destructor. This is the only 00239 // way to get virtual destructors to be called properly in the case that this 00240 // object was a cast of a different type of shared pointer. 00241 m_ptDirect->~_tType(); 00242 if ( m_pcCont->paAllocator ) { 00243 m_pcCont->paAllocator->Free( m_pcCont ); 00244 } 00245 else { 00246 CMemLib::Free( m_pcCont ); 00247 } 00248 } 00249 m_pcCont = NULL; 00250 m_ptDirect = NULL; 00251 } 00252 } 00253 00258 LSVOID LSE_CALL Trash() { 00259 if ( m_pcCont ) { 00260 if ( --m_pcCont->ui32RefCount == 0UL ) { 00261 // Trash it. 00262 m_ptDirect->Trash(); 00263 } 00264 m_pcCont = NULL; 00265 m_ptDirect = NULL; 00266 } 00267 } 00268 00277 const LSSTL_CONTAINER * LSE_CALL 00278 GetContainer() const { 00279 return m_pcCont; 00280 } 00281 00282 00283 protected : 00284 // == Members. 00288 LSSTL_CONTAINER * m_pcCont; 00289 00293 _tType * m_ptDirect; 00294 00295 }; 00296 00297 } // namespace lstl 00298 00299 #endif // __LSTL_SHAREDPTR_H__