- Avoid re-implementing the rw-lock; standard C++ (since C++14) has a good reader-writer lock implementation.
- Provide a simple, convenience layer atop the underlying
std::unique_lock
andstd::shared_lock
access to some type.
WE DO NOT IMPLEMENT a read-writer lock; the standard C++ library has one.
We provide a header-only package simplifying the locking code around thread-safe access to your underlying type.
NOT a wrapper; an envelope.
- You must be able to use
<shared_mutex>
and<mutex>
. - Minimal target is
C++17
. - The build and tests are for Visual Studio 2019 under x64.
- We use
nlohmann::json
only in our tests and the library is aware to provide a conversion operator if library is detected.
- Use the nuget SiddiqSoft.RWLEnvelope
- Copy paste..whatever works.
- The idea is to not "wrap" the underlying type forcing you to either inherit or re-implement the types but to take advantage of the underlying type's interface whilst ensuring that we have the necessary locks.
- Two methods:
- Observer/mutator model with callback and custom return to limit access and to focus the where and how to access the underlying type.
- Take advantage of init-statement in if-statement to get the contained object within a lock and have the compiler auto-release once we leave scope.
- A sample implementation (say you want a std::map with reader-writer lock)
using RWLMap = siddiqsoft::RWLEnvelope<std::map>;
#include "gtest/gtest.h"
#include "nlohmann/json.hpp"
#include "siddiqsoft/RWLEnvelope.hpp"
TEST(examples, AssignWithCallbacks)
{
siddiqsoft::RWLEnvelope<nlohmann::json> docl; // we will assign later
nlohmann::json doc2 {{"baa", 0x0baa}, {"fee", 0x0fee}, {"bee", 0x0bee}};
// Move assign here post init
docl.reassign(std::move(doc2));
// Must be empty since we moved it into the envelope
EXPECT_TRUE(doc2.empty());
// Check we have pre-change value.. Note that here we return a boolean to avoid data copy
EXPECT_TRUE(docl.observe<bool>([](const auto& doc) -> bool {
return (doc.value("fee", 0xfa17) == 0x0fee) && (doc.value("baa", 0xfa17) == 0x0baa) && (doc.value("bee", 0xfa17) == 0x0bee);
}));
EXPECT_EQ(3, docl.observe<size_t>([](const auto& doc) { return doc.size(); }));
}
TEST(examples, AssignWithDirectLocks)
{
siddiqsoft::RWLEnvelope<nlohmann::json> docl({{"foo", "bar"}, {"few", "lar"}});
nlohmann::json doc2 {{"baa", 0x0baa}, {"fee", 0x0fee}, {"bee", 0x0bee}};
// Previous document has two items..
if (auto const& [doc, rl] = docl.readLock(); rl) { EXPECT_EQ(2, doc.size()); }
// Modify the item (replace the initial with new)
if (auto [doc, wl] = docl.writeLock(); wl) { doc = std::move(doc2); };
//doc2 -> Must be empty since we moved it into the envelope
EXPECT_TRUE(doc2.empty());
// Check we have post-change value..
if (const auto& [doc, rl] = docl.readLock(); rl) { EXPECT_EQ(3, doc.size()); }
}
Additional examples.
© 2021 Siddiq Software LLC. All rights reserved.