#include "appcore.h"
#ifndef AC_SMR_HPP
#define AC_SMR_HPP
template< typename T > class shared_smr_ptr;
template< typename T > class local_smr_ptr;
template< typename T >
class shared_smr_ptr
{
friend class local_smr_ptr< T >;
mutable ac_lfgc_refcount_t *m_ref;
static void AC_CDECL smr_dtor( void *state )
{
delete (T*)state;
}
ac_lfgc_refcount_t* get_refcount() const { return m_ref; }
ac_lfgc_refcount_t* mb_get_refcount() const
{ return (ac_lfgc_refcount_t*)ac_mb_loadptr_depends( &m_ref ); }
public:
shared_smr_ptr( T *state = 0, ac_thread_t *_tls = 0 )
: m_ref( 0 )
{
if ( state )
{ int ret = ac_lfgc_refcount_alloc
( _tls,
&m_ref,
smr_dtor,
state );
if ( ret ) { throw ret; }
}
}
shared_smr_ptr( const shared_smr_ptr &src )
: m_ref( 0 ) { *this = src; }
shared_smr_ptr( const local_smr_ptr< T > &src )
: m_ref( 0 ) { *this = src; }
~shared_smr_ptr() { ac_lfgc_refcount_release( m_ref ); }
public:
void xchg( local_smr_ptr< T > &_xchg )
{
ac_lfgc_refcount_t *temp = _xchg.mb_get_refcount();
_xchg.m_ref = ac_lfgc_refcount_xchg( &m_ref, temp );
ac_lfgc_refcount_release( temp );
}
bool cas( const local_smr_ptr< T > &cmp,
const local_smr_ptr< T > &xchg )
{
return ( ! ac_lfgc_refcount_cas
( &m_ref,
cmp.get_refcount(),
xchg.get_refcount() ) )
? true : false;
}
public:
shared_smr_ptr& operator =( T *state )
{
if ( state )
{ local_smr_ptr< T > temp( state );
xchg( temp );
}
else { ac_lfgc_refcount_null( &m_ref ); }
return *this;
}
shared_smr_ptr& operator =( const shared_smr_ptr &src )
{
ac_lfgc_refcount_copy_shared
( 0,
&m_ref,
&src.m_ref );
return *this;
}
shared_smr_ptr& operator =( const local_smr_ptr< T > &src )
{
ac_lfgc_refcount_copy_local
( &m_ref,
src.get_refcount() );
return *this;
}
bool operator !() { return ( ! m_ref ); }
};
template< typename T >
class local_smr_ptr
{
friend class shared_smr_ptr< T >;
mutable ac_lfgc_refcount_t *m_ref;
ac_lfgc_refcount_t* get_refcount() const { return m_ref; }
ac_lfgc_refcount_t* mb_get_refcount() const
{ return (ac_lfgc_refcount_t*)ac_mb_loadptr_depends( &m_ref ); }
public:
local_smr_ptr( T *state = 0, ac_thread_t *_tls = 0 )
: m_ref( 0 )
{
if ( state )
{ int ret = ac_lfgc_refcount_alloc
( _tls,
&m_ref,
shared_smr_ptr< T >::smr_dtor,
state );
if ( ret ) { throw ret; }
}
}
local_smr_ptr( const local_smr_ptr &src )
: m_ref( 0 ) { *this = src; }
local_smr_ptr( const shared_smr_ptr< T > &src )
: m_ref( 0 ) { *this = src; }
~local_smr_ptr() { ac_lfgc_refcount_release( m_ref ); }
public:
local_smr_ptr& operator =( T *state )
{
if ( state )
{ local_smr_ptr< T > temp( state );
xchg( temp );
}
else { ac_lfgc_refcount_null( &m_ref ); }
return *this;
}
local_smr_ptr& operator =( const local_smr_ptr &src )
{
ac_lfgc_refcount_copy_local
( &m_ref,
src.get_refcount() );
return *this;
}
local_smr_ptr& operator =( const shared_smr_ptr< T > &src )
{
ac_lfgc_refcount_copy_shared
( 0,
&m_ref,
&src.m_ref );
return *this;
}
T* operator ->() { return (T*)ac_lfgc_refcount_get( m_ref ); }
bool operator !() { return ( ! m_ref ); }
};
#endif