Container System 0.1.0
High-performance C++20 type-safe container framework with SIMD-accelerated serialization
Loading...
Searching...
No Matches
kcenon::container::epoch_manager Class Reference

Epoch-based memory reclamation for lock-free data structures. More...

#include <epoch_manager.h>

Collaboration diagram for kcenon::container::epoch_manager:
Collaboration graph

Public Member Functions

void enter_critical () noexcept
 Enter critical section (pin to current epoch)
 
void exit_critical () noexcept
 Exit critical section.
 
bool in_critical_section () const noexcept
 Check if current thread is in critical section.
 
void defer_delete (void *ptr, std::function< void(void *)> deleter)
 Defer deletion of a pointer.
 
template<typename T >
void defer_delete (T *ptr)
 Defer deletion of a typed pointer.
 
size_t try_gc ()
 Attempt garbage collection.
 
size_t force_gc ()
 Force garbage collection of all epochs.
 
uint64_t current_epoch () const noexcept
 Get the current global epoch.
 
size_t gc_count () const noexcept
 Get the number of GC cycles performed.
 
size_t reclaimed_count () const noexcept
 Get the total number of objects reclaimed.
 
size_t pending_count () const
 Get the number of objects pending deletion.
 
 epoch_manager (const epoch_manager &)=delete
 
epoch_manageroperator= (const epoch_manager &)=delete
 
 epoch_manager (epoch_manager &&)=delete
 
epoch_manageroperator= (epoch_manager &&)=delete
 

Static Public Member Functions

static epoch_managerinstance ()
 Get the singleton instance.
 

Static Public Attributes

static constexpr uint64_t INACTIVE = UINT64_MAX
 Sentinel value indicating thread is not in critical section.
 
static constexpr size_t NUM_EPOCHS = 3
 Number of epochs in rotation (must be at least 3 for safety)
 

Private Member Functions

 epoch_manager ()=default
 Private constructor for singleton.
 
 ~epoch_manager ()
 Destructor - clean up any remaining deferred deletions.
 

Static Private Member Functions

static std::atomic< uint64_t > & thread_epoch ()
 Get thread-local epoch reference.
 

Private Attributes

std::atomic< uint64_t > global_epoch_ {0}
 
std::atomic< size_t > gc_count_ {0}
 
std::atomic< size_t > reclaimed_count_ {0}
 
std::array< std::mutex, NUM_EPOCHSretire_mutex_
 
std::array< std::vector< std::pair< void *, std::function< void(void *)> > >, NUM_EPOCHSretired_
 

Detailed Description

Epoch-based memory reclamation for lock-free data structures.

This class implements the epoch-based reclamation (EBR) algorithm for safe memory deallocation in lock-free data structures. It uses a three-epoch system where memory is deferred until all readers from two epochs ago have completed.

The algorithm:

  1. Threads enter a critical section by pinning to the current epoch
  2. Writers defer deletions to the current epoch's retire list
  3. When all threads have left an epoch, its retired memory can be reclaimed

Properties:

  • enter_critical/exit_critical: Lock-free
  • defer_delete: Lock-free (uses mutex only for list append)
  • try_gc: May reclaim memory when safe
// Reader thread
// ... read from lock-free structure ...
// Writer thread
em.defer_delete(old_node, [](void* p) { delete static_cast<Node*>(p); });
em.try_gc();
Epoch-based memory reclamation for lock-free data structures.
void exit_critical() noexcept
Exit critical section.
size_t try_gc()
Attempt garbage collection.
static epoch_manager & instance()
Get the singleton instance.
void defer_delete(void *ptr, std::function< void(void *)> deleter)
Defer deletion of a pointer.
void enter_critical() noexcept
Enter critical section (pin to current epoch)

Definition at line 46 of file epoch_manager.h.

Constructor & Destructor Documentation

◆ epoch_manager() [1/3]

kcenon::container::epoch_manager::epoch_manager ( const epoch_manager & )
delete

