"L. Spiro Engine"

F:/My Projects/LSEngine/Modules/LSTL/Src/SharedPtr/LSTLSharedPtr.h

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__
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator