SiddiqSoft.RWLEnvelope
1.5.1
dotnet add package SiddiqSoft.RWLEnvelope --version 1.5.1
NuGet\Install-Package SiddiqSoft.RWLEnvelope -Version 1.5.1
<PackageReference Include="SiddiqSoft.RWLEnvelope" Version="1.5.1" />
<PackageVersion Include="SiddiqSoft.RWLEnvelope" Version="1.5.1" />
<PackageReference Include="SiddiqSoft.RWLEnvelope" />
paket add SiddiqSoft.RWLEnvelope --version 1.5.1
#r "nuget: SiddiqSoft.RWLEnvelope, 1.5.1"
#:package SiddiqSoft.RWLEnvelope@1.5.1
#addin nuget:?package=SiddiqSoft.RWLEnvelope&version=1.5.1
#tool nuget:?package=SiddiqSoft.RWLEnvelope&version=1.5.1
RWLEnvelope : A simple read-writer lock envelope
Quick Start
RWLEnvelope is a header-only C++ template library that provides a simple, convenient envelope-access model for thread-safe access to objects using reader-writer locks.
#include "siddiqsoft/RWLEnvelope.hpp"
// Declare a map as container and initialize it with some values
// Using initializer list constructor for convenient initialization.
Note the brace-count as we use brace initializer to construct the RWLEnvelope
// while constructing its internal storage with the std::map initializer!
siddiqsoft::RWLEnvelope<std::map<std::string, int>> data({
{"key", 1010},
{"key2", 2020},
{"key3", 3030}
});
// Read-only access
auto val = data.observe([](const auto& m) noexcept -> auto {
return m.value("key", 0);
});
// Read-write access
data.mutate([](auto& m) noexcept {
m["key"] = 42;
});
std::println(std::cerr, "Contents: {}", data.snapshot());
Why RWLEnvelope?
- Automatic Lock Management: No manual lock/unlock needed
- Clear Intent:
observe()for reads,mutate()for writes - Exception Safe: Locks released properly even if callbacks throw
- Zero Overhead: Header-only, no runtime cost beyond std::shared_mutex
- Works with Any Type: Not limited to specific containers
- Convenient Initialization: Supports initializer lists for easy construction
Documentation
The full documentation includes:
- Detailed API reference
- Usage patterns and examples
- Performance considerations
- Thread safety guarantees
- Requirements and limitations
Installation
NuGet Package
Install-Package SiddiqSoft.RWLEnvelope
Header-Only
Copy include/siddiqsoft/RWLEnvelope.hpp to your project.
Requirements
- C++ Standard: C++20 or later (requires C++20 concepts support)
- Compiler: Must support
[[nodiscard]]attribute and C++20 concepts - Headers:
<shared_mutex>,<functional>,<tuple>,<utility>,<concepts> - Optional: nlohmann/json library for JSON serialization support
Key Features
Multiple Concurrent Readers
// Multiple threads can read simultaneously
data.observe([](const auto& m) noexcept {
return m.at("key");
});
Exclusive Writer
// Only one thread can write at a time
data.mutate([](auto& m) noexcept {
m["key"] = 42;
});
Direct Lock Access
// For complex operations
if (auto [map, lock] = data.writeLock(); lock) {
map["key"] = 42;
map.erase("old_key");
}
Snapshot for External Processing
// Get a copy to process outside the lock
std::vector<int> copy = data.snapshot();
std::sort(copy.begin(), copy.end());
Initializer List Construction
// Construct with initializer list - works with any container supporting std::initializer_list
siddiqsoft::RWLEnvelope<std::vector<int>> vec({1, 2, 3, 4, 5});
// Maps and other associative containers
siddiqsoft::RWLEnvelope<std::map<std::string, int>> map({
{"key1", 1},
{"key2", 2},
{"key3", 3}
});
// JSON objects
siddiqsoft::RWLEnvelope<nlohmann::json> doc({
{"name", "John"},
{"age", 30},
{"active", true}
});
Real-World Examples
Configuration Management
siddiqsoft::RWLEnvelope<AppConfig> config;
// Multiple threads reading config
auto url = config.observe([](const auto& cfg) noexcept {
return cfg.databaseUrl;
});
// Single thread updating config
config.mutate([](auto& cfg) noexcept {
cfg.databaseUrl = "new_url";
});
Cache Implementation
siddiqsoft::RWLEnvelope<std::unordered_map<std::string, CacheEntry>> cache;
// Fast concurrent reads
auto val = cache.observe([](const auto& c) noexcept {
return c.at("key").value;
});
// Exclusive writes
cache.mutate([](auto& c) noexcept {
c["key"] = {"computed_value", now()};
});
Initializing with Data
// Initialize a cache with pre-populated data
siddiqsoft::RWLEnvelope<std::map<std::string, std::string>> cache({
{"user:1", "Alice"},
{"user:2", "Bob"},
{"user:3", "Charlie"}
});
// Initialize a JSON document with structured data
siddiqsoft::RWLEnvelope<nlohmann::json> config({
{"database", {{"host", "localhost"}, {"port", 5432}}},
{"cache", {{"ttl", 3600}, {"enabled", true}}}
});
Testing
The library includes comprehensive test coverage with 38+ tests covering:
- Basic functionality (observe, mutate, readLock, writeLock)
- Initializer list construction
- Edge cases and exception safety
- Concurrent access patterns
- Data integrity under contention
Run tests:
cmake --preset Apple-Debug
cmake --build --preset Apple-Debug
ctest --preset Apple-Debug
License
BSD 3-Clause License - See LICENSE file for details
Resources
- Full API Documentation - Complete reference and examples
- GitHub Repository - Source code and issues
- C++ std::shared_mutex - Standard library reference
<small align="right">
© 2021 Abdulkareem Siddiq. All rights reserved.
</small>
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| native | native is compatible. |
This package has no dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on SiddiqSoft.RWLEnvelope:
| Package | Downloads |
|---|---|
|
SiddiqSoft.asynchrony
Add asynchrony to your apps |
GitHub repositories
This package is not used by any popular GitHub repositories.
## Features
- Header-only C++ template library (no compilation needed)
- Simple, intuitive API for thread-safe access patterns
- Automatic lock management with RAII semantics
- Support for both callback-based and direct lock access
- Exception-safe with proper lock release on errors
- Works with any type supporting move semantics
- Zero runtime overhead beyond standard library mutex
- Verified deadlock-free and race-condition-free
- Supports C++20 and later
- Enhanced Visual Studio debugging with natvis visualizers
## What's New
- BREAKING CHANGE:
- mutate and observe have strict requirements.
- compiler requirement now C++20