synchronized_wrapper.h 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. // Copyright 2015 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <algorithm>
  6. #include <mutex>
  7. namespace Common {
  8. /**
  9. * Wraps an object, only allowing access to it via a locking reference wrapper. Good to ensure no
  10. * one forgets to lock a mutex before acessing an object. To access the wrapped object construct a
  11. * SyncronizedRef on this wrapper. Inspired by Rust's Mutex type (http://doc.rust-lang.org/std/sync/struct.Mutex.html).
  12. */
  13. template <typename T>
  14. class SynchronizedWrapper {
  15. public:
  16. template <typename... Args>
  17. SynchronizedWrapper(Args&&... args) :
  18. data(std::forward<Args>(args)...) {
  19. }
  20. private:
  21. template <typename U>
  22. friend class SynchronizedRef;
  23. std::mutex mutex;
  24. T data;
  25. };
  26. /**
  27. * Synchronized reference, that keeps a SynchronizedWrapper's mutex locked during its lifetime. This
  28. * greatly reduces the chance that someone will access the wrapped resource without locking the
  29. * mutex.
  30. */
  31. template <typename T>
  32. class SynchronizedRef {
  33. public:
  34. SynchronizedRef(SynchronizedWrapper<T>& wrapper) : wrapper(&wrapper) {
  35. wrapper.mutex.lock();
  36. }
  37. SynchronizedRef(SynchronizedRef&) = delete;
  38. SynchronizedRef(SynchronizedRef&& o) : wrapper(o.wrapper) {
  39. o.wrapper = nullptr;
  40. }
  41. ~SynchronizedRef() {
  42. if (wrapper)
  43. wrapper->mutex.unlock();
  44. }
  45. SynchronizedRef& operator=(SynchronizedRef&) = delete;
  46. SynchronizedRef& operator=(SynchronizedRef&& o) {
  47. std::swap(wrapper, o.wrapper);
  48. return *this;
  49. }
  50. T& operator*() { return wrapper->data; }
  51. const T& operator*() const { return wrapper->data; }
  52. T* operator->() { return &wrapper->data; }
  53. const T* operator->() const { return &wrapper->data; }
  54. private:
  55. SynchronizedWrapper<T>* wrapper;
  56. };
  57. } // namespace Common