Thread System 0.3.1
High-performance C++20 thread pool with work stealing and DAG scheduling
Loading...
Searching...
No Matches
kcenon::thread::hazard_pointer Class Reference

Single hazard pointer that protects one object from reclamation Uses RAII pattern - automatically releases protection on destruction. More...

#include <hazard_pointer.h>

Collaboration diagram for kcenon::thread::hazard_pointer:
Collaboration graph

Public Member Functions

 hazard_pointer ()
 Default constructor - acquires a hazard pointer slot.
 
 hazard_pointer (hazard_pointer &&other) noexcept
 Move constructor.
 
hazard_pointeroperator= (hazard_pointer &&other) noexcept
 Move assignment.
 
 ~hazard_pointer ()
 Destructor - automatically releases protection.
 
 hazard_pointer (const hazard_pointer &)=delete
 Non-copyable.
 
hazard_pointeroperator= (const hazard_pointer &)=delete
 
template<typename T >
void protect (T *ptr) noexcept
 Protect a pointer from reclamation.
 
void reset () noexcept
 Release protection.
 
bool is_protected () const noexcept
 Check if currently protecting a pointer.
 
void * get_protected () const noexcept
 Get the protected pointer (may be null)
 

Private Attributes

std::atomic< void * > * slot_
 
size_t slot_index_
 

Static Private Attributes

static const void * SLOT_OWNED_MARKER = reinterpret_cast<void*>(0x1)
 

Detailed Description

Single hazard pointer that protects one object from reclamation Uses RAII pattern - automatically releases protection on destruction.

Definition at line 110 of file hazard_pointer.h.

Constructor & Destructor Documentation

◆ hazard_pointer() [1/3]

kcenon::thread::hazard_pointer::hazard_pointer ( )

Default constructor - acquires a hazard pointer slot.

Definition at line 241 of file hazard_pointer.cpp.

241 : slot_(nullptr), slot_index_(0) {
243
244 // Find an available slot (slot value is nullptr means available)
245 for (size_t i = 0; i < detail::thread_hazard_list::MAX_HAZARDS_PER_THREAD; ++i) {
246 void* expected = nullptr;
247 // Try to claim this slot with SLOT_OWNED_MARKER
248 // Use acq_rel: acquire to synchronize with prior release of the slot,
249 // release to publish ownership to scanning threads
250 if (thread_list->hazards[i].compare_exchange_strong(
251 expected, const_cast<void*>(SLOT_OWNED_MARKER), std::memory_order_acq_rel,
252 std::memory_order_relaxed)) {
253 slot_ = &thread_list->hazards[i];
254 slot_index_ = i;
255 // Slot is now owned with SLOT_OWNED_MARKER
256 return;
257 }
258 }
259
260 throw std::runtime_error("Hazard pointer slots exhausted");
261}
static hazard_pointer_registry & instance()
thread_hazard_list * get_thread_list()
Get or create thread-local hazard list.
static const void * SLOT_OWNED_MARKER
std::atomic< void * > * slot_
static constexpr size_t MAX_HAZARDS_PER_THREAD

References kcenon::thread::detail::hazard_pointer_registry::get_thread_list(), kcenon::thread::detail::hazard_pointer_registry::instance(), kcenon::thread::detail::thread_hazard_list::MAX_HAZARDS_PER_THREAD, slot_, slot_index_, and SLOT_OWNED_MARKER.

Referenced by kcenon::thread::hazard_pointer_domain< T >::acquire().

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

◆ hazard_pointer() [2/3]

kcenon::thread::hazard_pointer::hazard_pointer ( hazard_pointer && other)
noexcept

Move constructor.

Definition at line 263 of file hazard_pointer.cpp.

264 : slot_(other.slot_), slot_index_(other.slot_index_) {
265 other.slot_ = nullptr;
266 other.slot_index_ = 0;
267}

◆ ~hazard_pointer()

kcenon::thread::hazard_pointer::~hazard_pointer ( )

Destructor - automatically releases protection.

Definition at line 282 of file hazard_pointer.cpp.

