32 #ifndef _UTILS_SHARED_MUTEX_HPP_ 33 #define _UTILS_SHARED_MUTEX_HPP_ 36 #include <condition_variable> 39 #include <system_error> 57 typedef std::condition_variable
cond_t;
64 static const count_t write_entered_ = 1U << (
sizeof(count_t) * CHAR_BIT - 1);
65 static const count_t n_readers_ = ~write_entered_;
76 std::lock_guard<mutex_t> _(mut_);
88 std::lock_guard<mutex_t> _(mut_);
91 state_ = write_entered_;
99 std::lock_guard<mutex_t> _(mut_);
108 std::unique_lock<mutex_t> lk(mut_);
109 while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
113 count_t num_readers = (state_ & n_readers_) + 1;
114 state_ &= ~n_readers_;
115 state_ |= num_readers;
120 std::lock_guard<mutex_t> _(mut_);
121 count_t num_readers = state_ & n_readers_;
122 if (!(state_ & write_entered_) && num_readers != n_readers_)
125 state_ &= ~n_readers_;
126 state_ |= num_readers;
134 template<shared_mutex_type>
149 std::unique_lock<mutex_t> lk(mut_);
150 while (state_ & write_entered_)
154 state_ |= write_entered_;
155 while (state_ & n_readers_)
163 std::lock_guard<mutex_t> _(mut_);
164 count_t num_readers = (state_ & n_readers_) - 1;
165 state_ &= ~n_readers_;
166 state_ |= num_readers;
167 if (state_ & write_entered_)
169 if (num_readers == 0)
174 else if (num_readers == n_readers_ - 1)
188 count_t writer_waiting_ = 0;
194 std::unique_lock<mutex_t> lk(mut_);
196 while (state_ & n_readers_ || state_ & write_entered_)
200 state_ |= write_entered_;
206 std::lock_guard<mutex_t> _(mut_);
207 count_t num_readers = (state_ & n_readers_) - 1;
208 state_ &= ~n_readers_;
209 state_ |= num_readers;
211 if ((writer_waiting_ && num_readers == 0)
212 || (num_readers == n_readers_ - 1))
226 std::thread::id exclusive_owner_ = {};
228 std::map<std::thread::id, unsigned int> shared_owners_;
234 std::lock_guard<std::mutex> _(wm_);
242 std::lock_guard<std::mutex> _(wm_);
243 exclusive_owner_ = std::this_thread::get_id();
248 bool res = sm::try_lock();
249 std::lock_guard<std::mutex> _(wm_);
252 exclusive_owner_ = std::this_thread::get_id();
260 std::lock_guard<std::mutex> _(wm_);
261 exclusive_owner_ = std::thread::id();
269 std::lock_guard<std::mutex> _(wm_);
270 ++shared_owners_[std::this_thread::get_id()];
275 bool res = sm::try_lock_shared();
276 std::lock_guard<std::mutex> _(wm_);
279 ++shared_owners_[std::this_thread::get_id()];
287 std::lock_guard<std::mutex> _(wm_);
288 auto owner = shared_owners_.find(std::this_thread::get_id());
289 if ( owner != shared_owners_.end() && 0 == --owner->second )
291 shared_owners_.erase(owner);
300 #if defined(__has_include) && __has_include(<version>) 302 #endif // if defined(__has_include) && __has_include(<version>) 305 #if defined(__has_include) && __has_include(<version>) && !defined(__cpp_lib_shared_mutex) || \ 307 ( !(defined(__has_include) && __has_include(<version>)) && \ 308 !(defined(HAVE_CXX17) && HAVE_CXX17) && __cplusplus < 201703 ) 312 template <
class Mutex>
357 , owns_(m.try_lock_shared())
369 template <
class Clock,
class Duration>
372 const std::chrono::time_point<Clock, Duration>& abs_time)
374 , owns_(m.try_lock_shared_until(abs_time))
378 template <
class Rep,
class Period>
381 const std::chrono::duration<Rep, Period>& rel_time)
383 , owns_(m.try_lock_shared_for(rel_time))
405 sl.m_ =
nullptr; sl.owns_ =
false;
423 std::unique_lock<mutex_type>&& ul)
425 , owns_(ul.owns_lock())
429 m_->unlock_and_lock_shared();
436 template <
class Rep,
class Period>
438 const std::chrono::duration<Rep, Period>& rel_time)
440 return try_lock_until(std::chrono::steady_clock::now() + rel_time);
443 template <
class Clock,
class Duration>
446 const std::chrono::time_point<Clock, Duration>& abs_time);
453 std::swap(owns_, u.owns_);
469 operator int __nat::* ()
const {
470 return owns_ ? &__nat::_ : 0;
479 template <
class Mutex>
485 throw std::system_error(std::error_code(EPERM, std::system_category()),
486 "shared_lock::lock: references null mutex");
490 throw std::system_error(std::error_code(EDEADLK, std::system_category()),
491 "shared_lock::lock: already locked");
497 template <
class Mutex>
503 throw std::system_error(std::error_code(EPERM, std::system_category()),
504 "shared_lock::try_lock: references null mutex");
508 throw std::system_error(std::error_code(EDEADLK, std::system_category()),
509 "shared_lock::try_lock: already locked");
511 owns_ = m_->try_lock_shared();
515 template <
class Mutex>
516 template <
class Clock,
class Duration>
519 const std::chrono::time_point<Clock, Duration>& abs_time)
523 throw std::system_error(std::error_code(EPERM, std::system_category()),
524 "shared_lock::try_lock_until: references null mutex");
528 throw std::system_error(std::error_code(EDEADLK, std::system_category()),
529 "shared_lock::try_lock_until: already locked");
531 owns_ = m_->try_lock_shared_until(abs_time);
535 template <
class Mutex>
541 throw std::system_error(std::error_code(EPERM, std::system_category()),
542 "shared_lock::unlock: not locked");
548 template <
class Mutex>
560 #else // fallback to STL 562 #include <shared_mutex> 566 using std::shared_lock;
571 #endif // shared_lock selection 573 #ifndef USE_THIRDPARTY_SHARED_MUTEX 574 # if defined(_MSC_VER) && _MSVC_LANG < 202302L 575 # pragma message("warning: USE_THIRDPARTY_SHARED_MUTEX not defined. By default use framework version.") 577 # warning "USE_THIRDPARTY_SHARED_MUTEX not defined. By default use framework version." 578 # endif // if defined(_MSC_VER) && _MSVC_LANG < 202302L 579 # define USE_THIRDPARTY_SHARED_MUTEX 0 580 #endif // ifndef USE_THIRDPARTY_SHARED_MUTEX 583 #if defined(__has_include) && __has_include(<version>) && !defined(__cpp_lib_shared_mutex) || \ 585 (~USE_THIRDPARTY_SHARED_MUTEX + 1) || \ 587 ( !(defined(__has_include) && __has_include(<version>)) && \ 588 !(defined(HAVE_CXX17) && HAVE_CXX17) && __cplusplus < 201703 ) 643 #else // fallback to STL 645 #include <shared_mutex> 649 using std::shared_mutex;
653 #endif // shared_mutex selection 655 #endif // _UTILS_SHARED_MUTEX_HPP_ shared_lock(mutex_type &m)
Definition: shared_mutex.hpp:337
count_t state_
Definition: shared_mutex.hpp:62
shared_lock(mutex_type &m, std::adopt_lock_t)
Definition: shared_mutex.hpp:361
void unlock()
Definition: shared_mutex.hpp:537
void unlock_shared()
Definition: shared_mutex.hpp:204
~shared_lock()
Definition: shared_mutex.hpp:387
bool try_lock()
Definition: shared_mutex.hpp:246
bool owns_lock() const
Definition: shared_mutex.hpp:464
Mutex mutex_type
Definition: shared_mutex.hpp:317
shared_lock(mutex_type &m, const std::chrono::time_point< Clock, Duration > &abs_time)
Definition: shared_mutex.hpp:370
mutex_type * mutex() const
Definition: shared_mutex.hpp:472
bool try_lock()
Definition: shared_mutex.hpp:499
shared_lock(shared_lock &&sl)
Definition: shared_mutex.hpp:400
cond_t gate1_
Definition: shared_mutex.hpp:61
void lock()
Definition: shared_mutex.hpp:147
void unlock()
Definition: shared_mutex.hpp:257
shared_lock()
Definition: shared_mutex.hpp:331
std::mutex mutex_t
Definition: shared_mutex.hpp:56
std::condition_variable cond_t
Definition: shared_mutex.hpp:57
Definition: shared_mutex.hpp:222
bool try_lock_for(const std::chrono::duration< Rep, Period > &rel_time)
Definition: shared_mutex.hpp:437
void lock()
Definition: shared_mutex.hpp:239
bool try_lock_shared()
Definition: shared_mutex.hpp:118
~shared_mutex_base()
Definition: shared_mutex.hpp:74
void unlock()
Definition: shared_mutex.hpp:97
void swap(shared_lock< Mutex > &x, shared_lock< Mutex > &y)
Definition: shared_mutex.hpp:551
shared_lock(mutex_type &m, std::try_to_lock_t)
Definition: shared_mutex.hpp:353
eProsima namespace.
Definition: LibrarySettingsAttributes.h:23
void lock()
Definition: shared_mutex.hpp:192
mutex_type * release()
Definition: shared_mutex.hpp:456
void unlock_shared()
Definition: shared_mutex.hpp:284
shared_lock(std::unique_lock< mutex_type > &&ul)
Definition: shared_mutex.hpp:422
shared_mutex_type
Definition: shared_mutex.hpp:46
mutex_t mut_
Definition: shared_mutex.hpp:60
bool try_lock_shared()
Definition: shared_mutex.hpp:273
Definition: shared_mutex.hpp:135
void unlock_shared()
Definition: shared_mutex.hpp:161
bool try_lock_until(const std::chrono::time_point< Clock, Duration > &abs_time)
Definition: shared_mutex.hpp:518
shared_mutex_base()
Definition: shared_mutex.hpp:69
Definition: shared_mutex.hpp:313
unsigned count_t
Definition: shared_mutex.hpp:58
shared_lock(mutex_type &m, const std::chrono::duration< Rep, Period > &rel_time)
Definition: shared_mutex.hpp:379
void lock_shared()
Definition: shared_mutex.hpp:106
bool try_lock()
Definition: shared_mutex.hpp:86
~debug_wrapper()
Definition: shared_mutex.hpp:232
shared_lock(mutex_type &m, std::defer_lock_t)
Definition: shared_mutex.hpp:345
Definition: shared_mutex.hpp:51
void swap(shared_lock &&u)
Definition: shared_mutex.hpp:449
void lock_shared()
Definition: shared_mutex.hpp:266
void lock()
Definition: shared_mutex.hpp:481