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

True lock-free reader using RCU (Read-Copy-Update) pattern. More...

#include <thread_safe_container.h>

Collaboration diagram for kcenon::container::lockfree_container_reader:
Collaboration graph

Public Types

using snapshot_type = std::unordered_map<std::string, value>
 
using snapshot_ptr = std::shared_ptr<const snapshot_type>
 

Public Member Functions

 lockfree_container_reader (std::shared_ptr< thread_safe_container > container)
 Construct reader from container.
 
 lockfree_container_reader (const lockfree_container_reader &other)
 Copy constructor.
 
 lockfree_container_reader (lockfree_container_reader &&other) noexcept
 Move constructor.
 
lockfree_container_readeroperator= (const lockfree_container_reader &other)
 Copy assignment.
 
lockfree_container_readeroperator= (lockfree_container_reader &&other) noexcept
 Move assignment.
 
 ~lockfree_container_reader ()=default
 Destructor.
 
template<concepts::ValueVariantType T>
std::optional< T > get (std::string_view key) const noexcept
 Lock-free typed value read.
 
bool contains (std::string_view key) const noexcept
 Lock-free value existence check.
 
size_t size () const noexcept
 Lock-free snapshot size check.
 
bool empty () const noexcept
 Lock-free empty check.
 
std::vector< std::string > keys () const
 Get all keys from snapshot (lock-free)
 
template<typename Func >
void for_each (Func &&func) const
 Iterate over snapshot (lock-free for snapshot access)
 
void refresh ()
 Refresh snapshot from source container.
 
size_t refresh_count () const noexcept
 Get the number of refreshes performed.
 
std::shared_ptr< thread_safe_containersource () const noexcept
 Get the source container.
 

Private Attributes

std::shared_ptr< thread_safe_containercontainer_
 
snapshot_ptr snapshot_
 
std::atomic< size_t > refresh_count_ {0}
 

Detailed Description

True lock-free reader using RCU (Read-Copy-Update) pattern.

Unlike snapshot_reader which still uses a shared_mutex for snapshot access, this class provides genuinely lock-free reads using atomic shared_ptr operations. The trade-off is that reads may return slightly stale data between refreshes.

Properties:

  • Read: Wait-free O(1) - no locks, no blocking, no spinning
  • Refresh: Blocking (acquires source container lock)
  • Memory: Automatic reclamation via shared_ptr reference counting

Use this when:

  • You need true lock-free reads (e.g., signal handlers, real-time systems)
  • Read performance is critical and slight staleness is acceptable
  • You have many concurrent readers
// Create lock-free reader
auto container = std::make_shared<thread_safe_container>();
lockfree_container_reader reader(container);
// Lock-free reads from any thread
auto value = reader.get<int>("counter"); // No locks!
// Periodic refresh (e.g., from background thread)
reader.refresh();
True lock-free reader using RCU (Read-Copy-Update) pattern.
Enhanced type-safe value with perfect legacy compatibility.
Definition value.h:129
std::optional< T > get() const
Type-safe getter with optional return.
Definition value.h:213

Definition at line 383 of file thread_safe_container.h.

Member Typedef Documentation

◆ snapshot_ptr

◆ snapshot_type

using kcenon::container::lockfree_container_reader::snapshot_type = std::unordered_map<std::string, value>

Definition at line 385 of file thread_safe_container.h.

Constructor & Destructor Documentation

◆ lockfree_container_reader() [1/3]

kcenon::container::lockfree_container_reader::lockfree_container_reader ( std::shared_ptr< thread_safe_container > container)
inlineexplicit

Construct reader from container.

Parameters
containerThe thread-safe container to read from

Definition at line 392 of file thread_safe_container.h.

393 : container_(std::move(container))
394 , snapshot_(std::make_shared<const snapshot_type>())
395 {
396 refresh();
397 }
std::shared_ptr< thread_safe_container > container_
void refresh()
Refresh snapshot from source container.

References refresh().

Here is the call graph for this function:

◆ lockfree_container_reader() [2/3]

kcenon::container::lockfree_container_reader::lockfree_container_reader ( const lockfree_container_reader & other)
inline

Copy constructor.