◆ epoch_manager() [2/3]

kcenon::container::epoch_manager::epoch_manager ( epoch_manager && )
delete

◆ epoch_manager() [3/3]

kcenon::container::epoch_manager::epoch_manager ( )
privatedefault

Private constructor for singleton.

◆ ~epoch_manager()

kcenon::container::epoch_manager::~epoch_manager ( )
inlineprivate

Destructor - clean up any remaining deferred deletions.

Definition at line 264 of file epoch_manager.h.

264 {
265 force_gc();
266 }
size_t force_gc()
Force garbage collection of all epochs.

References force_gc().

Here is the call graph for this function:

Member Function Documentation

◆ current_epoch()

uint64_t kcenon::container::epoch_manager::current_epoch ( ) const
inlinenodiscardnoexcept

Get the current global epoch.

Returns
Current epoch number

Definition at line 216 of file epoch_manager.h.

216 {
217 return global_epoch_.load(std::memory_order_relaxed);
218 }
std::atomic< uint64_t > global_epoch_

References global_epoch_.

◆ defer_delete() [1/2]

template<typename T >
void kcenon::container::epoch_manager::defer_delete ( T * ptr)
inline

Defer deletion of a typed pointer.

Convenience overload that automatically creates the deleter.

Template Parameters
TType of the pointer
Parameters
ptrPointer to defer deletion for

Definition at line 131 of file epoch_manager.h.

131 {
132 defer_delete(static_cast<void*>(ptr), [](void* p) {
133 delete static_cast<T*>(p);
134 });
135 }

References defer_delete().

Here is the call graph for this function:

◆ defer_delete() [2/2]

void kcenon::container::epoch_manager::defer_delete ( void * ptr,
std::function< void(void *)> deleter )
inline

Defer deletion of a pointer.

The deleter will be called when it's safe to reclaim the memory (when all readers from the current epoch have exited).

Parameters
ptrPointer to defer deletion for
deleterFunction to call to delete the pointer

Thread safety: Uses mutex for list append

Definition at line 110 of file epoch_manager.h.

110 {
111 if (ptr == nullptr) {
112 return;
113 }
114
115 uint64_t epoch = global_epoch_.load(std::memory_order_relaxed);
116 size_t bucket = epoch % NUM_EPOCHS;
117
118 std::lock_guard<std::mutex> lock(retire_mutex_[bucket]);
119 retired_[bucket].emplace_back(ptr, std::move(deleter));
120 }
std::array< std::vector< std::pair< void *, std::function< void(void *)> > >, NUM_EPOCHS > retired_
std::array< std::mutex, NUM_EPOCHS > retire_mutex_
static constexpr size_t NUM_EPOCHS
Number of epochs in rotation (must be at least 3 for safety)

References global_epoch_, NUM_EPOCHS, retire_mutex_, and retired_.

Referenced by defer_delete().

Here is the caller graph for this function:

◆ enter_critical()

void kcenon::container::epoch_manager::enter_critical ( )
inlinenoexcept

Enter critical section (pin to current epoch)

Must be called before accessing any lock-free data structure. Must be paired with exit_critical().

Thread safety: Lock-free

Definition at line 76 of file epoch_manager.h.

76 {
77 thread_epoch() = global_epoch_.load(std::memory_order_acquire);
78 }
static std::atomic< uint64_t > & thread_epoch()
Get thread-local epoch reference.

References global_epoch_, and thread_epoch().

Referenced by kcenon::container::epoch_guard::epoch_guard().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ exit_critical()

void kcenon::container::epoch_manager::exit_critical ( )
inlinenoexcept

Exit critical section.

Must be called after finishing access to lock-free data structures.

Thread safety: Lock-free

Definition at line 87 of file epoch_manager.h.

87 {
89 }
static constexpr uint64_t INACTIVE
Sentinel value indicating thread is not in critical section.

References INACTIVE, and thread_epoch().

