libfilezilla
Loading...
Searching...
No Matches
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 <list>
20#include <memory>
21#include <thread>
22
23namespace fz {
24class mutex;
25class mutex_debug;
26
28struct FZ_PUBLIC_SYMBOL lock_order final {
29 std::vector<mutex*> mutexes_;
30 std::vector<void*> backtrace_;
31};
32
34struct FZ_PUBLIC_SYMBOL mutex_debug final
35{
36 static void record_lock(void* m);
37 static void record_unlock(void* m);
38
39 size_t count_{};
40 std::thread::id id_{};
41 std::vector<std::list<lock_order>::iterator> own_orders_;
42};
43}
44#endif
45
46namespace fz {
56class FZ_PUBLIC_SYMBOL mutex final
57{
58public:
59 explicit mutex(bool recursive = true);
60 ~mutex();
61
62 mutex(mutex const&) = delete;
63 mutex& operator=(mutex const&) = delete;
64
66 void lock();
67
69 void unlock();
70
72 bool try_lock();
73
74private:
75 friend class condition;
76 friend class scoped_lock;
77
78#ifdef FZ_WINDOWS
79 CRITICAL_SECTION m_;
80#else
81 pthread_mutex_t m_;
82#endif
83#ifdef LFZ_DEBUG_MUTEXES
84public:
85 mutex_debug debug_;
86#endif
87};
88
97class FZ_PUBLIC_SYMBOL scoped_lock final
98{
99public:
100 enum flag
101 {
102 try_lock
103 };
104
105 explicit scoped_lock(mutex& m)
106 : m_(&m.m_)
107 {
108#ifdef FZ_WINDOWS
109 EnterCriticalSection(m_);
110#else
111 pthread_mutex_lock(m_);
112#endif
113#ifdef LFZ_DEBUG_MUTEXES
114 mutex_debug::record_lock(m_);
115#endif
116 }
117
118 explicit scoped_lock(mutex& m, flag)
119 : m_(&m.m_)
120 {
121 if (!m.try_lock()) {
122 locked_ = false;
123 }
124 }
125
126 ~scoped_lock()
127 {
128 if (locked_) {
129#ifdef LFZ_DEBUG_MUTEXES
130 mutex_debug::record_unlock(m_);
131#endif
132#ifdef FZ_WINDOWS
133 LeaveCriticalSection(m_);
134#else
135 pthread_mutex_unlock(m_);
136#endif
137 }
138
139 }
140
141 scoped_lock(scoped_lock const&) = delete;
142 scoped_lock& operator=(scoped_lock const&) = delete;
143
144 scoped_lock(scoped_lock && op) noexcept
145 {
146 m_ = op.m_;
147 op.m_ = 0;
148 locked_ = op.locked_;
149 op.locked_ = false;
150 }
151
152 scoped_lock& operator=(scoped_lock && op) noexcept
153 {
154 if (this != &op) {
155 m_ = op.m_;
156 op.m_ = 0;
157 locked_ = op.locked_;
158 op.locked_ = false;
159 }
160 return *this;
161 }
162
167 void lock()
168 {
169 locked_ = true;
170#ifdef FZ_WINDOWS
171 EnterCriticalSection(m_);
172#else
173 pthread_mutex_lock(m_);
174#endif
175#ifdef LFZ_DEBUG_MUTEXES
176 mutex_debug::record_lock(m_);
177#endif
178 }
179
184 void unlock()
185 {
186 locked_ = false;
187#ifdef LFZ_DEBUG_MUTEXES
188 mutex_debug::record_unlock(m_);
189#endif
190#ifdef FZ_WINDOWS
191 LeaveCriticalSection(m_);
192#else
193 pthread_mutex_unlock(m_);
194#endif
195 }
196
197 explicit operator bool() const { return locked_; }
198
199private:
200 friend class condition;
201
202#ifdef FZ_WINDOWS
203 CRITICAL_SECTION * m_;
204#else
205 pthread_mutex_t * m_;
206#endif
207 bool locked_{true};
208};
209
214class FZ_PUBLIC_SYMBOL condition final
215{
216public:
217 condition();
218 ~condition();
219
220 condition(condition const&) = delete;
221 condition& operator=(condition const&) = delete;
222
230
242 bool wait(scoped_lock& l, duration const& timeout);
243
254
262 bool signalled(scoped_lock const&) const { return signalled_; }
263private:
264#ifdef FZ_WINDOWS
265 CONDITION_VARIABLE cond_;
266#else
267 pthread_cond_t cond_;
268#endif
269 bool signalled_{};
270};
271
272}
273#endif
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:262
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:57
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:98
void unlock()
Releases the mutex.
Definition mutex.hpp:184
void lock()
Obtains the mutex.
Definition mutex.hpp:167
Sets some global macros and further includes string.hpp.
The namespace used by libfilezilla.
Definition apply.hpp:17
Assorted classes dealing with time.