libfilezilla
mutex.hpp
Go to the documentation of this file.
1 #ifndef LIBFILEZILLA_MUTEX_HEADER
2 #define LIBFILEZILLA_MUTEX_HEADER
3 
7 #include "libfilezilla.hpp"
8 #include "time.hpp"
9 
10 #ifdef FZ_WINDOWS
11 #include "glue/windows.hpp"
12 #else
13 #include <pthread.h>
14 #endif
15 
16 //#define LFZ_DEBUG_MUTEXES
17 #ifdef LFZ_DEBUG_MUTEXES
18 
19 #include <memory>
20 
21 namespace fz {
22 class mutex;
24 struct FZ_PUBLIC_SYMBOL mutex_debug final
25 {
26  mutex_debug(mutex* mtx)
27  : mtx_(mtx)
28  {}
29 
30  static void record_lock(void* m);
31  static void record_unlock(void* m);
32 
33  size_t count_{};
34  mutex* mtx_{};
35 
36  std::vector<std::tuple<std::weak_ptr<mutex_debug>, std::vector<void*>>> order_;
37 };
38 }
39 #endif
40 
41 namespace fz {
51 class FZ_PUBLIC_SYMBOL mutex final
52 {
53 public:
54  explicit mutex(bool recursive = true);
55  ~mutex();
56 
57  mutex(mutex const&) = delete;
58  mutex& operator=(mutex const&) = delete;
59 
61  void lock();
62 
64  void unlock();
65 
67  bool try_lock();
68 
69 private:
70  friend class condition;
71  friend class scoped_lock;
72 
73 #ifdef FZ_WINDOWS
74  CRITICAL_SECTION m_;
75 #else
76  pthread_mutex_t m_;
77 #endif
78 #ifdef LFZ_DEBUG_MUTEXES
79 public:
80  std::shared_ptr<mutex_debug> h_;
81 #endif
82 };
83 
92 class FZ_PUBLIC_SYMBOL scoped_lock final
93 {
94 public:
95  explicit scoped_lock(mutex& m)
96  : m_(&m.m_)
97  {
98 #ifdef FZ_WINDOWS
99  EnterCriticalSection(m_);
100 #else
101  pthread_mutex_lock(m_);
102 #endif
103 #ifdef LFZ_DEBUG_MUTEXES
104  mutex_debug::record_lock(m_);
105 #endif
106  }
107 
108  ~scoped_lock()
109  {
110  if (locked_) {
111 #ifdef LFZ_DEBUG_MUTEXES
112  mutex_debug::record_unlock(m_);
113 #endif
114 #ifdef FZ_WINDOWS
115  LeaveCriticalSection(m_);
116 #else
117  pthread_mutex_unlock(m_);
118 #endif
119  }
120 
121  }
122 
123  scoped_lock(scoped_lock const&) = delete;
124  scoped_lock& operator=(scoped_lock const&) = delete;
125 
126  scoped_lock(scoped_lock && op) noexcept
127  {
128  m_ = op.m_;
129  op.m_ = 0;
130  locked_ = op.locked_;
131  op.locked_ = false;
132  }
133 
134  scoped_lock& operator=(scoped_lock && op) noexcept
135  {
136  if (this != &op) {
137  m_ = op.m_;
138  op.m_ = 0;
139  locked_ = op.locked_;
140  op.locked_ = false;
141  }
142  return *this;
143  }
144 
149  void lock()
150  {
151  locked_ = true;
152 #ifdef FZ_WINDOWS
153  EnterCriticalSection(m_);
154 #else
155  pthread_mutex_lock(m_);
156 #endif
157 #ifdef LFZ_DEBUG_MUTEXES
158  mutex_debug::record_lock(m_);
159 #endif
160 
161  }
162 
167  void unlock()
168  {
169  locked_ = false;
170 #ifdef LFZ_DEBUG_MUTEXES
171  mutex_debug::record_unlock(m_);
172 #endif
173 #ifdef FZ_WINDOWS
174  LeaveCriticalSection(m_);
175 #else
176  pthread_mutex_unlock(m_);
177 #endif
178  }
179 
180 private:
181  friend class condition;
182 
183 #ifdef FZ_WINDOWS
184  CRITICAL_SECTION * m_;
185 #else
186  pthread_mutex_t * m_;
187 #endif
188  bool locked_{true};
189 };
190 
195 class FZ_PUBLIC_SYMBOL condition final
196 {
197 public:
198  condition();
199  ~condition();
200 
201  condition(condition const&) = delete;
202  condition& operator=(condition const&) = delete;
203 
210  void wait(scoped_lock& l);
211 
223  bool wait(scoped_lock& l, duration const& timeout);
224 
234  void signal(scoped_lock& l);
235 
243  bool signalled(scoped_lock const&) const { return signalled_; }
244 private:
245 #ifdef FZ_WINDOWS
246  CONDITION_VARIABLE cond_;
247 #else
248  pthread_cond_t cond_;
249 #endif
250  bool signalled_{};
251 };
252 
253 }
254 #endif
Waitable condition variable.
Definition: mutex.hpp:196
void wait(scoped_lock &l)
Wait indefinitely for condition to become signalled.
bool wait(scoped_lock &l, duration const &timeout)
Wait until timeout for condition to become signalled.
bool signalled(scoped_lock const &) const
Check if condition is already signalled.
Definition: mutex.hpp:243
void signal(scoped_lock &l)
Signal condition variable.
The duration class represents a time interval in milliseconds.
Definition: time.hpp:291
Lean replacement for std::(recursive_)mutex.
Definition: mutex.hpp:52
void unlock()
Beware, manual locking isn't exception safe, use scoped_lock.
bool try_lock()
Beware, manual locking isn't exception safe.
void lock()
Beware, manual locking isn't exception safe, use scoped_lock.
A simple scoped lock.
Definition: mutex.hpp:93
void unlock()
Releases the mutex.
Definition: mutex.hpp:167
void lock()
Obtains the mutex.
Definition: mutex.hpp:149
Sets some global macros and further includes string.hpp.
The namespace used by libfilezilla.
Definition: apply.hpp:17
Assorted classes dealing with time.