Skip to content

Commit

Permalink
Make SMR and HP classes generic
Browse files Browse the repository at this point in the history
  • Loading branch information
Krock21 committed Jul 17, 2020
1 parent 155586f commit 21f7630
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 65 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ set(HEADERS_COMPONENT devel)

set(SOURCES src/init.cpp
src/hp.cpp
src/hp_thread_local.cpp
src/dhp.cpp
src/urcu_gp.cpp
src/urcu_sh.cpp
Expand Down
123 changes: 86 additions & 37 deletions cds/gc/hp.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ namespace cds { namespace gc {
}
};

static stat const& postmortem_statistics();

//@cond
/// Per-thread data
struct thread_data {
Expand Down Expand Up @@ -356,6 +358,8 @@ namespace cds { namespace gc {
//@cond
/// Hazard Pointer SMR (Safe Memory Reclamation)
class basic_smr {
template<typename TLSManager>
friend class generic_smr;
struct thread_record;

public:
Expand Down Expand Up @@ -472,13 +476,6 @@ namespace cds { namespace gc {
}
}

/// Returns thread-local data for the current thread
static CDS_EXPORT_API thread_data *tls();

static CDS_EXPORT_API void attach_thread();

static CDS_EXPORT_API void detach_thread();

/// Get internal statistics
CDS_EXPORT_API void statistics(stat &st);

Expand Down Expand Up @@ -579,14 +576,62 @@ namespace cds { namespace gc {
};
//@endcond

class DefaultTLSManager {
public:
static CDS_EXPORT_API thread_data* getTLS();
static CDS_EXPORT_API void setTLS(thread_data*);
};

class StrangeTLSManager {
public:
static CDS_EXPORT_API thread_data* getTLS();
static CDS_EXPORT_API void setTLS(thread_data*);
};

class HeapTLSManager {
public:
static CDS_EXPORT_API thread_data* getTLS();
static CDS_EXPORT_API void setTLS(thread_data*);
};

template<typename TLSManager>
class generic_smr : public basic_smr {
public:
/// Returns thread-local data for the current thread
static CDS_EXPORT_API thread_data* tls()
{
thread_data* data = TLSManager::getTLS();
assert( data != nullptr );
return data;
}

static CDS_EXPORT_API void attach_thread()
{
thread_data* data = TLSManager::getTLS();
if ( !data )
TLSManager::setTLS(reinterpret_cast<thread_data *>(instance().alloc_thread_data()));
}

static CDS_EXPORT_API void detach_thread()
{
thread_data* rec = TLSManager::getTLS();
if ( rec ) {
TLSManager::setTLS(nullptr);
instance().free_thread_data(reinterpret_cast<thread_record*>( rec ), true );
}
}
};



} // namespace details

//@cond
// for backward compatibility
typedef details::basic_smr smr;
typedef details::generic_smr<details::DefaultTLSManager> smr;
typedef smr GarbageCollector;
//@endcond
} // namespace hp
} // namespace cds::gc::hp

namespace details {
/// Hazard Pointer SMR (Safe Memory Reclamation)
Expand All @@ -604,7 +649,8 @@ namespace cds { namespace gc {
by contructing \p %cds::gc::HP object in beginning of your \p main().
See \ref cds_how_to_use "How to use" section for details how to apply SMR schema.
*/
class HP
template<typename TLSManager>
class generic_HP
{
public:
/// Native guarded pointer type
Expand Down Expand Up @@ -649,7 +695,7 @@ namespace cds { namespace gc {
@warning Can throw \p not_enough_hazard_ptr if internal hazard pointer objects are exhausted.
*/
Guard()
: guard_( hp::smr::tls()->hazards_.alloc())
: guard_( hp::details::generic_smr<TLSManager>::tls()->hazards_.alloc())
{}

/// Initilalizes an unlinked guard i.e. the guard contains no hazard pointer. Used for move semantics support
Expand Down Expand Up @@ -699,14 +745,14 @@ namespace cds { namespace gc {
void link()
{
if ( !guard_ )
guard_ = hp::smr::tls()->hazards_.alloc();
guard_ = hp::details::generic_smr<TLSManager>::tls()->hazards_.alloc();
}

/// Unlinks the guard from internal hazard pointer; the guard becomes in unlinked state
void unlink()
{
if ( guard_ ) {
hp::smr::tls()->hazards_.free( guard_ );
hp::details::generic_smr<TLSManager>::tls()->hazards_.free( guard_ );
guard_ = nullptr;
}
}
Expand Down Expand Up @@ -774,7 +820,7 @@ namespace cds { namespace gc {
assert( guard_ != nullptr );

guard_->set( p );
hp::smr::tls()->sync();
hp::details::generic_smr<TLSManager>::tls()->sync();
return p;
}

Expand Down Expand Up @@ -871,7 +917,7 @@ namespace cds { namespace gc {
/// Default ctor allocates \p Count hazard pointers
GuardArray()
{
hp::smr::tls()->hazards_.alloc( guards_ );
hp::details::generic_smr<TLSManager>::tls()->hazards_.alloc( guards_ );
}

/// Move ctor is prohibited
Expand All @@ -889,7 +935,7 @@ namespace cds { namespace gc {
/// Frees allocated hazard pointers
~GuardArray()
{
hp::smr::tls()->hazards_.free( guards_ );
hp::details::generic_smr<TLSManager>::tls()->hazards_.free( guards_ );
}

/// Protects a pointer of type \p atomic<T*>
Expand Down Expand Up @@ -945,7 +991,7 @@ namespace cds { namespace gc {
assert( nIndex < capacity());

guards_.set( nIndex, p );
hp::smr::tls()->sync();
hp::details::generic_smr<TLSManager>::tls()->sync();
return p;
}

Expand Down Expand Up @@ -1202,13 +1248,13 @@ namespace cds { namespace gc {
void alloc_guard()
{
if ( !guard_ )
guard_ = hp::smr::tls()->hazards_.alloc();
guard_ = hp::details::generic_smr<TLSManager>::tls()->hazards_.alloc();
}

void free_guard()
{
if ( guard_ ) {
hp::smr::tls()->hazards_.free( guard_ );
hp::details::generic_smr<TLSManager>::tls()->hazards_.free( guard_ );
guard_ = nullptr;
}
}
Expand Down Expand Up @@ -1240,14 +1286,14 @@ namespace cds { namespace gc {
- \p nMaxRetiredPtrCount - capacity of array of retired pointers for each thread. Must be greater than
<tt> nHazardPtrCount * nMaxThreadCount </tt>. Default is <tt>2 * nHazardPtrCount * nMaxThreadCount </tt>.
*/
HP(
generic_HP(
size_t nHazardPtrCount = 0, ///< Hazard pointer count per thread
size_t nMaxThreadCount = 0, ///< Max count of simultaneous working thread in your application
size_t nMaxRetiredPtrCount = 0, ///< Capacity of the array of retired objects for the thread
scan_type nScanType = scan_type::inplace ///< Scan type (see \p scan_type enum)
)
{
hp::smr::construct(
hp::details::generic_smr<TLSManager>::construct(
nHazardPtrCount,
nMaxThreadCount,
nMaxRetiredPtrCount,
Expand All @@ -1261,9 +1307,9 @@ namespace cds { namespace gc {
use CDS data structures based on \p %cds::gc::HP.
Usually, %HP object is destroyed at the end of your \p main().
*/
~HP()
~generic_HP()
{
hp::smr::destruct( true );
hp::details::generic_smr<TLSManager>::destruct( true );
}

/// Checks that required hazard pointer count \p nCountNeeded is less or equal then max hazard pointer count
Expand All @@ -1272,7 +1318,7 @@ namespace cds { namespace gc {
*/
static void check_available_guards( size_t nCountNeeded )
{
hp::smr::check_hazard_ptr_count( nCountNeeded );
hp::details::generic_smr<TLSManager>::check_hazard_ptr_count( nCountNeeded );
}

/// Set memory management functions
Expand All @@ -1289,25 +1335,25 @@ namespace cds { namespace gc {
void( *free_func )( void * p ) ///< \p free() function
)
{
hp::smr::set_memory_allocator( alloc_func, free_func );
hp::details::generic_smr<TLSManager>::set_memory_allocator( alloc_func, free_func );
}

/// Returns max Hazard Pointer count
static size_t max_hazard_count()
{
return hp::smr::instance().get_hazard_ptr_count();
return hp::details::generic_smr<TLSManager>::instance().get_hazard_ptr_count();
}

/// Returns max count of thread
static size_t max_thread_count()
{
return hp::smr::instance().get_max_thread_count();
return hp::details::generic_smr<TLSManager>::instance().get_max_thread_count();
}

/// Returns capacity of retired pointer array
static size_t retired_array_capacity()
{
return hp::smr::instance().get_max_retired_ptr_count();
return hp::details::generic_smr<TLSManager>::instance().get_max_retired_ptr_count();
}

/// Retire pointer \p p with function \p func
Expand All @@ -1319,9 +1365,9 @@ namespace cds { namespace gc {
template <typename T>
static void retire( T * p, void( *func )( void * ))
{
hp::details::thread_data* rec = hp::smr::tls();
hp::details::thread_data* rec = hp::details::generic_smr<TLSManager>::tls();
if ( !rec->retired_.push( hp::details::retired_ptr( p, func )))
hp::smr::instance().scan( rec );
hp::details::generic_smr<TLSManager>::instance().scan( rec );
}

/// Retire pointer \p p with functor of type \p Disposer
Expand Down Expand Up @@ -1376,20 +1422,20 @@ namespace cds { namespace gc {
template <class Disposer, typename T>
static void retire( T * p )
{
if ( !hp::smr::tls()->retired_.push( hp::details::retired_ptr( p, +[]( void* p ) { Disposer()( static_cast<T*>( p )); })))
if ( !hp::details::generic_smr<TLSManager>::tls()->retired_.push( hp::details::retired_ptr( p, +[]( void* p ) { Disposer()( static_cast<T*>( p )); })))
scan();
}

/// Get current scan strategy
static scan_type getScanType()
{
return static_cast<scan_type>( hp::smr::instance().get_scan_type());
return static_cast<scan_type>( hp::details::generic_smr<TLSManager>::instance().get_scan_type());
}

/// Checks if Hazard Pointer GC is constructed and may be used
static bool isUsed()
{
return hp::smr::isUsed();
return hp::details::generic_smr<TLSManager>::isUsed();
}

/// Forces SMR call for current thread
Expand All @@ -1398,7 +1444,7 @@ namespace cds { namespace gc {
*/
static void scan()
{
hp::smr::instance().scan( hp::smr::tls());
hp::details::generic_smr<TLSManager>::instance().scan( hp::details::generic_smr<TLSManager>::tls());
}

/// Synonym for \p scan()
Expand All @@ -1416,7 +1462,7 @@ namespace cds { namespace gc {
*/
static void statistics( stat& st )
{
hp::smr::instance().statistics( st );
hp::details::generic_smr<TLSManager>::instance().statistics( st );
}

/// Returns post-mortem statistics
Expand Down Expand Up @@ -1462,11 +1508,14 @@ namespace cds { namespace gc {
}
\endcode
*/
CDS_EXPORT_API static stat const& postmortem_statistics();
static stat const& postmortem_statistics() {
return cds::gc::hp::details::postmortem_statistics();
}
};
} // namespace cds::gc::details

typedef details::HP HP;
// for backward compatibility
typedef details::generic_HP<hp::details::DefaultTLSManager> HP;
typedef hp::details::basic_smr smr;
}} // namespace cds::gc

Expand Down
33 changes: 5 additions & 28 deletions src/hp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,6 @@ namespace cds { namespace gc { namespace hp { namespace details {
/*static*/ CDS_EXPORT_API basic_smr* basic_smr::instance_ = nullptr;
thread_local thread_data* tls_ = nullptr;

/*static*/ CDS_EXPORT_API thread_data* basic_smr::tls()
{
assert( tls_ != nullptr );
return tls_;
}

struct basic_smr::thread_record: thread_data
{
// next hazard ptr record in list
Expand Down Expand Up @@ -310,22 +304,6 @@ namespace cds { namespace gc { namespace hp { namespace details {
}
}

/*static*/ CDS_EXPORT_API void basic_smr::attach_thread()
{
if ( !tls_ )
tls_ = instance().alloc_thread_data();
}

/*static*/ CDS_EXPORT_API void basic_smr::detach_thread()
{
thread_data* rec = tls_;
if ( rec ) {
tls_ = nullptr;
instance().free_thread_data( static_cast<thread_record*>( rec ), true );
}
}


CDS_EXPORT_API void basic_smr::inplace_scan(thread_data* pThreadRec )
{
thread_record* pRec = static_cast<thread_record*>( pThreadRec );
Expand Down Expand Up @@ -539,10 +517,9 @@ namespace cds { namespace gc { namespace hp { namespace details {
# endif
}

}}}} // namespace cds::gc::hp::details

CDS_EXPORT_API /*static*/ cds::gc::HP::stat const& cds::gc::HP::postmortem_statistics()
{
return cds::gc::hp::details::s_postmortem_stat;
}
cds::gc::hp::details::stat const& postmortem_statistics()
{
return s_postmortem_stat;
}

}}}} // namespace cds::gc::hp::details
Loading

0 comments on commit 21f7630

Please sign in to comment.