]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #pragma once | |
5 | ||
6 | #include <condition_variable> | |
7 | #include <ctime> | |
8 | #include <pthread.h> | |
9 | #include "common/ceph_time.h" | |
10 | ||
11 | namespace ceph { | |
12 | ||
13 | namespace mutex_debug_detail { | |
14 | template<bool> class mutex_debug_impl; | |
15 | } | |
16 | ||
17 | class condition_variable_debug { | |
18 | using mutex_debug = mutex_debug_detail::mutex_debug_impl<false>; | |
19 | ||
20 | pthread_cond_t cond; | |
21 | mutex_debug* waiter_mutex; | |
22 | ||
23 | condition_variable_debug& | |
24 | operator=(const condition_variable_debug&) = delete; | |
25 | condition_variable_debug(const condition_variable_debug&) = delete; | |
26 | ||
27 | public: | |
28 | condition_variable_debug(); | |
29 | ~condition_variable_debug(); | |
30 | void wait(std::unique_lock<mutex_debug>& lock); | |
31 | template<class Predicate> | |
32 | void wait(std::unique_lock<mutex_debug>& lock, Predicate pred) { | |
33 | while (!pred()) { | |
34 | wait(lock); | |
35 | } | |
36 | } | |
37 | template<class Clock, class Duration> | |
38 | std::cv_status wait_until( | |
39 | std::unique_lock<mutex_debug>& lock, | |
40 | const std::chrono::time_point<Clock, Duration>& when) { | |
20effc67 TL |
41 | if constexpr (Clock::is_steady) { |
42 | // convert from mono_clock to real_clock | |
43 | auto real_when = ceph::real_clock::now(); | |
44 | const auto delta = when - Clock::now(); | |
45 | real_when += std::chrono::ceil<typename Clock::duration>(delta); | |
46 | timespec ts = ceph::real_clock::to_timespec(real_when); | |
47 | return _wait_until(lock.mutex(), &ts); | |
48 | } else { | |
49 | timespec ts = Clock::to_timespec(when); | |
50 | return _wait_until(lock.mutex(), &ts); | |
51 | } | |
11fdf7f2 TL |
52 | } |
53 | template<class Rep, class Period> | |
54 | std::cv_status wait_for( | |
55 | std::unique_lock<mutex_debug>& lock, | |
56 | const std::chrono::duration<Rep, Period>& awhile) { | |
57 | ceph::real_time when{ceph::real_clock::now()}; | |
58 | when += awhile; | |
59 | timespec ts = ceph::real_clock::to_timespec(when); | |
60 | return _wait_until(lock.mutex(), &ts); | |
61 | } | |
9f95a23c TL |
62 | template<class Rep, class Period, class Pred> |
63 | bool wait_for( | |
64 | std::unique_lock<mutex_debug>& lock, | |
65 | const std::chrono::duration<Rep, Period>& awhile, | |
66 | Pred pred) { | |
67 | ceph::real_time when{ceph::real_clock::now()}; | |
68 | when += awhile; | |
69 | timespec ts = ceph::real_clock::to_timespec(when); | |
70 | while (!pred()) { | |
71 | if ( _wait_until(lock.mutex(), &ts) == std::cv_status::timeout) { | |
72 | return pred(); | |
73 | } | |
74 | } | |
75 | return true; | |
76 | } | |
11fdf7f2 TL |
77 | void notify_one(); |
78 | void notify_all(bool sloppy = false); | |
79 | private: | |
80 | std::cv_status _wait_until(mutex_debug* mutex, timespec* ts); | |
81 | }; | |
82 | ||
83 | } // namespace ceph |