Definition at line 402 of file thread_safe_container.h.

403 : container_(other.container_)
404 , snapshot_(std::atomic_load_explicit(&other.snapshot_, std::memory_order_acquire))
405 {}

◆ lockfree_container_reader() [3/3]

kcenon::container::lockfree_container_reader::lockfree_container_reader ( lockfree_container_reader && other)
inlinenoexcept

Move constructor.

Definition at line 410 of file thread_safe_container.h.

411 : container_(std::move(other.container_))
412 , snapshot_(std::atomic_load_explicit(&other.snapshot_, std::memory_order_acquire))
413 {}

◆ ~lockfree_container_reader()

kcenon::container::lockfree_container_reader::~lockfree_container_reader ( )
default

Destructor.

Member Function Documentation

◆ contains()

bool kcenon::container::lockfree_container_reader::contains ( std::string_view key) const
inlinenodiscardnoexcept

Lock-free value existence check.

Parameters
keyThe key to check
Returns
true if key exists in snapshot, false otherwise

Thread safety: Safe to call concurrently with any operation

Definition at line 479 of file thread_safe_container.h.

479 {
480 auto snap = std::atomic_load_explicit(&snapshot_, std::memory_order_acquire);
481 if (!snap) {
482 return false;
483 }
484 return snap->find(std::string(key)) != snap->end();
485 }

References snapshot_.

◆ empty()

bool kcenon::container::lockfree_container_reader::empty ( ) const
inlinenodiscardnoexcept

Lock-free empty check.

Returns
true if snapshot is empty, false otherwise

Thread safety: Safe to call concurrently with any operation

Definition at line 506 of file thread_safe_container.h.

506 {
507 return size() == 0;
508 }
size_t size() const noexcept
Lock-free snapshot size check.

References size().

Here is the call graph for this function:

◆ for_each()

template<typename Func >
void kcenon::container::lockfree_container_reader::for_each ( Func && func) const
inline

Iterate over snapshot (lock-free for snapshot access)

The callback is called for each key-value pair in the snapshot. The iteration itself is lock-free, but the callback may perform locking operations.

Template Parameters
FuncCallback function type: void(const std::string&, const value&)
Parameters
funcCallback to apply to each key-value pair

Thread safety: Safe to call concurrently with any operation

Definition at line 542 of file thread_safe_container.h.

542 {
543 auto snap = std::atomic_load_explicit(&snapshot_, std::memory_order_acquire);
544 if (snap) {
545 for (const auto& [key, val] : *snap) {
546 func(key, val);
547 }
548 }
549 }

References snapshot_.

◆ get()

template<concepts::ValueVariantType T>
std::optional< T > kcenon::container::lockfree_container_reader::get ( std::string_view key) const
inlinenodiscardnoexcept

Lock-free typed value read.

This operation is wait-free: it completes in O(1) time regardless of what other threads are doing. The snapshot may be stale; call refresh() to update.

Template Parameters
TThe expected value type (must satisfy ValueVariantType)
Parameters
keyThe key to look up
Returns
Optional containing value if found and type matches

Thread safety: Safe to call concurrently with any operation including refresh()

Definition at line 458 of file thread_safe_container.h.

458 {
459 auto snap = std::atomic_load_explicit(&snapshot_, std::memory_order_acquire);
460 if (!snap) {
461 return std::nullopt;
462 }
463
464 auto it = snap->find(std::string(key));
465 if (it != snap->end()) {
466 return it->second.get<T>();
467 }
468 return std::nullopt;
469 }

References snapshot_.

◆ keys()

std::vector< std::string > kcenon::container::lockfree_container_reader::keys ( ) const
inlinenodiscard

Get all keys from snapshot (lock-free)

Returns
Vector of keys in the current snapshot

Thread safety: Safe to call concurrently with any operation

Definition at line 517 of file thread_safe_container.h.

517 {
518 auto snap = std::atomic_load_explicit(&snapshot_, std::memory_order_acquire);
519 std::vector<std::string> result;
520 if (snap) {
521 result.reserve(snap->size());
522 for (const auto& [key, val] : *snap) {
523 result.push_back(key);
524 }
525 }
526 return result;
527 }

