Created
June 3, 2022 01:12
-
-
Save ridiculousfish/952ceb797165201ab1ab76aec940845f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// An object wrapping a scoped lock and a value | |
// This is returned from owning_lock.acquire() | |
// Sample usage: | |
// owning_lock<string> locked_name; | |
// acquired_lock<string> name = name.acquire(); | |
// name.value = "derp" | |
// | |
// Or for simple cases: | |
// name.acquire().value = "derp" | |
// | |
template <typename Data> | |
class acquired_lock : noncopyable_t { | |
template <typename T> | |
friend class owning_lock; | |
template <typename T> | |
friend class acquired_lock; | |
acquired_lock(std::mutex &lk, Data *v) : lock(lk), value(v) {} | |
acquired_lock(std::unique_lock<std::mutex> &&lk, Data *v) : lock(std::move(lk)), value(v) {} | |
std::unique_lock<std::mutex> lock; | |
Data *value; | |
public: | |
Data *operator->() { return value; } | |
const Data *operator->() const { return value; } | |
Data &operator*() { return *value; } | |
const Data &operator*() const { return *value; } | |
/// Implicit conversion to const version. | |
operator acquired_lock<const Data>() { | |
// We're about to give up our lock, don't hold onto the data. | |
const Data *cvalue = value; | |
value = nullptr; | |
return acquired_lock<const Data>(std::move(lock), cvalue); | |
} | |
/// Create from a global lock. | |
/// This is used in weird cases where a global lock protects more than one piece of data. | |
static acquired_lock from_global(std::mutex &lk, Data *v) { return acquired_lock{lk, v}; } | |
/// \return a reference to the lock, for use with a condition variable. | |
std::unique_lock<std::mutex> &get_lock() { return lock; } | |
}; | |
// A lock that owns a piece of data | |
// Access to the data is only provided by taking the lock | |
template <typename Data> | |
class owning_lock { | |
// No copying | |
owning_lock &operator=(const scoped_lock &) = delete; | |
owning_lock(const scoped_lock &) = delete; | |
owning_lock(owning_lock &&) = default; | |
owning_lock &operator=(owning_lock &&) = default; | |
std::mutex lock; | |
Data data; | |
public: | |
owning_lock(Data &&d) : data(std::move(d)) {} | |
owning_lock(const Data &d) : data(d) {} | |
owning_lock() : data() {} | |
acquired_lock<Data> acquire() { return {lock, &data}; } | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment