7#include <unordered_map>
15#include <condition_variable>
22 class lockfree_container_reader;
23 class auto_refresh_reader;
34 using value_map = std::unordered_map<std::string, value>;
73 std::optional<value>
get(std::string_view key)
const;
81 template<concepts::ValueVariantType T>
82 std::optional<T>
get_typed(std::string_view key)
const {
83 std::shared_lock lock(
mutex_);
84 auto it =
values_.find(std::string(key));
86 return it->second.get<T>();
104 template<concepts::ValueVariantType T>
106 set(key,
value(key, std::forward<T>(val)));
114 bool remove(std::string_view key);
134 bool contains(std::string_view key)
const;
139 std::vector<std::string>
keys()
const;
152 std::optional<value>
get_variant(
const std::string& key)
const;
160 std::shared_ptr<thread_safe_container> container);
167 std::shared_ptr<thread_safe_container>
get_container(
const std::string& key)
const;
174 template<concepts::KeyValueCallback Func>
176 std::shared_lock lock(
mutex_);
177 for (
const auto& [key, val] :
values_) {
187 template<concepts::MutableKeyValueCallback Func>
189 std::unique_lock lock(
mutex_);
190 for (
auto& [key, val] :
values_) {
200 template<concepts::ValueMapCallback<value_map> Func>
202 std::unique_lock lock(
mutex_);
213 template<concepts::ConstValueMapCallback<value_map> Func>
215 std::shared_lock lock(
mutex_);
228 const value& expected,
229 const value& desired);
257 static std::shared_ptr<thread_safe_container>
deserialize(
258 const std::vector<uint8_t>& data);
294 std::chrono::milliseconds refresh_interval);
318 using snapshot_ptr = std::shared_ptr<const thread_safe_container::value_map>;
330 template<concepts::ValueVariantType T>
331 std::optional<T>
get(std::string_view key)
const {
335 auto it =
snapshot_->find(std::string(key));
337 return it->second.get<T>();
412 ,
snapshot_(std::atomic_load_explicit(&other.snapshot_, std::memory_order_acquire))
419 if (
this != &other) {
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);
431 if (
this != &other) {
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);
457 template<concepts::ValueVariantType T>
458 [[nodiscard]] std::optional<T>
get(std::string_view key)
const noexcept {
459 auto snap = std::atomic_load_explicit(&
snapshot_, std::memory_order_acquire);
464 auto it = snap->find(std::string(key));
465 if (it != snap->end()) {
466 return it->second.get<T>();
479 [[nodiscard]]
bool contains(std::string_view key)
const noexcept {
480 auto snap = std::atomic_load_explicit(&
snapshot_, std::memory_order_acquire);
484 return snap->find(std::string(key)) != snap->end();
494 [[nodiscard]]
size_t size() const noexcept {
495 auto snap = std::atomic_load_explicit(&
snapshot_, std::memory_order_acquire);
496 return snap ? snap->size() : 0;
506 [[nodiscard]]
bool empty() const noexcept {
517 [[nodiscard]] std::vector<std::string>
keys()
const {
518 auto snap = std::atomic_load_explicit(&
snapshot_, std::memory_order_acquire);
519 std::vector<std::string> result;
521 result.reserve(snap->size());
522 for (
const auto& [key, val] : *snap) {
523 result.push_back(key);
541 template<
typename Func>
543 auto snap = std::atomic_load_explicit(&
snapshot_, std::memory_order_acquire);
545 for (
const auto& [key, val] : *snap) {
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);
567 std::memory_order_release);
583 [[nodiscard]] std::shared_ptr<thread_safe_container>
source() const noexcept {
654 std::lock_guard<std::mutex> lock(
mutex_);
671 std::lock_guard<std::mutex> lock(
mutex_);
692 template<concepts::ValueVariantType T>
693 [[nodiscard]] std::optional<T>
get(std::string_view key)
const noexcept {
702 [[nodiscard]]
bool contains(std::string_view key)
const noexcept {
710 [[nodiscard]]
size_t size() const noexcept {
718 [[nodiscard]]
bool empty() const noexcept {
726 [[nodiscard]] std::vector<std::string>
keys()
const {
735 template<
typename Func>
737 reader_->for_each(std::forward<Func>(func));
754 return reader_->refresh_count();
761 [[nodiscard]] std::shared_ptr<lockfree_container_reader>
reader() const noexcept {
769 [[nodiscard]] std::shared_ptr<thread_safe_container>
source() const noexcept {
776 std::unique_lock<std::mutex> lock(
mutex_);
785 std::shared_ptr<lockfree_container_reader>
reader_;
789 std::condition_variable
cv_;
798 return std::make_shared<lockfree_container_reader>(shared_from_this());
803 std::chrono::milliseconds refresh_interval) {
804 return std::make_shared<auto_refresh_reader>(shared_from_this(), refresh_interval);
Auto-refreshing lock-free reader.
auto_refresh_reader(std::shared_ptr< thread_safe_container > container, std::chrono::milliseconds refresh_interval)
Construct auto-refresh reader.
bool empty() const noexcept
Lock-free empty check.
std::shared_ptr< thread_safe_container > source() const noexcept
Get the source container.
std::condition_variable cv_
void for_each(Func &&func) const
Iterate over snapshot.
std::vector< std::string > keys() const
Get all keys from snapshot.
std::optional< T > get(std::string_view key) const noexcept
Lock-free typed value read.
auto_refresh_reader & operator=(auto_refresh_reader &&)=delete
std::thread refresh_thread_
std::shared_ptr< lockfree_container_reader > reader() const noexcept
Get the underlying lock-free reader.
void stop()
Stop the auto-refresh thread.
auto_refresh_reader & operator=(const auto_refresh_reader &)=delete
auto_refresh_reader(const auto_refresh_reader &)=delete
auto_refresh_reader(auto_refresh_reader &&)=delete
std::chrono::milliseconds refresh_interval_
std::chrono::milliseconds refresh_interval() const noexcept
Get the refresh interval.
void refresh()
Manual refresh (in addition to automatic)
size_t refresh_count() const noexcept
Get the number of refreshes performed.
size_t size() const noexcept
Lock-free snapshot size check.
~auto_refresh_reader()
Destructor - stops the refresh thread.
bool is_running() const noexcept
Check if auto-refresh is running.
std::shared_ptr< lockfree_container_reader > reader_
bool contains(std::string_view key) const noexcept
Lock-free value existence check.
True lock-free reader using RCU (Read-Copy-Update) pattern.
size_t refresh_count() const noexcept
Get the number of refreshes performed.
lockfree_container_reader(const lockfree_container_reader &other)
Copy constructor.
bool empty() const noexcept
Lock-free empty check.
void for_each(Func &&func) const
Iterate over snapshot (lock-free for snapshot access)
bool contains(std::string_view key) const noexcept
Lock-free value existence check.
std::shared_ptr< const snapshot_type > snapshot_ptr
std::shared_ptr< thread_safe_container > container_
lockfree_container_reader(std::shared_ptr< thread_safe_container > container)
Construct reader from container.
std::shared_ptr< thread_safe_container > source() const noexcept
Get the source container.
~lockfree_container_reader()=default
Destructor.
void refresh()
Refresh snapshot from source container.
std::optional< T > get(std::string_view key) const noexcept
Lock-free typed value read.
std::atomic< size_t > refresh_count_
lockfree_container_reader & operator=(lockfree_container_reader &&other) noexcept
Move assignment.
size_t size() const noexcept
Lock-free snapshot size check.
std::vector< std::string > keys() const
Get all keys from snapshot (lock-free)
std::unordered_map< std::string, value > snapshot_type
lockfree_container_reader(lockfree_container_reader &&other) noexcept
Move constructor.
lockfree_container_reader & operator=(const lockfree_container_reader &other)
Copy assignment.
Snapshot-based reader for frequently accessed data.
snapshot_reader(std::shared_ptr< thread_safe_container > container)
void update_snapshot()
Update snapshot from container.
std::optional< T > get(std::string_view key) const
Get value from snapshot (lock-protected read of snapshot)
std::shared_ptr< const thread_safe_container::value_map > snapshot_ptr
std::shared_ptr< thread_safe_container > container_
std::shared_mutex snapshot_mutex_
Thread-safe container with lock optimization.
std::shared_ptr< lockfree_container_reader > create_lockfree_reader()
Create a lock-free reader for this container.
std::optional< value > get(std::string_view key) const
Get value by key (thread-safe read)
bool contains(std::string_view key) const
Check if key exists.
thread_safe_container & operator=(const thread_safe_container &other)
Copy assignment (thread-safe)
std::shared_ptr< thread_safe_container > get_container(const std::string &key) const
Get a nested container.
value & operator[](const std::string &key)
Array-style access (creates if not exists)
Statistics get_statistics() const
size_t size() const
Get the number of values.
std::unordered_map< std::string, value > value_map
void clear()
Clear all values.
thread_safe_container()=default
Default constructor.
bool empty() const
Check if container is empty.
auto bulk_read(Func &&reader) const
Bulk read operation.
void bulk_update(Func &&updater)
Bulk update operation with minimal lock contention.
std::shared_ptr< auto_refresh_reader > create_auto_refresh_reader(std::chrono::milliseconds refresh_interval)
Create an auto-refreshing lock-free reader.
value_map::const_iterator const_iterator
std::optional< T > get_typed(std::string_view key) const
Get typed value by key.
std::vector< std::string > keys() const
Get all keys.
std::atomic< size_t > bulk_write_count_
static std::shared_ptr< thread_safe_container > deserialize(const std::vector< uint8_t > &data)
Deserialize from binary.
std::atomic< size_t > read_count_
std::optional< value > get_variant(const std::string &key) const
Get a value as variant value.
std::atomic< size_t > bulk_read_count_
std::string to_json() const
Serialize container to JSON.
void set_variant(const value &val)
Set a value directly using variant value.
void for_each_mut(Func &&func)
Apply a function to all values (mutable)
bool remove(std::string_view key)
Remove value by key.
std::atomic< size_t > write_count_
void set(std::string_view key, value value)
Set value for key (thread-safe write)
void set_container(const std::string &key, std::shared_ptr< thread_safe_container > container)
Set a nested container.
std::vector< uint8_t > serialize() const
Serialize container to binary.
value_map::iterator iterator
void set_typed(std::string_view key, T &&val)
Set typed value for key.
void for_each(Func &&func) const
Apply a function to all values (read-only)
bool compare_exchange(std::string_view key, const value &expected, const value &desired)
Atomic compare and swap.
Enhanced type-safe value with perfect legacy compatibility.