summaryrefslogtreecommitdiffstats
path: root/src/common/synchronized_wrapper.h
diff options
context:
space:
mode:
authorYuri Kunde Schlesner <yuriks@yuriks.net>2015-02-05 17:53:25 +0100
committerYuri Kunde Schlesner <yuriks@yuriks.net>2015-03-02 01:47:13 +0100
commitcd1fbfcf1b70e365d81480ec0f56db19ed02454f (patch)
treeb220b105d1b8016bb258047683bf2d03795c8881 /src/common/synchronized_wrapper.h
parentMerge pull request #616 from archshift/5551 (diff)
downloadyuzu-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.h69
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