synchronized_wrapper.h 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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. template <typename T>
  9. class SynchronizedWrapper;
  10. /**
  11. * Synchronized reference, that keeps a SynchronizedWrapper's mutex locked during its lifetime. This
  12. * greatly reduces the chance that someone will access the wrapped resource without locking the
  13. * mutex.
  14. */
  15. template <typename T>
  16. class SynchronizedRef {
  17. public:
  18. SynchronizedRef(SynchronizedWrapper<T>& wrapper) : wrapper(&wrapper) {
  19. wrapper.mutex.lock();
  20. }
  21. SynchronizedRef(SynchronizedRef&) = delete;
  22. SynchronizedRef(SynchronizedRef&& o) : wrapper(o.wrapper) {
  23. o.wrapper = nullptr;
  24. }
  25. ~SynchronizedRef() {
  26. if (wrapper)
  27. wrapper->mutex.unlock();
  28. }
  29. SynchronizedRef& operator=(SynchronizedRef&) = delete;
  30. SynchronizedRef& operator=(SynchronizedRef&& o) {
  31. std::swap(wrapper, o.wrapper);
  32. return *this;
  33. }
  34. T& operator*() {
  35. return wrapper->data;
  36. }
  37. const T& operator*() const {
  38. return wrapper->data;
  39. }
  40. T* operator->() {
  41. return &wrapper->data;
  42. }
  43. const T* operator->() const {
  44. return &wrapper->data;
  45. }
  46. private:
  47. SynchronizedWrapper<T>* wrapper;
  48. };
  49. /**
  50. * Wraps an object, only allowing access to it via a locking reference wrapper. Good to ensure no
  51. * one forgets to lock a mutex before acessing an object. To access the wrapped object construct a
  52. * SyncronizedRef on this wrapper. Inspired by Rust's Mutex type
  53. * (http://doc.rust-lang.org/std/sync/struct.Mutex.html).
  54. */
  55. template <typename T>
  56. class SynchronizedWrapper {
  57. public:
  58. template <typename... Args>
  59. SynchronizedWrapper(Args&&... args) : data(std::forward<Args>(args)...) {}
  60. SynchronizedRef<T> Lock() {
  61. return {*this};
  62. }
  63. private:
  64. template <typename U>
  65. friend class SynchronizedRef;
  66. std::mutex mutex;
  67. T data;
  68. };
  69. } // namespace Common