SiddiqSoft.RWLEnvelope 1.5.1

dotnet add package SiddiqSoft.RWLEnvelope --version 1.5.1
                    
NuGet\Install-Package SiddiqSoft.RWLEnvelope -Version 1.5.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SiddiqSoft.RWLEnvelope" Version="1.5.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SiddiqSoft.RWLEnvelope" Version="1.5.1" />
                    
Directory.Packages.props
<PackageReference Include="SiddiqSoft.RWLEnvelope" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SiddiqSoft.RWLEnvelope --version 1.5.1
                    
#r "nuget: SiddiqSoft.RWLEnvelope, 1.5.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SiddiqSoft.RWLEnvelope@1.5.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SiddiqSoft.RWLEnvelope&version=1.5.1
                    
Install as a Cake Addin
#tool nuget:?package=SiddiqSoft.RWLEnvelope&version=1.5.1
                    
Install as a Cake Tool

RWLEnvelope : A simple read-writer lock envelope

CodeQL Build Status alternate text is missing from this package README image alternate text is missing from this package README image alternate text is missing from this package README image alternate text is missing from this package README image

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

📖 Complete API 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

<small align="right">

© 2021 Abdulkareem Siddiq. All rights reserved.

</small>

Product Compatible and additional computed target framework versions.
native native is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.

Version Downloads Last Updated
1.5.1 0 7/4/2026
1.5.0 97 6/27/2026
1.4.5 97 6/25/2026
1.4.4 147 5/22/2026
1.4.3 177 4/29/2026
1.2.0 581 12/7/2024
1.1.1 929 12/2/2021
1.1.0 9,719 7/22/2021
1.1.0-main0001 721 7/22/2021
1.0.0 1,950 7/22/2021
0.10.0-main0001 713 7/22/2021

## 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