|
|
@ -1,85 +0,0 @@ |
|
|
// Copyright 2015 Citra Emulator Project |
|
|
|
|
|
// Licensed under GPLv2 or any later version |
|
|
|
|
|
// Refer to the license.txt file included. |
|
|
|
|
|
|
|
|
|
|
|
#pragma once |
|
|
|
|
|
|
|
|
|
|
|
#include <algorithm> |
|
|
|
|
|
#include <mutex> |
|
|
|
|
|
|
|
|
|
|
|
namespace Common { |
|
|
|
|
|
|
|
|
|
|
|
template <typename T> |
|
|
|
|
|
class SynchronizedWrapper; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 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); |
|
|
|
|
|
return *this; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 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)...) {} |
|
|
|
|
|
|
|
|
|
|
|
SynchronizedRef<T> Lock() { |
|
|
|
|
|
return {*this}; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
|
template <typename U> |
|
|
|
|
|
friend class SynchronizedRef; |
|
|
|
|
|
|
|
|
|
|
|
std::mutex mutex; |
|
|
|
|
|
T data; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
} // namespace Common |
|
|
|