RWLEnvelope 0.0.0
Thread-safe envelope wrapper using reader-writer locks
Loading...
Searching...
No Matches
pages Directory Reference
Directory dependency graph for pages:
pages

Detailed Description

CodeQL Build Status

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.

// Read-only access
data.observe([](const auto& m) noexcept {
return m.find("key") != m.end();
});
// Read-write access
data.mutate([](auto& m) noexcept {
m["key"] = 42;
});
Thread-safe envelope wrapper using reader-writer locks.
Thread-safe envelope wrapper using reader-writer locks.

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

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());

Real-World Examples

Configuration Management

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

// 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()};
});

Testing

The library includes comprehensive test coverage with 38+ tests covering:

  • Basic functionality (observe, mutate, readLock, writeLock)
  • 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

© 2021 Abdulkareem Siddiq. All rights reserved.