diff --git a/src/common.h b/src/common.h index da91aa189..34edc3079 100644 --- a/src/common.h +++ b/src/common.h @@ -544,10 +544,16 @@ class scoped_lock { bool locked; // No copying. - scoped_lock &operator=(const scoped_lock &); - scoped_lock(const scoped_lock &); + scoped_lock &operator=(const scoped_lock &) = delete; + scoped_lock(const scoped_lock &) = delete; public: + scoped_lock(scoped_lock &&rhs) : lock_obj(rhs.lock_obj), locked(rhs.locked) { + // we acquire any locked state + // ensure the rhs doesn't try to unlock + rhs.locked = false; + } + void lock(void); void unlock(void); explicit scoped_lock(pthread_mutex_t &mutex); @@ -561,6 +567,9 @@ class rwlock_t { rwlock_t() { VOMIT_ON_FAILURE_NO_ERRNO(pthread_rwlock_init(&rwlock, NULL)); } ~rwlock_t() { VOMIT_ON_FAILURE_NO_ERRNO(pthread_rwlock_destroy(&rwlock)); } + + rwlock_t &operator=(const rwlock_t &) = delete; + rwlock_t(const rwlock_t &) = delete; }; // Scoped lock class for rwlocks. @@ -570,8 +579,8 @@ class scoped_rwlock { bool locked_shared; // No copying. - scoped_rwlock &operator=(const scoped_lock &); - explicit scoped_rwlock(const scoped_lock &); + scoped_rwlock &operator=(const scoped_lock &) = delete; + explicit scoped_rwlock(const scoped_lock &) = delete; public: void lock(void); @@ -585,6 +594,57 @@ class scoped_rwlock { ~scoped_rwlock(); }; +// An object wrapping a scoped lock and a value +// This is returned from owning_lock.acquire() +// Sample usage: +// owning_lock locked_name; +// acquired_lock name = name.acquire(); +// name.value = "derp" +// +// Or for simple cases: +// name.acquire().value = "derp" +// +template +class acquired_lock { + scoped_lock lock; + acquired_lock(mutex_lock_t &lk, DATA *v) : lock(lk), value(*v) + {} + + template + friend class owning_lock; + + public: + // No copying, move only + acquired_lock &operator=(const acquired_lock &) = delete; + acquired_lock(const acquired_lock &) = delete; + acquired_lock(acquired_lock &&) = default; + acquired_lock &operator=(acquired_lock &&) = default; + + DATA &value; +}; + +// A lock that owns a piece of data +// Access to the data is only provided by taking the lock +template +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; + + mutex_lock_t lock; + DATA data; + +public: + owning_lock(DATA d) : data(std::move(d)) {} + owning_lock() : data() {} + + acquired_lock acquire() { + return {lock, &data}; + } +}; + /// A scoped manager to save the current value of some variable, and optionally set it to a new /// value. On destruction it restores the variable to its old value. ///