userver: userver/engine/mutex.hpp Source File
Loading...
Searching...
No Matches
mutex.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/engine/mutex.hpp
4/// @brief @copybrief engine::Mutex
5
6#include <atomic>
7#include <chrono>
8#include <mutex> // for std locks
9
10#include <userver/engine/deadline.hpp>
11#include <userver/engine/impl/wait_list_fwd.hpp>
12
13USERVER_NAMESPACE_BEGIN
14
15namespace engine {
16
17/// @ingroup userver_concurrency
18///
19/// @brief std::mutex replacement for asynchronous tasks.
20///
21/// Ignores task cancellations (succeeds even if the current task is cancelled).
22///
23/// ## Example usage:
24///
25/// @snippet engine/mutex_test.cpp Sample engine::Mutex usage
26///
27/// @see @ref scripts/docs/en/userver/synchronization.md
28class Mutex final {
29public:
30 Mutex();
31 ~Mutex();
32
33 Mutex(const Mutex&) = delete;
34 Mutex(Mutex&&) = delete;
35 Mutex& operator=(const Mutex&) = delete;
36 Mutex& operator=(Mutex&&) = delete;
37
38 /// Locks the mutex. Blocks current coroutine if the mutex is locked by
39 /// another coroutine. Throws if a coroutine tries to lock a mutex
40 /// which is already locked by the current coroutine.
41 ///
42 /// @note The method waits for the mutex even if the current task is
43 /// cancelled.
44 void lock();
45
46 /// Unlocks the mutex. Before calling this method the mutex should be locked
47 /// by the current coroutine.
48 ///
49 /// @note the order of coroutines to unblock is unspecified. Any code assuming
50 /// any specific order (e.g. FIFO) is incorrect and should be fixed.
51 void unlock();
52
53 /// Tries to lock the mutex without blocking the coroutine, returns true if
54 /// succeeded.
55 ///
56 /// @note The behavior of the function is not affected by the cancellation
57 /// requests.
58 [[nodiscard]] bool try_lock() noexcept;
59
60 /// Tries to lock the mutex in specified duration. Blocks current coroutine if
61 /// the mutex is locked by another coroutine up to the provided duration.
62 /// Throws if a coroutine tries to lock a mutex
63 /// which is already locked by the current coroutine.
64 ///
65 /// @returns true if the locking succeeded
66 ///
67 /// @note The method waits for the mutex even if the current task is
68 /// cancelled.
69 template <typename Rep, typename Period>
70 [[nodiscard]] bool try_lock_for(const std::chrono::duration<Rep, Period>&);
71
72 /// Tries to lock the mutex till specified time point. Blocks current
73 /// coroutine if the mutex is locked by another coroutine up to the provided
74 /// time point. Throws if a coroutine tries to lock a mutex
75 /// which is already locked by the current coroutine.
76 ///
77 /// @returns true if the locking succeeded
78 ///
79 /// @note The method waits for the mutex even if the current task is
80 /// cancelled.
81 template <typename Clock, typename Duration>
82 [[nodiscard]] bool try_lock_until(const std::chrono::time_point<Clock, Duration>&);
83
84 /// @overload
85 [[nodiscard]] bool try_lock_until(Deadline deadline);
86
87private:
88 class Impl;
89
90 utils::FastPimpl<Impl, 96, alignof(void*)> impl_;
91};
92
93template <typename Rep, typename Period>
94bool Mutex::try_lock_for(const std::chrono::duration<Rep, Period>& duration) {
95 return try_lock_until(Deadline::FromDuration(duration));
96}
97
98template <typename Clock, typename Duration>
99bool Mutex::try_lock_until(const std::chrono::time_point<Clock, Duration>& until) {
100 return try_lock_until(Deadline::FromTimePoint(until));
101}
102
103} // namespace engine
104
105USERVER_NAMESPACE_END