fairness  v1.0.0
A collection of advanced syncronization mechanisms.
Loading...
Searching...
No Matches
shared_priority_mutex.hpp
Go to the documentation of this file.
1
12#ifndef BOOST_FAIRNESS_SHARED_PRIORITY_MUTEX_HPP
13#define BOOST_FAIRNESS_SHARED_PRIORITY_MUTEX_HPP
14#include <array>
15#include <atomic>
19
20namespace boost::fairness{
21
22 #define WAIT 0
23 #define PROCEED 1
24
47 template<size_t N = 1>
48 requires (N >= 1 && N <= BOOST_FAIRNESS_MAXIMUM_PRIORITY)
50
51 using Thread_cnt_t = uint32_t;
52
53 struct threadPriority{
54 Thread_cnt_t writers_waiting{};
55 Thread_cnt_t readers_waiting{};
56 };
57
58 template<size_t S = 1>
59 requires (S >= 1 && S <= BOOST_FAIRNESS_MAXIMUM_PRIORITY)
60 struct waitingFlags{
61 std::array<std::atomic<uint32_t>, S> writers{};
62 std::array<std::atomic<uint32_t>, S> readers{};
63 };
64
65 public:
66
68 shared_priority_mutex() = default;
69
72
74 shared_priority_mutex& operator=(const shared_priority_mutex&) = delete;
75
78
80 shared_priority_mutex& operator=(shared_priority_mutex&&) = delete;
81
83 ~shared_priority_mutex() = default;
84
109 void lock(Priority_t const priority = 0){
110
111 internalMutex_.lock(priority);
112
113 ++priorities_[priority].writers_waiting;
114
115 ++totalWritersWaiting_;
116
117 for (;;)
118 {
119
120 if (
121 totalCurrentReaders_ == 0 &&
122 !lockOwned_ &&
123 find_first_priority_() >= priority
124 ){
125 --priorities_[priority].writers_waiting;
126
127 --totalWritersWaiting_;
128
129 lockOwned_ = true;
130
131 internalMutex_.unlock();
132
133 return;
134 }
135
136 internalMutex_.unlock();
137
138 detail::wait(waitingFlags_.writers[priority], WAIT);
139
140 internalMutex_.lock(priority);
141
142 }
143 }
144
169 void unlock(){
170
171 Priority_t p;
172
173 internalMutex_.lock();
174
175 lockOwned_ = false;
176
177 p = find_first_priority_();
178
180 {
181 internalMutex_.unlock();
182
183 return;
184 }
185
186 if (totalWritersWaiting_ == 0)
187 {
188 allow_all_readers_();
189
190 internalMutex_.unlock();
191
192 notify_all_readers_();
193
194 return;
195 }
196
197 reset_(p);
198
199 internalMutex_.unlock();
200
201 notify_priority_(p);
202
203 }
204
231 [[nodiscard]] bool try_lock(Priority_t const priority = 0){
232
233 internalMutex_.lock(priority);
234
235 if (lockOwned_ ||
236 totalCurrentReaders_ > 0 ||
237 find_first_priority_() < priority)
238 {
239
240 internalMutex_.unlock();
241
242 return false;
243 }
244
245 lockOwned_ = true;
246
247 internalMutex_.unlock();
248
249 return true;
250
251 }
252
281 void lock_shared(Priority_t priority = 0){
282
283 internalMutex_.lock(priority);
284
285 ++priorities_[priority].readers_waiting;
286
287 for(;;){
288
289 if (!lockOwned_ && find_first_priority_with_writers_() >= priority)
290 {
291 ++totalCurrentReaders_;
292
293 --priorities_[priority].readers_waiting;
294
295 internalMutex_.unlock();
296
297 return;
298 }
299
300 internalMutex_.unlock();
301
302 detail::wait(waitingFlags_.readers[priority], WAIT);
303
304 internalMutex_.lock(priority);
305
306 }
307 }
308
334
335 Priority_t p;
336
337 internalMutex_.lock();
338
339 --totalCurrentReaders_;
340
341 p = find_first_priority_();
342
344 {
345 internalMutex_.unlock();
346
347 return;
348 }
349
350 if (totalWritersWaiting_ == 0)
351 {
352 allow_all_readers_();
353
354 internalMutex_.unlock();
355
356 notify_all_readers_();
357
358 return;
359 }
360
361 if (totalCurrentReaders_ == 0)
362 {
363 reset_(p);
364
365 internalMutex_.unlock();
366
367 notify_priority_(p);
368
369 return;
370 }
371
372 internalMutex_.unlock();
373
374 }
375
403 [[nodiscard]] bool try_lock_shared(Priority_t priority = 0){
404
405 internalMutex_.lock(priority);
406
407 if (lockOwned_ || find_first_priority_with_writers_() < priority){
408
409 internalMutex_.unlock();
410
411 return false;
412 }
413
414 ++totalCurrentReaders_;
415
416 internalMutex_.unlock();
417
418 return true;
419
420 }
421
422 private:
423
425 alignas(BOOST_FAIRNESS_HARDWARE_DESTRUCTIVE_SIZE) waitingFlags<N> waitingFlags_;
426 std::array<threadPriority, N> priorities_{};
427 Thread_cnt_t totalCurrentReaders_{};
428 Thread_cnt_t totalWritersWaiting_{};
429 bool lockOwned_{};
430
431 Priority_t find_first_priority_() const {
432 for (Priority_t i = 0; i < N; ++i){
433 if (priorities_[i].writers_waiting+priorities_[i].readers_waiting > 0)
434 return i;
435 }
437 }
438
439 Priority_t find_first_priority_with_writers_() const {
440 for (Priority_t i = 0; i < N; ++i){
441 if (priorities_[i].writers_waiting > 0)
442 return i;
443 }
445 }
446
447 void notify_all_readers_(){
448 for (Priority_t i = 0; i < N; ++i){
449 waitingFlags_.readers[i].store(PROCEED);
450 detail::notify_all(waitingFlags_.readers[i]);
451 }
452 }
453
454 void notify_priority_(Priority_t const p){
455 detail::notify_one(waitingFlags_.writers[p]);
456 detail::notify_all(waitingFlags_.readers[p]);
457 }
458
459 void reset_(Priority_t const p){
460 for (Priority_t i = 0; i < N; ++i){
461 waitingFlags_.writers[i].store(WAIT);
462 waitingFlags_.readers[i].store(WAIT);
463 }
464 waitingFlags_.writers[p].store(PROCEED);
465 waitingFlags_.readers[p].store(PROCEED);
466 }
467
468 void allow_all_readers_(){
469 for (Priority_t i = 0; i < N; ++i){
470 waitingFlags_.readers[i].store(PROCEED);
471 waitingFlags_.writers[i].store(WAIT);
472 }
473 }
474 };
475
476 #undef WAIT
477 #undef PROCEED
478
479}
480#endif // BOOST_FAIRNESS_SHARED_PRIORITY_MUTEX_HPP
The shared_priority_mutex is an advanced synchronization mechanism that enhances the traditional shar...
Definition shared_priority_mutex.hpp:49
void lock(Priority_t const priority=0)
Try to acquire the unique ownership of the shared_priority_mutex, blocking the thread if the shared_p...
Definition shared_priority_mutex.hpp:109
void unlock()
Release the shared_priority_mutex from unique ownership. The mutex must be locked by the current th...
Definition shared_priority_mutex.hpp:169
void lock_shared(Priority_t priority=0)
Try to acquire the shared ownership of the shared_priority_mutex, blocking the thread if the shared_p...
Definition shared_priority_mutex.hpp:281
bool try_lock(Priority_t const priority=0)
Try to acquire the unique ownership of the shared_priority_mutex, if successful will return true,...
Definition shared_priority_mutex.hpp:231
bool try_lock_shared(Priority_t priority=0)
Try to acquire the shared ownership of the shared_priority_mutex, if successful will return true,...
Definition shared_priority_mutex.hpp:403
void unlock_shared()
Release the shared_priority_mutex from shared ownership by the calling thread. The mutex shared_prio...
Definition shared_priority_mutex.hpp:333
The spinlock_priority_mutex is an advanced synchronization mechanism that enhances the traditional mu...
Definition spinlock_priority_mutex_cpl.hpp:31
#define BOOST_FAIRNESS_HARDWARE_DESTRUCTIVE_SIZE
Size to be aligned to avoid false sharing
Definition config.hpp:85
void wait(T &mem, K const expected) noexcept
Definition wait_ops.hpp:69
void notify_all(T &mem) noexcept
Definition wait_ops.hpp:108
void notify_one(T &mem) noexcept
Definition wait_ops.hpp:103
Definition acquisition_modes.hpp:16
uint8_t Priority_t
Definition priority_t.hpp:17
#define PROCEED
Definition priority_mutex_tatas.hpp:25
#define WAIT
Definition priority_mutex_tatas.hpp:24
Alias the type Priority_t. Priority_t is the type of priorities that are used by the priority_mutexes...
#define BOOST_FAIRNESS_MAXIMUM_PRIORITY
Priorities are indexes in an array, that means that if I define a priority_mutex<BOOST_FAIRNESS_MAXIM...
Definition priority_t.hpp:24
This file contains the implementation of the spinlock_priority_mutex based on a scalable list base al...
This file contains the implementation of the wait operations used by the mutexes.