References snapshot_.

◆ operator=() [1/2]

lockfree_container_reader & kcenon::container::lockfree_container_reader::operator= ( const lockfree_container_reader & other)
inline

Copy assignment.

Definition at line 418 of file thread_safe_container.h.

418 {
419 if (this != &other) {
420 container_ = other.container_;
421 auto new_snapshot = std::atomic_load_explicit(&other.snapshot_, std::memory_order_acquire);
422 std::atomic_store_explicit(&snapshot_, new_snapshot, std::memory_order_release);
423 }
424 return *this;
425 }

References container_, and snapshot_.

◆ operator=() [2/2]

lockfree_container_reader & kcenon::container::lockfree_container_reader::operator= ( lockfree_container_reader && other)
inlinenoexcept

Move assignment.

Definition at line 430 of file thread_safe_container.h.

430 {
431 if (this != &other) {
432 container_ = std::move(other.container_);
433 auto new_snapshot = std::atomic_load_explicit(&other.snapshot_, std::memory_order_acquire);
434 std::atomic_store_explicit(&snapshot_, new_snapshot, std::memory_order_release);
435 }
436 return *this;
437 }

References container_, and snapshot_.

◆ refresh()

void kcenon::container::lockfree_container_reader::refresh ( )
inline

Refresh snapshot from source container.

This operation acquires the container's read lock to create a new snapshot. After this call returns, subsequent lock-free reads will see the updated data.

Thread safety: Safe to call concurrently with reads, but multiple concurrent refreshes may waste work (only one will "win").

Definition at line 560 of file thread_safe_container.h.

560 {
561 auto new_snapshot = std::make_shared<snapshot_type>();
562 container_->for_each([&new_snapshot](const std::string& key, const value& val) {
563 new_snapshot->emplace(key, val);
564 });
565 std::atomic_store_explicit(&snapshot_,
566 snapshot_ptr(new_snapshot),
567 std::memory_order_release);
568 refresh_count_.fetch_add(1, std::memory_order_relaxed);
569 }
std::shared_ptr< const snapshot_type > snapshot_ptr

References container_, refresh_count_, and snapshot_.

Referenced by lockfree_container_reader().

Here is the caller graph for this function:

◆ refresh_count()

size_t kcenon::container::lockfree_container_reader::refresh_count ( ) const
inlinenodiscardnoexcept

Get the number of refreshes performed.

Returns
Refresh count since construction

Definition at line 575 of file thread_safe_container.h.

575 {
576 return refresh_count_.load(std::memory_order_relaxed);
577 }

References refresh_count_.

◆ size()

size_t kcenon::container::lockfree_container_reader::size ( ) const
inlinenodiscardnoexcept

Lock-free snapshot size check.

Returns
Number of values in the current snapshot

Thread safety: Safe to call concurrently with any operation

Definition at line 494 of file thread_safe_container.h.

494 {
495 auto snap = std::atomic_load_explicit(&snapshot_, std::memory_order_acquire);
496 return snap ? snap->size() : 0;
497 }

References snapshot_.

Referenced by empty().

Here is the caller graph for this function:

◆ source()

std::shared_ptr< thread_safe_container > kcenon::container::lockfree_container_reader::source ( ) const
inlinenodiscardnoexcept

Get the source container.

Returns
Shared pointer to the source container

Definition at line 583 of file thread_safe_container.h.

583 {
584 return container_;
585 }

References container_.

Member Data Documentation

◆ container_

std::shared_ptr<thread_safe_container> kcenon::container::lockfree_container_reader::container_
private

Definition at line 588 of file thread_safe_container.h.

Referenced by operator=(), operator=(), refresh(), and source().

◆ refresh_count_

std::atomic<size_t> kcenon::container::lockfree_container_reader::refresh_count_ {0}
private

Definition at line 590 of file thread_safe_container.h.

590{0};

Referenced by refresh(), and refresh_count().

◆ snapshot_

snapshot_ptr kcenon::container::lockfree_container_reader::snapshot_
private

Definition at line 589 of file thread_safe_container.h.

Referenced by contains(), for_each(), get(), keys(), operator=(), operator=(), refresh(), and size().


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