mutex.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Hamburg University of Applied Sciences (HAW)
3  *
4  * This file is subject to the terms and conditions of the GNU Lesser
5  * General Public License v2.1. See the file LICENSE in the top level
6  * directory for more details.
7  */
8 
24 #ifndef RIOT_MUTEX_HPP
25 #define RIOT_MUTEX_HPP
26 
27 #include "mutex.h"
28 
29 #include <utility>
30 #include <stdexcept>
31 #include <system_error>
32 
33 namespace riot {
34 
43 class mutex {
44 public:
49 
50  inline constexpr mutex() noexcept : m_mtx{{0}} {}
51  ~mutex();
52 
56  void lock();
61  bool try_lock() noexcept;
65  void unlock() noexcept;
66 
71  inline native_handle_type native_handle() { return &m_mtx; }
72 
73 private:
74  mutex(const mutex&);
75  mutex& operator=(const mutex&);
76 
77  mutex_t m_mtx;
78 };
79 
83 struct defer_lock_t {};
87 struct try_to_lock_t {};
91 struct adopt_lock_t {};
92 
105 
112 template <class Mutex>
113 class lock_guard {
114 public:
118  using mutex_type = Mutex;
119 
123  inline explicit lock_guard(mutex_type& mtx) : m_mtx(mtx) { m_mtx.lock(); }
128  inline lock_guard(mutex_type& mtx, adopt_lock_t) : m_mtx{mtx} {}
129  inline ~lock_guard() { m_mtx.unlock(); }
130 
131 private:
132  mutex_type& m_mtx;
133 };
134 
141 template <class Mutex>
142 class unique_lock {
143 public:
147  using mutex_type = Mutex;
148 
149  inline unique_lock() noexcept : m_mtx{nullptr}, m_owns{false} {}
153  inline explicit unique_lock(mutex_type& mtx) : m_mtx{&mtx}, m_owns{true} {
154  m_mtx->lock();
155  }
159  inline unique_lock(mutex_type& mtx, defer_lock_t) noexcept : m_mtx{&mtx},
160  m_owns{false} {}
165  : m_mtx{&mtx}, m_owns{mtx.try_lock()} {}
171  : m_mtx{&mtx}, m_owns{true} {}
172  inline ~unique_lock() {
173  if (m_owns) {
174  m_mtx->unlock();
175  }
176  }
180  inline unique_lock(unique_lock&& lock) noexcept : m_mtx{lock.m_mtx},
181  m_owns{lock.m_owns} {
182  lock.m_mtx = nullptr;
183  lock.m_owns = false;
184  }
188  inline unique_lock& operator=(unique_lock&& lock) noexcept {
189  if (m_owns) {
190  m_mtx->unlock();
191  }
192  m_mtx = lock.m_mtx;
193  m_owns = lock.m_owns;
194  lock.m_mtx = nullptr;
195  lock.m_owns = false;
196  return *this;
197  }
198 
202  void lock();
208  bool try_lock();
212  void unlock();
213 
217  inline void swap(unique_lock& lock) noexcept {
218  std::swap(m_mtx, lock.m_mtx);
219  std::swap(m_owns, lock.m_owns);
220  }
221 
227  inline mutex_type* release() noexcept {
228  mutex_type* mtx = m_mtx;
229  m_mtx = nullptr;
230  m_owns = false;
231  return mtx;
232  }
233 
239  inline bool owns_lock() const noexcept { return m_owns; }
245  inline explicit operator bool() const noexcept { return m_owns; }
250  inline mutex_type* mutex() const noexcept { return m_mtx; }
251 
252 private:
253  unique_lock(unique_lock const&);
254  unique_lock& operator=(unique_lock const&);
255 
256  mutex_type* m_mtx;
257  bool m_owns;
258 };
259 
260 template <class Mutex>
262  if (m_mtx == nullptr) {
263  throw std::system_error(
264  std::make_error_code(std::errc::operation_not_permitted),
265  "References null mutex.");
266  }
267  if (m_owns) {
268  throw std::system_error(
269  std::make_error_code(std::errc::resource_deadlock_would_occur),
270  "Already locked.");
271  }
272  m_mtx->lock();
273  m_owns = true;
274 }
275 
276 template <class Mutex>
278  if (m_mtx == nullptr) {
279  throw std::system_error(
280  std::make_error_code(std::errc::operation_not_permitted),
281  "References null mutex.");
282  }
283  if (m_owns) {
284  throw std::system_error(
285  std::make_error_code(std::errc::resource_deadlock_would_occur),
286  "Already locked.");
287  }
288  m_owns = m_mtx->try_lock();
289  return m_owns;
290 }
291 
292 template <class Mutex>
294  if (!m_owns) {
295  throw std::system_error(
296  std::make_error_code(std::errc::operation_not_permitted),
297  "Mutex not locked.");
298  }
299  m_mtx->unlock();
300  m_owns = false;
301 }
302 
308 template <class Mutex>
309 inline void swap(unique_lock<Mutex>& lhs, unique_lock<Mutex>& rhs) noexcept {
310  lhs.swap(rhs);
311 }
312 
313 } // namespace riot
314 
315 #endif // RIOT_MUTEX_HPP
Mutex mutex_type
The type of Mutex used by the lock_guard.
Definition: mutex.hpp:118
void unlock()
Unlocks the associated mutex.
Definition: mutex.hpp:293
Definition: chrono.hpp:34
void unlock() noexcept
Unlock the mutex.
unique_lock(mutex_type &mtx, defer_lock_t) noexcept
Constructs a unique_lock from a Mutex but does not lock it.
Definition: mutex.hpp:159
C++11 complient implementation of mutex, uses the time point implemented in our chrono replacement in...
Definition: mutex.hpp:43
constexpr defer_lock_t defer_lock
Tag constant for defer lock strategy.
Definition: mutex.hpp:96
unique_lock(unique_lock &&lock) noexcept
Move constructor.
Definition: mutex.hpp:180
bool try_lock() noexcept
Try to lock the mutex.
constexpr adopt_lock_t adopt_lock
Tag constant for adopt lock strategy.
Definition: mutex.hpp:104
mutex_type * mutex() const noexcept
Provides access to the associated mutex.
Definition: mutex.hpp:250
void swap(unique_lock< Mutex > &lhs, unique_lock< Mutex > &rhs) noexcept
Swaps two mutexes.
Definition: mutex.hpp:309
Tag type for defer lock strategy.
Definition: mutex.hpp:83
native_handle_type native_handle()
Provides access to the native handle.
Definition: mutex.hpp:71
unique_lock(mutex_type &mtx)
Constructs a unique_lock from a Mutex and locks it.
Definition: mutex.hpp:153
Tag type for adopt lock strategy.
Definition: mutex.hpp:91
unique_lock(mutex_type &mtx, adopt_lock_t)
Constructs a unique_lock from a Mutex that is already owned by the thread.
Definition: mutex.hpp:170
lock_guard(mutex_type &mtx)
Constructs a lock_gurad from a Mutex and locks it.
Definition: mutex.hpp:123
RIOT synchronization API.
C++11 complient implementation of unique lock.
Definition: mutex.hpp:142
unique_lock(mutex_type &mtx, try_to_lock_t)
Constructs a unique_lock from a Mutex and tries to lock it.
Definition: mutex.hpp:164
void lock()
Lock the mutex.
void lock()
Locks the associated mutex.
Definition: mutex.hpp:261
lock_guard(mutex_type &mtx, adopt_lock_t)
Constructs a lock_guard from a Mutex, acquireing ownership without locking it.
Definition: mutex.hpp:128
Mutex structure.
Definition: mutex.h:36
C++11 complient implementation of unique lock.
Definition: mutex.hpp:113
void swap(unique_lock &lock) noexcept
Swap this unique_lock with another unique_lock.
Definition: mutex.hpp:217
constexpr try_to_lock_t try_to_lock
Tag constant for try lock strategy.
Definition: mutex.hpp:100
Tag type for try lock strategy.
Definition: mutex.hpp:87
bool try_lock()
Tries to lock the associated mutex.
Definition: mutex.hpp:277
bool owns_lock() const noexcept
Query ownership of the associate mutex.
Definition: mutex.hpp:239
Mutex mutex_type
The type of Mutex used by the lock.
Definition: mutex.hpp:147
mutex_type * release() noexcept
Disassociate this lock from its mutex.
Definition: mutex.hpp:227
unique_lock & operator=(unique_lock &&lock) noexcept
Move assignment operator.
Definition: mutex.hpp:188