etqw-sdk/source/idlib/SmartPtr.h

181 lines
4.9 KiB
C
Raw Normal View History

2008-05-29 00:00:00 +00:00
// Copyright (C) 2007 Id Software, Inc.
//
#ifndef __LIB_SMARTPTR_H__
#define __LIB_SMARTPTR_H__
// this version eats up all instances where T doesn't have GetThisPtr enabled
ID_INLINE void sdDetail_AssignThis( ... ) { }
/*
============
sdSmartPtr
============
*/
#ifdef _DEBUG
template< class T, class CleanupPolicy = sdDefaultCleanupPolicy< T >, class CheckingPolicy = sdNULLPtrCheck< T > >
#else
template< class T, class CleanupPolicy = sdDefaultCleanupPolicy< T >, class CheckingPolicy = sdNoPtrCheck< T > >
#endif
class sdSmartPtr {
public:
typedef T& Reference;
typedef T* Pointer;
typedef const T& ConstReference;
typedef const T* ConstPointer;
typedef CheckingPolicy checkingPolicy;
typedef CleanupPolicy cleanupPolicy;
explicit sdSmartPtr( Pointer p = NULL ) : pointee( p ), isWeak( false ) {
count = GetCountAllocator().Alloc();
*count = 1;
sdDetail_AssignThis( pointee, *this );
}
explicit sdSmartPtr( idNullPtr p ) : pointee( p ), isWeak( false ) {
count = GetCountAllocator().Alloc();
*count = 1;
sdDetail_AssignThis( pointee, *this );
}
sdSmartPtr( const sdSmartPtr& rhs ) :
pointee( rhs.pointee ),
count( rhs.count ),
isWeak( false ) {
if( !isWeak ) {
++( *count );
}
}
~sdSmartPtr() {
if( !isWeak ) {
--( *count );
if( ( *count ) == 0 ) {
cleanupPolicy::Free( pointee );
GetCountAllocator().Free( count );
}
}
count = NULL;
pointee = NULL;
isWeak = true;
}
int Num() const {
return *count;
}
template< class U >
bool friend operator==( const Pointer lhs, const sdSmartPtr< U >& rhs ) { return lhs == rhs.pointee; }
template< class U >
bool friend operator==( const sdSmartPtr< U >& lhs, const Pointer rhs ) { return lhs.pointee == rhs; }
template< class U >
bool friend operator==( const sdSmartPtr< U >& lhs, const sdSmartPtr& rhs ) { return lhs.Get() == rhs.pointee; }
// operator !=
template< class U >
bool friend operator!=( const Pointer lhs, const sdSmartPtr< U >& rhs ) { return lhs != rhs.pointee; }
template< class U >
bool friend operator!=( const sdSmartPtr< U >& lhs, const Pointer rhs ) { return lhs.pointee != rhs; }
template< class U >
bool friend operator!=( const sdSmartPtr& lhs, const sdSmartPtr< U >& rhs ) { return lhs.pointee != rhs.pointee; }
// dereferencing
Pointer operator->() { checkingPolicy::Check( pointee ); return pointee; }
ConstPointer operator->() const { checkingPolicy::Check( pointee ); return pointee; }
Reference operator*() { checkingPolicy::Check( pointee ); return *pointee; }
ConstReference operator*() const { checkingPolicy::Check( pointee ); return *pointee; }
// accessors
Pointer Get() { return pointee; }
const Pointer Get() const { return pointee; }
sdSmartPtr& operator=( const sdSmartPtr& rhs ) {
sdSmartPtr( rhs ).Swap( *this );
return *this;
}
sdSmartPtr& Reset( const Pointer rhs ) {
sdSmartPtr( rhs ).Swap( *this );
return *this;
}
sdSmartPtr& ResetWeak( const sdSmartPtr& rhs ) {
MakeWeak();
assert( count == NULL );
pointee = rhs.pointee;
count = rhs.count;
return *this;
}
void Swap( const sdSmartPtr& rhs ) {
idSwap( isWeak, rhs.isWeak );
idSwap( pointee, const_cast< Pointer >( rhs.pointee ) );
idSwap( count, const_cast< int* >( rhs.count ) );
}
protected:
// we don't support this, use != NULL instead
bool operator!() const;
void MakeWeak() {
assert( pointee == NULL || isWeak );
if( !isWeak ) {
GetCountAllocator().Free( count );
count = NULL;
}
isWeak = true;
}
private:
Pointer pointee;
int* count;
mutable bool isWeak;
typedef idBlockAlloc< int, 64 > countAllocator_t;
static countAllocator_t& GetCountAllocator() {
static countAllocator_t countAllocator;
return countAllocator;
}
};
template< class T, class CleanupPolicy, class CheckingPolicy >
void Swap( const sdSmartPtr< T, CleanupPolicy, CheckingPolicy >& lhs, const sdSmartPtr< T, CleanupPolicy, CheckingPolicy >& rhs ) {
lhs.Swap( rhs );
}
template< class T >
class sdSmartPtrFromThis {
public:
sdSmartPtrFromThis() {}
sdSmartPtrFromThis( const sdSmartPtrFromThis& rhs ) {}
sdSmartPtr< T >& GetThisPtr() { return thisPtr; }
const sdSmartPtr< T >& GetThisPtr() const { return thisPtr; }
sdSmartPtrFromThis& operator=( const sdSmartPtrFromThis& rhs ) { return *this; }
mutable sdSmartPtr< T > thisPtr;
};
template< class T >
void sdDetail_AssignThis( const sdSmartPtrFromThis< T >* p, const sdSmartPtr< T >& ptr ) {
if( p != NULL ) {
p->thisPtr.ResetWeak( ptr );
}
}
#endif // ! __LIB_SMARTPTR_H__