userver: userver/engine/shared_mutex.hpp Source File
Loading...
Searching...
No Matches
shared_mutex.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/engine/shared_mutex.hpp
4/// @brief @copybrief engine::SharedMutex
5
6#include <userver/engine/condition_variable.hpp>
7#include <userver/engine/mutex.hpp>
8#include <userver/engine/semaphore.hpp>
9
10USERVER_NAMESPACE_BEGIN
11
12namespace engine {
13
14/// @ingroup userver_concurrency
15///
16/// @brief std::shared_mutex replacement for asynchronous tasks
17///
18/// ## Example usage:
19///
20/// @snippet engine/shared_mutex_test.cpp Sample engine::SharedMutex usage
21///
22/// @see @ref scripts/docs/en/userver/synchronization.md
23class SharedMutex final {
24 public:
25 SharedMutex();
26 ~SharedMutex() = default;
27
28 SharedMutex(const SharedMutex&) = delete;
29 SharedMutex(SharedMutex&&) = delete;
30 SharedMutex& operator=(const SharedMutex&) = delete;
31 SharedMutex& operator=(SharedMutex&&) = delete;
32
33 void lock();
34 void unlock();
35
36 bool try_lock();
37
38 template <typename Rep, typename Period>
39 bool try_lock_for(const std::chrono::duration<Rep, Period>&);
40
41 template <typename Clock, typename Duration>
42 bool try_lock_until(const std::chrono::time_point<Clock, Duration>&);
43
44 bool try_lock_until(Deadline deadline);
45
46 void lock_shared();
47 void unlock_shared();
48 bool try_lock_shared();
49
50 template <typename Rep, typename Period>
51 bool try_lock_shared_for(const std::chrono::duration<Rep, Period>&);
52
53 template <typename Clock, typename Duration>
54 bool try_lock_shared_until(const std::chrono::time_point<Clock, Duration>&);
55
56 bool try_lock_shared_until(Deadline deadline);
57
58 private:
59 bool HasWaitingWriter() const noexcept;
60
61 bool WaitForNoWaitingWriters(Deadline deadline);
62
63 void DecWaitingWriters();
64
65 /* Semaphore can be get by 1 or by SIZE_MAX.
66 * 1 = reader, SIZE_MAX = writer.
67 *
68 * Three possible cases:
69 * 1) semaphore is free
70 * 2) there are readers in critical section (any count)
71 * 3) there is a single writer in critical section
72 */
73 Semaphore semaphore_;
74
75 /* Readers don't try to hold semaphore_ if there is at least one
76 * waiting writer => writers don't starve.
77 */
78 std::atomic_size_t waiting_writers_count_;
79 Mutex waiting_writers_count_mutex_;
80 ConditionVariable waiting_writers_count_cv_;
81};
82
83template <typename Rep, typename Period>
84bool SharedMutex::try_lock_for(
85 const std::chrono::duration<Rep, Period>& duration) {
86 return try_lock_until(Deadline::FromDuration(duration));
87}
88
89template <typename Rep, typename Period>
90bool SharedMutex::try_lock_shared_for(
91 const std::chrono::duration<Rep, Period>& duration) {
92 return try_lock_shared_until(Deadline::FromDuration(duration));
93}
94
95template <typename Clock, typename Duration>
96bool SharedMutex::try_lock_until(
97 const std::chrono::time_point<Clock, Duration>& until) {
98 return try_lock_until(Deadline::FromTimePoint(until));
99}
100
101template <typename Clock, typename Duration>
102bool SharedMutex::try_lock_shared_until(
103 const std::chrono::time_point<Clock, Duration>& until) {
104 return try_lock_shared_until(Deadline::FromTimePoint(until));
105}
106
107} // namespace engine
108
109USERVER_NAMESPACE_END