//@cond
namespace cds {
- /**
- @page cds_garbage_collectors_comparison GC comparison
- @ingroup cds_garbage_collector
-
- <table>
- <tr>
- <th>Feature</th>
- <th>%cds::gc::HP</th>
- <th>%cds::gc::DHP</th>
- </tr>
- <tr>
- <td>Implementation quality</td>
- <td>stable</td>
- <td>stable</td>
- </tr>
- <tr>
- <td>Performance rank (1 - slowest, 5 - fastest)</td>
- <td>5</td>
- <td>4</td>
- </tr>
- <tr>
- <td>Max number of guarded (hazard) pointers per thread</td>
- <td>limited (specifies in GC object ctor)</td>
- <td>unlimited (dynamically allocated when needed)</td>
- </tr>
- <tr>
- <td>Max number of retired pointers<sup>1</sup></td>
- <td>bounded</td>
- <td>bounded</td>
- </tr>
- <tr>
- <td>Array of retired pointers</td>
- <td>preallocated for each thread, limited in size</td>
- <td>global for the entire process, unlimited (dynamically allocated when needed)</td>
- </tr>
- <tr>
- <td>Support direct pointer to item of lock-free container (useful for iterators)</td>
- <td>not supported</td>
- <td>not supported</td>
- </tr>
- </table>
-
- <sup>1</sup>Unbounded count of retired pointer means a possibility of memory exhaustion.
- */
-
/// Different safe memory reclamation schemas (garbage collectors)
/** @ingroup cds_garbage_collector
public:
/// Iterator
- typedef retired_vector_impl::iterator iterator;
+ typedef retired_vector_impl::iterator iterator;
/// Constructor
- retired_vector( const cds::gc::hp::GarbageCollector& HzpMgr ) CDS_NOEXCEPT; // inline
+ retired_vector( const cds::gc::hp::GarbageCollector& HzpMgr ); // inline
~retired_vector()
{}
The capacity is constant for any thread. It is defined by cds::gc::hp::GarbageCollector.
*/
size_t capacity() const CDS_NOEXCEPT
- {
- return m_arr.capacity();
+ {
+ return m_arr.capacity();
}
/// Current vector size (count of retired pointers in the vector)
size_t size() const CDS_NOEXCEPT
- {
- return m_nSize;
+ {
+ return m_nSize;
}
/// Set vector size. Uses internally
}
/// Pushes retired pointer to the vector
- void push( const retired_ptr& p )
+ void push( retired_ptr const& p )
{
assert( m_nSize < capacity() );
m_arr[ m_nSize ] = p;
/// Begin iterator
iterator begin() CDS_NOEXCEPT
- {
- return m_arr.begin();
+ {
+ return m_arr.begin();
}
/// End iterator
iterator end() CDS_NOEXCEPT
- {
- return m_arr.begin() + m_nSize ;
+ {
+ return m_arr.begin() + m_nSize;
}
/// Clears the vector. After clearing, size() == 0
/// Internal list of cds::gc::hp::details::hp_record
struct hplist_node : public details::hp_record
{
- hplist_node * m_pNextNode ; ///< next hazard ptr record in list
- atomics::atomic<OS::ThreadId> m_idOwner ; ///< Owner thread id; 0 - the record is free (not owned)
- atomics::atomic<bool> m_bFree ; ///< true if record if free (not owned)
+ hplist_node * m_pNextNode; ///< next hazard ptr record in list
+ atomics::atomic<OS::ThreadId> m_idOwner; ///< Owner thread id; 0 - the record is free (not owned)
+ atomics::atomic<bool> m_bFree; ///< true if record if free (not owned)
hplist_node( const GarbageCollector& HzpMgr )
: hp_record( HzpMgr ),
*/
void DeleteHPRec( hplist_node * pNode );
- /// Permanently deletes retired pointer \p p
- /**
- Caveat: for performance reason this function is defined as inline and cannot be called directly
- */
- void DeletePtr( details::retired_ptr& p );
-
void detachAllThread();
public:
/// Returns max Hazard Pointer count defined in construction time
size_t getHazardPointerCount() const CDS_NOEXCEPT
- {
- return m_nHazardPointerCount;
+ {
+ return m_nHazardPointerCount;
}
/// Returns max thread count defined in construction time
size_t getMaxThreadCount() const CDS_NOEXCEPT
- {
- return m_nMaxThreadCount;
+ {
+ return m_nMaxThreadCount;
}
/// Returns max size of retired objects array. It is defined in construction time
size_t getMaxRetiredPtrCount() const CDS_NOEXCEPT
- {
- return m_nMaxRetiredPtrCount;
+ {
+ return m_nMaxRetiredPtrCount;
}
// Internal statistics
/// Auto hp_guard.
/**
This class encapsulates Hazard Pointer guard to protect a pointer against deletion .
- It allocates one HP from thread's HP array in constructor and free the hazard pointer allocated
+ It allocates one HP from thread's HP array in constructor and free the hazard pointer allocated
in destructor.
*/
class guard
{
- details::hp_guard& m_hp ; ///< Hazard pointer guarded
- ThreadGC& m_gc ; ///< Thread GC
+ details::hp_guard& m_hp ; ///< Hazard pointer guarded
public:
typedef details::hp_guard::hazard_ptr hazard_ptr ; ///< Hazard pointer type
public:
- /// Allocates HP guard from \p gc
- guard( ThreadGC& gc )
- : m_hp( gc.allocGuard() )
- , m_gc( gc )
- {}
+ /// Allocates HP guard
+ guard(); // inline in hp_impl.h
/// Allocates HP guard from \p gc and protects the pointer \p p of type \p T
template <typename T>
- guard( ThreadGC& gc, T * p )
- : m_hp( gc.allocGuard() )
- , m_gc( gc )
- {
- m_hp = p;
- }
+ explicit guard( T * p ); // inline in hp_impl.h
/// Frees HP guard. The pointer guarded may be deleted after this.
- ~guard()
- {
- m_gc.freeGuard( m_hp );
- }
-
- /// Returns thread GC
- ThreadGC& getGC() const
- {
- return m_gc;
- }
+ ~guard(); // inline in hp_impl.h
/// Protects the pointer \p p against reclamation (guards the pointer).
template <typename T>
template <size_t Count>
class array : public details::hp_array<Count>
{
- ThreadGC& m_mgr ; ///< Thread GC
-
public:
/// Rebind array for other size \p COUNT2
template <size_t Count2>
};
public:
- /// Allocates array of HP guard from \p mgr
- array( ThreadGC& mgr )
- : m_mgr( mgr )
- {
- mgr.allocGuard( *this );
- }
+ /// Allocates array of HP guard
+ array(); // inline in hp_impl.h
/// Frees array of HP guard
- ~array()
- {
- m_mgr.freeGuard( *this );
- }
-
- /// Returns thread GC
- ThreadGC& getGC() const { return m_mgr; }
+ ~array(); //inline in hp_impl.h
};
} // namespace hp
}} // namespace cds::gc
//@endcond
+//@cond
// Inlines
-#include <cds/gc/details/hp_inline.h>
+namespace cds {
+ namespace gc { namespace hp { namespace details {
+
+ inline retired_vector::retired_vector( const cds::gc::hp::GarbageCollector& HzpMgr )
+ : m_arr( HzpMgr.getMaxRetiredPtrCount() ),
+ m_nSize(0)
+ {}
+
+ inline hp_record::hp_record( const cds::gc::hp::GarbageCollector& HzpMgr )
+ : m_hzp( HzpMgr.getHazardPointerCount() ),
+ m_arrRetired( HzpMgr )
+ {}
+
+ }}} // namespace gc::hp::details
+} // namespace cds
+//@endcond
+
#if CDS_COMPILER == CDS_COMPILER_MSVC
# pragma warning(pop)