]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net> | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
15 | ||
16 | #ifndef CEPH_COND_H | |
17 | #define CEPH_COND_H | |
18 | ||
11fdf7f2 | 19 | #include "common/Clock.h" |
9f95a23c | 20 | #include "common/ceph_mutex.h" |
7c673cae | 21 | #include "include/Context.h" |
11fdf7f2 | 22 | |
7c673cae FG |
23 | /** |
24 | * context to signal a cond | |
25 | * | |
26 | * Generic context to signal a cond and store the return value. We | |
27 | * assume the caller is holding the appropriate lock. | |
28 | */ | |
29 | class C_Cond : public Context { | |
9f95a23c | 30 | ceph::condition_variable& cond; ///< Cond to signal |
7c673cae FG |
31 | bool *done; ///< true if finish() has been called |
32 | int *rval; ///< return value | |
33 | public: | |
9f95a23c | 34 | C_Cond(ceph::condition_variable &c, bool *d, int *r) : cond(c), done(d), rval(r) { |
7c673cae FG |
35 | *done = false; |
36 | } | |
37 | void finish(int r) override { | |
38 | *done = true; | |
39 | *rval = r; | |
9f95a23c | 40 | cond.notify_all(); |
7c673cae FG |
41 | } |
42 | }; | |
43 | ||
44 | /** | |
45 | * context to signal a cond, protected by a lock | |
46 | * | |
47 | * Generic context to signal a cond under a specific lock. We take the | |
48 | * lock in the finish() callback, so the finish() caller must not | |
49 | * already hold it. | |
50 | */ | |
51 | class C_SafeCond : public Context { | |
9f95a23c TL |
52 | ceph::mutex& lock; ///< Mutex to take |
53 | ceph::condition_variable& cond; ///< Cond to signal | |
7c673cae FG |
54 | bool *done; ///< true after finish() has been called |
55 | int *rval; ///< return value (optional) | |
56 | public: | |
9f95a23c TL |
57 | C_SafeCond(ceph::mutex& l, ceph::condition_variable& c, bool *d, int *r=0) |
58 | : lock(l), cond(c), done(d), rval(r) { | |
7c673cae FG |
59 | *done = false; |
60 | } | |
61 | void finish(int r) override { | |
9f95a23c | 62 | std::lock_guard l{lock}; |
7c673cae FG |
63 | if (rval) |
64 | *rval = r; | |
65 | *done = true; | |
9f95a23c | 66 | cond.notify_all(); |
7c673cae FG |
67 | } |
68 | }; | |
69 | ||
70 | /** | |
71 | * Context providing a simple wait() mechanism to wait for completion | |
72 | * | |
73 | * The context will not be deleted as part of complete and must live | |
74 | * until wait() returns. | |
75 | */ | |
76 | class C_SaferCond : public Context { | |
9f95a23c TL |
77 | ceph::mutex lock; ///< Mutex to take |
78 | ceph::condition_variable cond; ///< Cond to signal | |
79 | bool done = false; ///< true after finish() has been called | |
80 | int rval = 0; ///< return value | |
7c673cae | 81 | public: |
9f95a23c TL |
82 | C_SaferCond() : |
83 | C_SaferCond("C_SaferCond") | |
84 | {} | |
85 | explicit C_SaferCond(const std::string &name) | |
86 | : lock(ceph::make_mutex(name)) {} | |
7c673cae FG |
87 | void finish(int r) override { complete(r); } |
88 | ||
89 | /// We overload complete in order to not delete the context | |
90 | void complete(int r) override { | |
11fdf7f2 | 91 | std::lock_guard l(lock); |
7c673cae FG |
92 | done = true; |
93 | rval = r; | |
9f95a23c | 94 | cond.notify_all(); |
7c673cae FG |
95 | } |
96 | ||
97 | /// Returns rval once the Context is called | |
98 | int wait() { | |
9f95a23c TL |
99 | std::unique_lock l{lock}; |
100 | cond.wait(l, [this] { return done;}); | |
7c673cae FG |
101 | return rval; |
102 | } | |
11fdf7f2 TL |
103 | |
104 | /// Wait until the \c secs expires or \c complete() is called | |
105 | int wait_for(double secs) { | |
f91f0fd5 TL |
106 | return wait_for(ceph::make_timespan(secs)); |
107 | } | |
108 | ||
109 | int wait_for(ceph::timespan secs) { | |
9f95a23c | 110 | std::unique_lock l{lock}; |
11fdf7f2 TL |
111 | if (done) { |
112 | return rval; | |
113 | } | |
f91f0fd5 | 114 | if (cond.wait_for(l, secs, [this] { return done; })) { |
9f95a23c TL |
115 | return rval; |
116 | } else { | |
117 | return ETIMEDOUT; | |
118 | } | |
11fdf7f2 | 119 | } |
7c673cae FG |
120 | }; |
121 | ||
122 | #endif |