diff options
author | Yuri Kunde Schlesner <yuriks@yuriks.net> | 2015-02-05 17:53:25 +0100 |
---|---|---|
committer | Yuri Kunde Schlesner <yuriks@yuriks.net> | 2015-03-02 01:47:13 +0100 |
commit | cd1fbfcf1b70e365d81480ec0f56db19ed02454f (patch) | |
tree | b220b105d1b8016bb258047683bf2d03795c8881 /src/common/synchronized_wrapper.h | |
parent | Merge pull request #616 from archshift/5551 (diff) | |
download | yuzu-cd1fbfcf1b70e365d81480ec0f56db19ed02454f.tar yuzu-cd1fbfcf1b70e365d81480ec0f56db19ed02454f.tar.gz yuzu-cd1fbfcf1b70e365d81480ec0f56db19ed02454f.tar.bz2 yuzu-cd1fbfcf1b70e365d81480ec0f56db19ed02454f.tar.lz yuzu-cd1fbfcf1b70e365d81480ec0f56db19ed02454f.tar.xz yuzu-cd1fbfcf1b70e365d81480ec0f56db19ed02454f.tar.zst yuzu-cd1fbfcf1b70e365d81480ec0f56db19ed02454f.zip |
Diffstat (limited to '')
-rw-r--r-- | src/common/synchronized_wrapper.h | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/common/synchronized_wrapper.h b/src/common/synchronized_wrapper.h new file mode 100644 index 000000000..946252b8c --- /dev/null +++ b/src/common/synchronized_wrapper.h @@ -0,0 +1,69 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <mutex> + +namespace Common { + +/** + * Wraps an object, only allowing access to it via a locking reference wrapper. Good to ensure no + * one forgets to lock a mutex before acessing an object. To access the wrapped object construct a + * SyncronizedRef on this wrapper. Inspired by Rust's Mutex type (http://doc.rust-lang.org/std/sync/struct.Mutex.html). + */ +template <typename T> +class SynchronizedWrapper { +public: + template <typename... Args> + SynchronizedWrapper(Args&&... args) : + data(std::forward<Args>(args)...) { + } + +private: + template <typename U> + friend class SynchronizedRef; + + std::mutex mutex; + T data; +}; + +/** + * Synchronized reference, that keeps a SynchronizedWrapper's mutex locked during its lifetime. This + * greatly reduces the chance that someone will access the wrapped resource without locking the + * mutex. + */ +template <typename T> +class SynchronizedRef { +public: + SynchronizedRef(SynchronizedWrapper<T>& wrapper) : wrapper(&wrapper) { + wrapper.mutex.lock(); + } + + SynchronizedRef(SynchronizedRef&) = delete; + SynchronizedRef(SynchronizedRef&& o) : wrapper(o.wrapper) { + o.wrapper = nullptr; + } + + ~SynchronizedRef() { + if (wrapper) + wrapper->mutex.unlock(); + } + + SynchronizedRef& operator=(SynchronizedRef&) = delete; + SynchronizedRef& operator=(SynchronizedRef&& o) { + std::swap(wrapper, o.wrapper); + } + + T& operator*() { return wrapper->data; } + const T& operator*() const { return wrapper->data; } + + T* operator->() { return &wrapper->data; } + const T* operator->() const { return &wrapper->data; } + +private: + SynchronizedWrapper<T>* wrapper; +}; + +} // namespace Common |