15 std::initializer_list<std::pair<std::string, value>> init)
17 for (
const auto& [key,
value] : init) {
24 std::shared_lock other_lock(other.
mutex_);
34 std::unique_lock other_lock(other.mutex_);
35 values_ = std::move(other.values_);
36 read_count_ = other.read_count_.load();
37 write_count_ = other.write_count_.load();
38 bulk_read_count_ = other.bulk_read_count_.load();
39 bulk_write_count_ = other.bulk_write_count_.load();
41 other.read_count_ = 0;
42 other.write_count_ = 0;
43 other.bulk_read_count_ = 0;
44 other.bulk_write_count_ = 0;
64 std::scoped_lock lock(mutex_, other.mutex_);
65 values_ = std::move(other.values_);
66 write_count_.fetch_add(1, std::memory_order_relaxed);
73 std::shared_lock lock(
mutex_);
74 read_count_.fetch_add(1, std::memory_order_relaxed);
76 auto it =
values_.find(std::string(key));
85 std::unique_lock lock(
mutex_);
93 std::unique_lock lock(
mutex_);
96 auto it =
values_.find(std::string(key));
106 std::unique_lock lock(
mutex_);
113 std::shared_lock lock(
mutex_);
119 std::shared_lock lock(
mutex_);
125 std::shared_lock lock(
mutex_);
126 read_count_.fetch_add(1, std::memory_order_relaxed);
132 std::shared_lock lock(
mutex_);
133 read_count_.fetch_add(1, std::memory_order_relaxed);
135 std::vector<std::string> result;
136 result.reserve(
values_.size());
139 result.push_back(key);
147 std::unique_lock lock(
mutex_);
154 std::shared_lock lock(
mutex_);
155 read_count_.fetch_add(1, std::memory_order_relaxed);
165 std::shared_ptr<thread_safe_container> container)
167 std::unique_lock lock(
mutex_);
173 const std::string& key)
const
175 std::shared_lock lock(
mutex_);
176 read_count_.fetch_add(1, std::memory_order_relaxed);
180 return it->second.get<std::shared_ptr<thread_safe_container>>().value_or(
nullptr);
186 const value& expected,
187 const value& desired)
189 std::unique_lock lock(
mutex_);
192 auto it =
values_.find(std::string(key));
194 if (it->second == expected) {
195 it->second = desired;
204 std::shared_lock lock(
mutex_);
216 std::shared_lock lock(
mutex_);
217 read_count_.fetch_add(1, std::memory_order_relaxed);
219 std::string result =
"{";
232 case '"': result +=
"\\\"";
break;
233 case '\\': result +=
"\\\\";
break;
234 case '\n': result +=
"\\n";
break;
235 case '\r': result +=
"\\r";
break;
236 case '\t': result +=
"\\t";
break;
237 default: result += c;
250 std::shared_lock lock(
mutex_);
251 read_count_.fetch_add(1, std::memory_order_relaxed);
253 std::vector<uint8_t> result;
256 uint32_t count =
static_cast<uint32_t
>(
values_.size());
257 result.insert(result.end(),
258 reinterpret_cast<const uint8_t*
>(&count),
259 reinterpret_cast<const uint8_t*
>(&count) +
sizeof(count));
264 uint32_t key_len =
static_cast<uint32_t
>(key.size());
265 result.insert(result.end(),
266 reinterpret_cast<const uint8_t*
>(&key_len),
267 reinterpret_cast<const uint8_t*
>(&key_len) +
sizeof(key_len));
268 result.insert(result.end(), key.begin(), key.end());
272 uint32_t value_len =
static_cast<uint32_t
>(value_data.size());
273 result.insert(result.end(),
274 reinterpret_cast<const uint8_t*
>(&value_len),
275 reinterpret_cast<const uint8_t*
>(&value_len) +
sizeof(value_len));
276 result.insert(result.end(), value_data.begin(), value_data.end());
283 const std::vector<uint8_t>& data)
285 if (data.size() <
sizeof(uint32_t)) {
289 auto container = std::make_shared<thread_safe_container>();
294 std::memcpy(&count, data.data() + offset,
sizeof(count));
295 offset +=
sizeof(count);
298 for (uint32_t i = 0; i < count; ++i) {
299 if (offset +
sizeof(uint32_t) > data.size()) {
305 std::memcpy(&key_len, data.data() + offset,
sizeof(key_len));
306 offset +=
sizeof(key_len);
308 if (offset + key_len +
sizeof(uint32_t) > data.size()) {
312 std::string key(data.begin() + offset, data.begin() + offset + key_len);
317 std::memcpy(&value_len, data.data() + offset,
sizeof(value_len));
318 offset +=
sizeof(value_len);
320 if (offset + value_len > data.size()) {
325 std::vector<uint8_t> value_data(data.begin() + offset,
326 data.begin() + offset + value_len);
331 container->values_[key] = std::move(*value_opt);
340 std::unique_lock lock(
mutex_);
345 auto [new_it, inserted] =
values_.emplace(key,
value(key));
346 return new_it->second;
354 auto new_snapshot = std::make_shared<thread_safe_container::value_map>(
355 container_->bulk_read([](
const auto& map) { return map; })
void update_snapshot()
Update snapshot from container.
std::shared_ptr< thread_safe_container > container_
std::shared_mutex snapshot_mutex_
Thread-safe container with lock optimization.
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.
void clear()
Clear all values.
thread_safe_container()=default
Default constructor.
bool empty() const
Check if container is empty.
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.
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.
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.
std::string to_json() const
Convert to JSON representation.
std::string_view name() const noexcept
Get the name of this value (lock-free, immutable)
static std::optional< value > deserialize(const std::vector< uint8_t > &data)
Deserialize from binary format (legacy compatible)
std::vector< uint8_t > serialize() const
Serialize to binary format (legacy compatible)