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&);
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
riot::unique_lock::owns_lock
bool owns_lock() const noexcept
Query ownership of the associate mutex.
Definition: mutex.hpp:239
riot::mutex::native_handle
native_handle_type native_handle()
Provides access to the native handle.
Definition: mutex.hpp:71
riot::unique_lock::operator=
unique_lock & operator=(unique_lock &&lock) noexcept
Move assignment operator.
Definition: mutex.hpp:188
riot::unique_lock::release
mutex_type * release() noexcept
Disassociate this lock from its mutex.
Definition: mutex.hpp:227
riot::lock_guard
C++11 compliant implementation of unique lock.
Definition: mutex.hpp:113
riot::adopt_lock_t
Tag type for adopt lock strategy.
Definition: mutex.hpp:91
riot::lock_guard::lock_guard
lock_guard(mutex_type &mtx)
Constructs a lock_gurad from a Mutex and locks it.
Definition: mutex.hpp:123
riot::unique_lock::unique_lock
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
riot::mutex::lock
void lock()
Lock the mutex.
riot::defer_lock
constexpr defer_lock_t defer_lock
Tag constant for defer lock strategy.
Definition: mutex.hpp:96
riot::lock_guard::lock_guard
lock_guard(mutex_type &mtx, adopt_lock_t)
Constructs a lock_guard from a Mutex, acquireing ownership without locking it.
Definition: mutex.hpp:128
riot::adopt_lock
constexpr adopt_lock_t adopt_lock
Tag constant for adopt lock strategy.
Definition: mutex.hpp:104
Mutex
Mutex struct within mqtt paho.
Definition: paho_mqtt.h:145
riot::mutex::try_lock
bool try_lock() noexcept
Try to lock the mutex.
riot::unique_lock::mutex_type
Mutex mutex_type
The type of Mutex used by the lock.
Definition: mutex.hpp:147
riot::swap
void swap(unique_lock< Mutex > &lhs, unique_lock< Mutex > &rhs) noexcept
Swaps two mutexes.
Definition: mutex.hpp:309
riot::unique_lock
C++11 compliant implementation of unique lock.
Definition: mutex.hpp:142
riot::mutex::unlock
void unlock() noexcept
Unlock the mutex.
riot::unique_lock::unique_lock
unique_lock(unique_lock &&lock) noexcept
Move constructor.
Definition: mutex.hpp:180
riot::unique_lock::unlock
void unlock()
Unlocks the associated mutex.
Definition: mutex.hpp:293
Mutex::lock
mutex_t lock
MQTT thread mutex.
Definition: paho_mqtt.h:146
riot::unique_lock::unique_lock
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
riot::unique_lock::unique_lock
unique_lock(mutex_type &mtx)
Constructs a unique_lock from a Mutex and locks it.
Definition: mutex.hpp:153
riot::unique_lock::try_lock
bool try_lock()
Tries to lock the associated mutex.
Definition: mutex.hpp:277
mutex.h
Mutex for thread synchronization.
riot::unique_lock::unique_lock
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
riot::mutex
C++11 compliant implementation of mutex, uses the time point implemented in our chrono replacement in...
Definition: mutex.hpp:43
riot::unique_lock::swap
void swap(unique_lock &lock) noexcept
Swap this unique_lock with another unique_lock.
Definition: mutex.hpp:217
riot::unique_lock::lock
void lock()
Locks the associated mutex.
Definition: mutex.hpp:261
riot::try_to_lock
constexpr try_to_lock_t try_to_lock
Tag constant for try lock strategy.
Definition: mutex.hpp:100
riot::unique_lock::mutex
mutex_type * mutex() const noexcept
Provides access to the associated mutex.
Definition: mutex.hpp:250
riot::defer_lock_t
Tag type for defer lock strategy.
Definition: mutex.hpp:83
riot::try_to_lock_t
Tag type for try lock strategy.
Definition: mutex.hpp:87
riot::lock_guard::mutex_type
Mutex mutex_type
The type of Mutex used by the lock_guard.
Definition: mutex.hpp:118
mutex_t
Mutex structure.
Definition: mutex.h:120