181 lines
4.9 KiB
C
181 lines
4.9 KiB
C
|
// 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__
|