282 {
283 if (slot_) {
284 // Release the slot back to the pool
285 slot_->store(nullptr, std::memory_order_release);
286 }
287}

References slot_.

◆ hazard_pointer() [3/3]

kcenon::thread::hazard_pointer::hazard_pointer ( const hazard_pointer & )
delete

Non-copyable.

Member Function Documentation

◆ get_protected()

void * kcenon::thread::hazard_pointer::get_protected ( ) const
noexcept

Get the protected pointer (may be null)

Definition at line 304 of file hazard_pointer.cpp.

304 {
305 if (!slot_) {
306 return nullptr;
307 }
308 void* ptr = slot_->load(std::memory_order_acquire);
309 // Return nullptr if slot is just owned but not protecting anything
310 return (ptr == SLOT_OWNED_MARKER) ? nullptr : ptr;
311}

References slot_, and SLOT_OWNED_MARKER.

◆ is_protected()

bool kcenon::thread::hazard_pointer::is_protected ( ) const
noexcept

Check if currently protecting a pointer.

Definition at line 296 of file hazard_pointer.cpp.

296 {
297 if (!slot_) {
298 return false;
299 }
300 void* ptr = slot_->load(std::memory_order_acquire);
301 return ptr != nullptr && ptr != SLOT_OWNED_MARKER;
302}

References slot_, and SLOT_OWNED_MARKER.

Referenced by kcenon::thread::hazard_pointer_domain< T >::thread_retire_list::scan_and_reclaim().

Here is the caller graph for this function:

◆ operator=() [1/2]

hazard_pointer & kcenon::thread::hazard_pointer::operator= ( const hazard_pointer & )
delete

◆ operator=() [2/2]

hazard_pointer & kcenon::thread::hazard_pointer::operator= ( hazard_pointer && other)
noexcept

Move assignment.

Definition at line 269 of file hazard_pointer.cpp.

269 {
270 if (this != &other) {
271 reset();
272
273 slot_ = other.slot_;
274 slot_index_ = other.slot_index_;
275
276 other.slot_ = nullptr;
277 other.slot_index_ = 0;
278 }
279 return *this;
280}
void reset() noexcept
Release protection.

◆ protect()

template<typename T >
void kcenon::thread::hazard_pointer::protect ( T * ptr)
inlinenoexcept

Protect a pointer from reclamation.

Parameters
ptrPointer to protect
Note
Thread-safe, can be called concurrently
Uses memory_order_seq_cst to ensure the hazard pointer store is globally visible before any subsequent load of the shared pointer in the protect-then-verify pattern. On weak memory architectures (ARM), release + acquire is insufficient because the store and subsequent load can be reordered.

Definition at line 137 of file hazard_pointer.h.

137 {
138 if (slot_) {
139 slot_->store(static_cast<void*>(ptr), std::memory_order_seq_cst);
140 }
141 }

References slot_.

◆ reset()

void kcenon::thread::hazard_pointer::reset ( )
noexcept

Release protection.

Note
After reset(), the previously protected pointer may be reclaimed
Keeps the slot owned but clears the protected pointer

Definition at line 289 of file hazard_pointer.cpp.

289 {
290 if (slot_) {
291 // Clear protection but keep slot owned
292 slot_->store(const_cast<void*>(SLOT_OWNED_MARKER), std::memory_order_release);
293 }
294}

References slot_, and SLOT_OWNED_MARKER.

Member Data Documentation

◆ slot_

std::atomic<void*>* kcenon::thread::hazard_pointer::slot_
private

◆ slot_index_

size_t kcenon::thread::hazard_pointer::slot_index_
private

Definition at line 159 of file hazard_pointer.h.

Referenced by hazard_pointer().

◆ SLOT_OWNED_MARKER

const void* kcenon::thread::hazard_pointer::SLOT_OWNED_MARKER = reinterpret_cast<void*>(0x1)
inlinestaticprivate

Definition at line 156 of file hazard_pointer.h.

Referenced by get_protected(), hazard_pointer(), is_protected(), and reset().


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