mirror of https://github.com/PCSX2/pcsx2.git
328 lines
7.6 KiB
C++
328 lines
7.6 KiB
C++
#pragma once
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// ScopedPtr
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
template< typename T >
|
|
class ScopedPtr
|
|
{
|
|
DeclareNoncopyableObject(ScopedPtr);
|
|
|
|
protected:
|
|
T* m_ptr;
|
|
|
|
public:
|
|
typedef T element_type;
|
|
|
|
wxEXPLICIT ScopedPtr(T * ptr = NULL) : m_ptr(ptr) { }
|
|
|
|
~ScopedPtr() throw()
|
|
{ Delete(); }
|
|
|
|
ScopedPtr& Reassign(T * ptr = NULL)
|
|
{
|
|
if ( ptr != m_ptr )
|
|
{
|
|
Delete();
|
|
m_ptr = ptr;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
ScopedPtr& Delete() throw()
|
|
{
|
|
// Thread-safe deletion: Set the pointer to NULL first, and then issue
|
|
// the deletion. This allows pending Application messages that might be
|
|
// dependent on the current object to nullify their actions.
|
|
|
|
T* deleteme = m_ptr;
|
|
m_ptr = NULL;
|
|
delete deleteme;
|
|
|
|
return *this;
|
|
}
|
|
|
|
// Removes the pointer from scoped management, but does not delete!
|
|
T *DetachPtr()
|
|
{
|
|
T *ptr = m_ptr;
|
|
m_ptr = NULL;
|
|
return ptr;
|
|
}
|
|
|
|
// Returns the managed pointer. Can return NULL as a valid result if the ScopedPtr
|
|
// has no object in management.
|
|
T* GetPtr() const
|
|
{
|
|
return m_ptr;
|
|
}
|
|
|
|
void SwapPtr(ScopedPtr& other)
|
|
{
|
|
T * const tmp = other.m_ptr;
|
|
other.m_ptr = m_ptr;
|
|
m_ptr = tmp;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// ScopedPtr Operators
|
|
// ----------------------------------------------------------------------------
|
|
// I've decided to use the ATL's approach to pointer validity tests, opposed to
|
|
// the wx/boost approach (which uses some bizarre member method pointer crap, and can't
|
|
// allow the T* implicit casting.
|
|
|
|
bool operator!() const throw()
|
|
{
|
|
return m_ptr == NULL;
|
|
}
|
|
|
|
operator T*() const
|
|
{
|
|
return m_ptr;
|
|
}
|
|
|
|
// Equality
|
|
bool operator==(T* pT) const throw()
|
|
{
|
|
return m_ptr == pT;
|
|
}
|
|
|
|
// Inequality
|
|
bool operator!=(T* pT) const throw()
|
|
{
|
|
return !operator==(pT);
|
|
}
|
|
|
|
// Convenient assignment operator. ScopedPtr = NULL will issue an automatic deletion
|
|
// of the managed pointer.
|
|
ScopedPtr& operator=( T* src )
|
|
{
|
|
return Reassign( src );
|
|
}
|
|
|
|
// Dereference operator, returns a handle to the managed pointer.
|
|
// Generates a debug assertion if the object is NULL!
|
|
T& operator*() const
|
|
{
|
|
pxAssert(m_ptr != NULL);
|
|
return *m_ptr;
|
|
}
|
|
|
|
T* operator->() const
|
|
{
|
|
pxAssert(m_ptr != NULL);
|
|
return m_ptr;
|
|
}
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// ScopedArray - same as ScopedPtr but uses delete[], and has operator[]
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
template< typename T >
|
|
class ScopedArray
|
|
{
|
|
DeclareNoncopyableObject(ScopedArray);
|
|
|
|
protected:
|
|
T* m_array;
|
|
uint m_valid_range;
|
|
public:
|
|
typedef T element_type;
|
|
|
|
wxEXPLICIT ScopedArray(T * ptr = NULL) :
|
|
m_array(ptr)
|
|
, m_valid_range( 0xffffffff )
|
|
{
|
|
}
|
|
|
|
wxEXPLICIT ScopedArray( int size ) :
|
|
m_array( pxAssertDev( size >= 0, "Invalid negative size specified." ) ? new T[size] : NULL )
|
|
, m_valid_range( (uint)size )
|
|
{
|
|
}
|
|
|
|
// For breaking the 2gb barrier, lets provision this:
|
|
wxEXPLICIT ScopedArray( s64 size ) :
|
|
m_array( pxAssertDev( size >= 0 && (size < UINT_MAX), "Invalid negative size specified to ScopedArray." ) ? new T[size] : NULL )
|
|
, m_valid_range( (uint)size )
|
|
{
|
|
}
|
|
|
|
~ScopedArray() throw()
|
|
{ Delete(); }
|
|
|
|
ScopedArray& Reassign(T * ptr = NULL)
|
|
{
|
|
if( ptr != m_array )
|
|
{
|
|
Delete();
|
|
m_array = ptr;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
ScopedArray& Delete() throw()
|
|
{
|
|
// Thread-safe deletion: Set the pointer to NULL first, and then issue
|
|
// the deletion. This allows pending Application messages that might be
|
|
// dependent on the current object to nullify their actions.
|
|
|
|
T* deleteme = m_array;
|
|
m_array = NULL;
|
|
delete[] deleteme;
|
|
|
|
return *this;
|
|
}
|
|
|
|
// Removes the pointer from scoped management, but does not delete!
|
|
T *DetachPtr()
|
|
{
|
|
T *ptr = m_array;
|
|
m_array = NULL;
|
|
return ptr;
|
|
}
|
|
|
|
// Returns the managed pointer. Can return NULL as a valid result if the ScopedPtr
|
|
// has no object in management.
|
|
T* GetPtr() const
|
|
{
|
|
return m_array;
|
|
}
|
|
|
|
void SwapPtr(ScopedArray& other)
|
|
{
|
|
T * const tmp = other.m_array;
|
|
other.m_array = m_array;
|
|
m_array = tmp;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// ScopedPtr Operators
|
|
// ----------------------------------------------------------------------------
|
|
// I've decided to use the ATL's approach to pointer validity tests, opposed to
|
|
// the wx/boost approach (which uses some bizarre member method pointer crap, and can't
|
|
// allow the T* implicit casting.
|
|
|
|
bool operator!() const throw()
|
|
{
|
|
return m_array == NULL;
|
|
}
|
|
|
|
// Equality
|
|
bool operator==(T* pT) const throw()
|
|
{
|
|
return m_array == pT;
|
|
}
|
|
|
|
// Inequality
|
|
bool operator!=(T* pT) const throw()
|
|
{
|
|
return !operator==(pT);
|
|
}
|
|
|
|
// Convenient assignment operator. ScopedPtr = NULL will issue an automatic deletion
|
|
// of the managed pointer.
|
|
ScopedArray& operator=( T* src )
|
|
{
|
|
return Reassign( src );
|
|
}
|
|
|
|
T& operator[]( uint idx ) const
|
|
{
|
|
pxAssertDev( idx < m_valid_range, "Array index out of bounds on ScopedArray." );
|
|
return m_array[idx];
|
|
}
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// pxObjPtr -- fancified version of wxScopedPtr
|
|
// --------------------------------------------------------------------------------------
|
|
// This class is a non-null scoped pointer container. What that means is that the object
|
|
// always resets itself to a valid "placebo" function rather than NULL, such that methods
|
|
// can be invoked safely without fear of NULL pointer exceptions. This system is useful
|
|
// for objects where most or all public methods can fail silently, and still allow program
|
|
// execution flow to continue.
|
|
//
|
|
// It also implements basic scoped pointer behavior: when the pxObjPtr class is deleted,
|
|
// it will automatically delete the pointer in its posession, if the pointer is valid.
|
|
//
|
|
// Notes:
|
|
// * This class intentionally does not implement the "release" API, because it doesn't
|
|
// really make sense within the context of a non-nullable pointer specification.
|
|
//
|
|
template< typename T, T& DefaultStaticInst >
|
|
class pxObjPtr
|
|
{
|
|
DeclareNoncopyableObject(pxObjPtr);
|
|
|
|
protected:
|
|
T * m_ptr;
|
|
|
|
public:
|
|
typedef T element_type;
|
|
|
|
explicit pxObjPtr(T * ptr = &DefaultStaticInst) : m_ptr(ptr) { }
|
|
|
|
bool IsEmpty() const
|
|
{
|
|
return m_ptr != &DefaultStaticInst;
|
|
}
|
|
|
|
~pxObjPtr()
|
|
{
|
|
if( !IsEmpty() ) delete m_ptr;
|
|
m_ptr = NULL;
|
|
}
|
|
|
|
// test for pointer validity: defining conversion to unspecified_bool_type
|
|
// and not more obvious bool to avoid implicit conversions to integer types
|
|
typedef T *(pxObjPtr<T,DefaultStaticInst>::*unspecified_bool_type)() const;
|
|
|
|
operator unspecified_bool_type() const
|
|
{
|
|
return ( !IsEmpty() ) ? &ScopedPtr<T>::get : NULL;
|
|
}
|
|
|
|
void reset(T * ptr = &DefaultStaticInst)
|
|
{
|
|
if ( ptr != m_ptr )
|
|
{
|
|
if( !IsEmpty() )
|
|
delete m_ptr;
|
|
m_ptr = ptr;
|
|
}
|
|
}
|
|
|
|
T& operator*() const
|
|
{
|
|
pxAssert(m_ptr != NULL);
|
|
return *m_ptr;
|
|
}
|
|
|
|
T* operator->() const
|
|
{
|
|
pxAssert(m_ptr != NULL);
|
|
return m_ptr;
|
|
}
|
|
|
|
T* get() const
|
|
{
|
|
pxAssert(m_ptr != NULL);
|
|
return m_ptr;
|
|
}
|
|
|
|
void swap(pxObjPtr& other)
|
|
{
|
|
// Neither pointer in either container should ever be NULL...
|
|
pxAssert(m_ptr != NULL);
|
|
pxAssert(other.m_ptr != NULL);
|
|
|
|
T * const tmp = other.m_ptr;
|
|
other.m_ptr = m_ptr;
|
|
m_ptr = tmp;
|
|
}
|
|
};
|
|
|