Referenced by kcenon::container::epoch_guard::~epoch_guard().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ force_gc()

size_t kcenon::container::epoch_manager::force_gc ( )
inline

Force garbage collection of all epochs.

This should only be called when no threads are accessing lock-free data structures (e.g., during shutdown).

Returns
Number of objects reclaimed

Definition at line 188 of file epoch_manager.h.

188 {
189 size_t total = 0;
190 for (size_t i = 0; i < NUM_EPOCHS; ++i) {
191 std::vector<std::pair<void*, std::function<void(void*)>>> to_delete;
192 {
193 std::lock_guard<std::mutex> lock(retire_mutex_[i]);
194 to_delete = std::move(retired_[i]);
195 retired_[i].clear();
196 }
197
198 for (auto& [ptr, deleter] : to_delete) {
199 deleter(ptr);
200 }
201 total += to_delete.size();
202 }
203
204 if (total > 0) {
205 gc_count_.fetch_add(1, std::memory_order_relaxed);
206 reclaimed_count_.fetch_add(total, std::memory_order_relaxed);
207 }
208
209 return total;
210 }
std::atomic< size_t > reclaimed_count_
std::atomic< size_t > gc_count_

References gc_count_, NUM_EPOCHS, reclaimed_count_, retire_mutex_, and retired_.

Referenced by ~epoch_manager().

Here is the caller graph for this function:

◆ gc_count()

size_t kcenon::container::epoch_manager::gc_count ( ) const
inlinenodiscardnoexcept

Get the number of GC cycles performed.

Returns
GC cycle count

Definition at line 224 of file epoch_manager.h.

224 {
225 return gc_count_.load(std::memory_order_relaxed);
226 }

References gc_count_.

◆ in_critical_section()

bool kcenon::container::epoch_manager::in_critical_section ( ) const
inlinenodiscardnoexcept

Check if current thread is in critical section.

Returns
true if in critical section

Definition at line 95 of file epoch_manager.h.

95 {
96 return thread_epoch() != INACTIVE;
97 }

References INACTIVE, and thread_epoch().

Here is the call graph for this function:

◆ instance()

static epoch_manager & kcenon::container::epoch_manager::instance ( )
inlinestatic

Get the singleton instance.

Returns
Reference to the global epoch manager

Definition at line 63 of file epoch_manager.h.

63 {
65 return instance;
66 }
epoch_manager()=default
Private constructor for singleton.

References instance().

Referenced by kcenon::container::epoch_guard::epoch_guard(), instance(), and kcenon::container::epoch_guard::~epoch_guard().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ operator=() [1/2]

epoch_manager & kcenon::container::epoch_manager::operator= ( const epoch_manager & )
delete

◆ operator=() [2/2]

epoch_manager & kcenon::container::epoch_manager::operator= ( epoch_manager && )
delete

◆ pending_count()

size_t kcenon::container::epoch_manager::pending_count ( ) const
inlinenodiscard

Get the number of objects pending deletion.

Returns
Number of objects in retire lists

Definition at line 240 of file epoch_manager.h.

240 {
241 size_t total = 0;
242 for (size_t i = 0; i < NUM_EPOCHS; ++i) {
243 std::lock_guard<std::mutex> lock(retire_mutex_[i]);
244 total += retired_[i].size();
245 }
246 return total;
247 }

References NUM_EPOCHS, retire_mutex_, and retired_.

◆ reclaimed_count()

size_t kcenon::container::epoch_manager::reclaimed_count ( ) const
inlinenodiscardnoexcept

Get the total number of objects reclaimed.

Returns
Reclaimed object count

Definition at line 232 of file epoch_manager.h.

232 {
233 return reclaimed_count_.load(std::memory_order_relaxed);
234 }

References reclaimed_count_.

◆ thread_epoch()

static std::atomic< uint64_t > & kcenon::container::epoch_manager::thread_epoch ( )
inlinestaticprivate

Get thread-local epoch reference.

Returns
Reference to this thread's epoch

