fork download
  1. #include <iostream>
  2. #include <mutex>
  3. #include <thread>
  4.  
  5. template <typename MUTEX, typename RESOURCE> class LockedResource
  6. {
  7. using my_type = LockedResource<MUTEX, RESOURCE>;
  8. using mutex_t = MUTEX;
  9. using type_t = RESOURCE;
  10. using thread_id_t = std::thread::id;
  11.  
  12. mutex_t m_mutex;
  13. type_t m_resource;
  14. thread_id_t m_thread_id{};
  15.  
  16. public:
  17. template <typename ... ARGS>
  18. LockedResource(ARGS &&... args) :
  19. m_resource(std::forward<ARGS>(args) ...)
  20. {}
  21.  
  22. class Handler
  23. {
  24. using lock_t = std::unique_lock<mutex_t>;
  25.  
  26. lock_t m_lock;
  27. type_t &m_resource;
  28. thread_id_t &m_thread_id;
  29.  
  30. friend class LockedResource;
  31.  
  32. Handler(mutex_t &a_mutex, type_t &a_resource, thread_id_t a_thread_id) :
  33. m_lock{a_mutex},
  34. m_resource{a_resource},
  35. m_thread_id{a_thread_id}
  36. {}
  37. public:
  38. Handler(Handler &&a_handler) :
  39. m_lock{std::move(a_handler.m_lock)},
  40. m_resource{a_handler.m_resource},
  41. m_thread_id{a_handler.m_thread_id}
  42. {}
  43.  
  44. ~Handler()
  45. {
  46. m_thread_id = {};
  47. }
  48. type_t *operator->() const
  49. {
  50. return &m_resource;
  51. }
  52.  
  53. friend std::ostream &operator<<(std::ostream &o, const Handler &h) { return o << h.m_resource; }
  54. };
  55.  
  56. Handler get() throw(std::runtime_error)
  57. {
  58. if (m_thread_id == std::this_thread::get_id())
  59. {
  60. using namespace std::string_literals;
  61. throw std::runtime_error{"Double lock at "s.append(__PRETTY_FUNCTION__)};
  62. }
  63.  
  64. return {m_mutex, m_resource, m_thread_id = std::this_thread::get_id()};
  65. }
  66.  
  67. friend std::ostream &operator<<(std::ostream &o, my_type &lr) { return o << lr.get(); }
  68. };
  69.  
  70. template <typename T> using Resource = LockedResource<std::mutex, T>;
  71.  
  72. #include <vector>
  73. #include <string>
  74.  
  75. Resource<std::vector<int>> locked_vector{10, 10};
  76. Resource<std::string> locked_string{"Hello world!"};
  77.  
  78. int main()
  79. {
  80. const auto &vec = locked_vector.get();
  81. std::cout << vec->size() << '\n';
  82. //locked_vector.get();
  83.  
  84. std::cout << locked_string << '\n';
  85.  
  86. return 0;
  87. }
Runtime error #stdin #stdout #stderr 0s 3272KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
terminate called after throwing an instance of 'std::runtime_error'
  what():  Double lock at LockedResource<MUTEX, RESOURCE>::Handler LockedResource<MUTEX, RESOURCE>::get() [with MUTEX = std::mutex; RESOURCE = std::vector<int>]