]>
Commit | Line | Data |
---|---|---|
a4b75251 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*- |
2 | ||
3 | #pragma once | |
4 | ||
5 | #include "common/ceph_mutex.h" | |
6 | ||
7 | #include <thread> | |
8 | #include <string> | |
9 | ||
10 | namespace ceph { | |
11 | /// a FIFO mutex | |
12 | class fair_mutex { | |
13 | public: | |
14 | fair_mutex(const std::string& name) | |
15 | : mutex{ceph::make_mutex(name)} | |
16 | {} | |
17 | ~fair_mutex() = default; | |
18 | fair_mutex(const fair_mutex&) = delete; | |
19 | fair_mutex& operator=(const fair_mutex&) = delete; | |
20 | ||
21 | void lock() | |
22 | { | |
23 | std::unique_lock lock(mutex); | |
24 | const unsigned my_id = next_id++; | |
25 | cond.wait(lock, [&] { | |
26 | return my_id == unblock_id; | |
27 | }); | |
28 | _set_locked_by(); | |
29 | } | |
30 | ||
31 | bool try_lock() | |
32 | { | |
33 | std::lock_guard lock(mutex); | |
34 | if (is_locked()) { | |
35 | return false; | |
36 | } | |
37 | ++next_id; | |
38 | _set_locked_by(); | |
39 | return true; | |
40 | } | |
41 | ||
42 | void unlock() | |
43 | { | |
44 | std::lock_guard lock(mutex); | |
45 | ++unblock_id; | |
46 | _reset_locked_by(); | |
47 | cond.notify_all(); | |
48 | } | |
49 | ||
50 | bool is_locked() const | |
51 | { | |
52 | return next_id != unblock_id; | |
53 | } | |
54 | ||
55 | #ifdef CEPH_DEBUG_MUTEX | |
56 | bool is_locked_by_me() const { | |
57 | return is_locked() && locked_by == std::this_thread::get_id(); | |
58 | } | |
59 | private: | |
60 | void _set_locked_by() { | |
61 | locked_by = std::this_thread::get_id(); | |
62 | } | |
63 | void _reset_locked_by() { | |
64 | locked_by = {}; | |
65 | } | |
66 | #else | |
67 | void _set_locked_by() {} | |
68 | void _reset_locked_by() {} | |
69 | #endif | |
70 | ||
71 | private: | |
72 | unsigned next_id = 0; | |
73 | unsigned unblock_id = 0; | |
74 | ceph::condition_variable cond; | |
75 | ceph::mutex mutex; | |
76 | #ifdef CEPH_DEBUG_MUTEX | |
77 | std::thread::id locked_by = {}; | |
78 | #endif | |
79 | }; | |
80 | } // namespace ceph |