Definition at line 272 of file epoch_manager.h.

272 {
273 thread_local std::atomic<uint64_t> epoch{INACTIVE};
274 return epoch;
275 }

References INACTIVE.

Referenced by enter_critical(), exit_critical(), and in_critical_section().

Here is the caller graph for this function:

◆ try_gc()

size_t kcenon::container::epoch_manager::try_gc ( )
inline

Attempt garbage collection.

Advances the global epoch and reclaims memory from epochs that are safe to collect (all threads have exited that epoch).

Returns
Number of objects reclaimed

Definition at line 145 of file epoch_manager.h.

145 {
146 // Advance epoch
147 uint64_t current = global_epoch_.fetch_add(1, std::memory_order_acq_rel);
148
149 // Calculate which epoch is safe to collect
150 // We need 2 epoch advances before an epoch is safe
151 if (current < 2) {
152 return 0;
153 }
154
155 uint64_t safe_epoch = current - 2;
156 size_t bucket = safe_epoch % NUM_EPOCHS;
157
158 // Check if any thread is still in the safe epoch
159 // For simplicity, we just try to collect
160 // In production, you'd check all registered threads
161
162 std::vector<std::pair<void*, std::function<void(void*)>>> to_delete;
163 {
164 std::lock_guard<std::mutex> lock(retire_mutex_[bucket]);
165 to_delete = std::move(retired_[bucket]);
166 retired_[bucket].clear();
167 }
168
169 // Actually delete the objects
170 for (auto& [ptr, deleter] : to_delete) {
171 deleter(ptr);
172 }
173
174 gc_count_.fetch_add(1, std::memory_order_relaxed);
175 reclaimed_count_.fetch_add(to_delete.size(), std::memory_order_relaxed);
176
177 return to_delete.size();
178 }

References gc_count_, global_epoch_, NUM_EPOCHS, reclaimed_count_, retire_mutex_, and retired_.

Member Data Documentation

◆ gc_count_

std::atomic<size_t> kcenon::container::epoch_manager::gc_count_ {0}
private

Definition at line 278 of file epoch_manager.h.

278{0};

Referenced by force_gc(), gc_count(), and try_gc().

◆ global_epoch_

std::atomic<uint64_t> kcenon::container::epoch_manager::global_epoch_ {0}
private

Definition at line 277 of file epoch_manager.h.

277{0};

Referenced by current_epoch(), defer_delete(), enter_critical(), and try_gc().

◆ INACTIVE

uint64_t kcenon::container::epoch_manager::INACTIVE = UINT64_MAX
staticconstexpr

Sentinel value indicating thread is not in critical section.

Definition at line 52 of file epoch_manager.h.

Referenced by exit_critical(), in_critical_section(), and thread_epoch().

◆ NUM_EPOCHS

size_t kcenon::container::epoch_manager::NUM_EPOCHS = 3
staticconstexpr

Number of epochs in rotation (must be at least 3 for safety)

Definition at line 57 of file epoch_manager.h.

Referenced by defer_delete(), force_gc(), pending_count(), and try_gc().

◆ reclaimed_count_

std::atomic<size_t> kcenon::container::epoch_manager::reclaimed_count_ {0}
private

Definition at line 279 of file epoch_manager.h.

279{0};

Referenced by force_gc(), reclaimed_count(), and try_gc().

◆ retire_mutex_

std::array<std::mutex, NUM_EPOCHS> kcenon::container::epoch_manager::retire_mutex_
mutableprivate

Definition at line 281 of file epoch_manager.h.

Referenced by defer_delete(), force_gc(), pending_count(), and try_gc().

◆ retired_

std::array<std::vector<std::pair<void*, std::function<void(void*)> > >, NUM_EPOCHS> kcenon::container::epoch_manager::retired_
private

Definition at line 282 of file epoch_manager.h.

Referenced by defer_delete(), force_gc(), pending_count(), and try_gc().


The documentation for this class was generated from the following file: