103 lines
2.1 KiB
C++
103 lines
2.1 KiB
C++
/******************************************************************************/
|
|
/* POINTERS *******************************************************************/
|
|
/******************************************************************************/
|
|
|
|
#include <ebcl/Alloc.hh>
|
|
#include <ebcl/Config.hh>
|
|
#include <ebcl/Pointers.hh>
|
|
using namespace ebcl;
|
|
|
|
|
|
/*= T_WeakChain_ =============================================================*/
|
|
|
|
T_WeakChain_::T_WeakChain_( T_Reference_*& ref )
|
|
: ref( &ref ) , prev( nullptr ) , next( nullptr )
|
|
{ }
|
|
|
|
void T_WeakChain_::unchain( )
|
|
{
|
|
if ( prev != nullptr ) {
|
|
prev->next = next;
|
|
prev = nullptr;
|
|
} else if ( (*ref) != nullptr ) {
|
|
assert( this == (*ref)->weaks_ );
|
|
(*ref)->weaks_ = next;
|
|
}
|
|
if ( next != nullptr ) {
|
|
next->prev = prev;
|
|
next = nullptr;
|
|
}
|
|
}
|
|
|
|
void T_WeakChain_::init( )
|
|
{
|
|
if ( (*ref) == nullptr ) {
|
|
return;
|
|
}
|
|
next = (*ref)->weaks_;
|
|
if ( next != nullptr ) {
|
|
next->prev = this;
|
|
}
|
|
(*ref)->weaks_ = this;
|
|
}
|
|
|
|
|
|
/*= T_Reference_ =============================================================*/
|
|
|
|
namespace {
|
|
|
|
static T_ThreadedPoolAllocator<
|
|
sizeof( T_Reference_ ) , alignof( T_Reference_ ) ,
|
|
EBCL_CFG_SHAREDPTR_REFPOOL_SIZE ,
|
|
EBCL_CFG_SHAREDPTR_REFPOOL_MAXFREE
|
|
> ReferenceAllocator_;
|
|
|
|
}
|
|
|
|
void* T_Reference_::operator new(
|
|
const size_t count ) noexcept
|
|
{
|
|
return ReferenceAllocator_.allocate( count );
|
|
}
|
|
|
|
void T_Reference_::operator delete(
|
|
void* const object ) noexcept
|
|
{
|
|
return ReferenceAllocator_.free( object );
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
T_Reference_::T_Reference_(
|
|
void* const ptr ,
|
|
F_Destr_ destructor )
|
|
: pointer_( ptr ) , destr_( std::move( destructor ) ) ,
|
|
count_( 1 ) , weaks_( nullptr )
|
|
{
|
|
assert( pointer_ != nullptr );
|
|
}
|
|
|
|
T_Reference_::~T_Reference_( )
|
|
{
|
|
assert( count_ == 0 );
|
|
T_WeakChain_* wr = weaks_;
|
|
while ( wr != nullptr ) {
|
|
T_WeakChain_* const next = wr->next;
|
|
wr->unchain( );
|
|
*( wr->ref ) = nullptr;
|
|
wr = next;
|
|
}
|
|
destr_( pointer_ );
|
|
}
|
|
|
|
void* T_Reference_::extract( )
|
|
{
|
|
if ( count_ > 1 ) {
|
|
throw X_TooManyReferences( );
|
|
}
|
|
void* p( pointer_ );
|
|
count_ = 0;
|
|
pointer_ = nullptr;
|
|
delete this;
|
|
return p;
|
|
}
|