OpenLibrary
ts_resource.hpp
1 
2 #ifndef OPENLIBRARY_PALGORITHM_TS_RESOURCE
3 #define OPENLIBRARY_PALGORITHM_TS_RESOURCE
4 
5 #include <cassert>
6 
7 #include <mutex>
8 #include <memory>
9 #include <ostream>
10 
11 namespace ol
12 {
13 
15 
23  template<typename T>
25  {
26  public:
28  struct INotify
29  {
30  virtual ~INotify() {}
31  virtual void unlocked() = 0;
32  };
33 
35 
40  struct Accessor
41  {
44  Accessor(std::mutex& mutex, T* object): m_lock(mutex), m_object(object), m_notify(nullptr) {}
45 
47  Accessor(Accessor&& other): m_lock(std::move(other.m_lock)),
48  m_object(other.m_object),
49  m_notify(other.m_notify)
50  {
51  other.m_object = nullptr;
52  other.m_notify = nullptr;
53  }
54 
57  Accessor(): m_lock(), m_object(nullptr), m_notify(nullptr) {}
58 
60  Accessor(std::unique_lock<std::mutex>&& lock, T* object): m_lock(std::move(lock)), m_object(object), m_notify(nullptr) {}
61  Accessor(const Accessor &) = delete;
62 
63  Accessor& operator=(const Accessor &) = delete;
64 
67  {
68  m_lock = std::move(other.m_lock);
69  m_object = other.m_object;
70  m_notify = other.m_notify;
71 
72  other.m_object = nullptr;
73  other.m_notify = nullptr;
74 
75  return *this;
76  }
77 
79 
83  virtual ~Accessor()
84  {
85  if (m_lock)
86  m_lock.unlock();
87 
88  if (m_notify != nullptr)
89  m_notify->unlocked();
90  }
91 
93  T& get()
94  {
95  return *m_object;
96  }
97 
99  const T& get() const
100  {
101  return *m_object;
102  }
103 
106  {
107  return m_object;
108  }
109 
111  const T* operator->() const
112  {
113  return m_object;
114  }
115 
118  {
119  return *m_object;
120  }
121 
123  const T& operator*() const
124  {
125  return *m_object;
126  }
127 
129 
131  bool is_valid() const
132  {
133  return m_object != nullptr;
134  }
135 
136  private:
137  friend class ThreadSafeResource;
138  std::unique_lock<std::mutex> m_lock;
139  T* m_object;
140  INotify* m_notify;
141 
142  void set(INotify* notify)
143  {
144  m_notify = notify;
145  }
146  };
147 
149 
150  template<typename... Args>
151  ThreadSafeResource(const Args&... args): m_mutex(), m_resource(args...)
152  {
153  }
154 
158  {
159  // point of this lock is te be sure resource is not used (no live Accessors exist)
160  std::unique_lock<std::mutex> l(m_mutex);
161  }
162 
163  ThreadSafeResource(const ThreadSafeResource<T> &) = delete;
164  ThreadSafeResource<T>& operator=(const ThreadSafeResource<T> &) = delete;
165 
169  {
170  Accessor accessor(m_mutex, &m_resource);
171 
172  return accessor;
173  }
174 
178  {
179  Accessor accessor = lock();
180  accessor.set(notify);
181 
182  return accessor;
183  }
184 
185 
189  {
190  std::unique_lock<std::mutex> l(m_mutex, std::defer_lock);
191  const bool locked = l.try_lock();
192  Accessor result;
193 
194  if (locked)
195  result = Accessor(std::move(l), &m_resource);
196 
197  return result;
198  }
199 
200  private:
201  std::mutex m_mutex;
202  T m_resource;
203  };
204 
205 }
206 
207 #endif
T * operator->()
get pointer to resource
Definition: ts_resource.hpp:105
virtual ~Accessor()
Destructor.
Definition: ts_resource.hpp:83
Accessor try_lock()
Definition: ts_resource.hpp:188
const T * operator->() const
get pointer to const resource
Definition: ts_resource.hpp:111
bool is_valid() const
Check if Accessor is valid.
Definition: ts_resource.hpp:131
Thread safe wrapper for objects.
Definition: ts_resource.hpp:24
Accessor()
Definition: ts_resource.hpp:57
T & operator*()
get reference to resource
Definition: ts_resource.hpp:117
Definition: debug.hpp:45
Accessor lock()
Definition: ts_resource.hpp:168
const T & operator*() const
get reference to const resource
Definition: ts_resource.hpp:123
virtual void unlocked()=0
Called when Accessor is being destructed and resource is unlocked.
ThreadSafeResource(const Args &...args)
Contructor.
Definition: ts_resource.hpp:151
Accessor(std::unique_lock< std::mutex > &&lock, T *object)
Constructor.
Definition: ts_resource.hpp:60
ThreadSafeResource's helper class.
Definition: ts_resource.hpp:40
Notification interface.
Definition: ts_resource.hpp:28
Accessor & operator=(Accessor &&other)
Move operator.
Definition: ts_resource.hpp:66
~ThreadSafeResource()
Definition: ts_resource.hpp:157
Accessor lock(INotify *notify)
Definition: ts_resource.hpp:177
Accessor(Accessor &&other)
Move Constructor.
Definition: ts_resource.hpp:47
Accessor(std::mutex &mutex, T *object)
Definition: ts_resource.hpp:44