1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
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.
19 #include "include/Context.h"
27 // don't allow copying.
28 void operator=(Cond &C);
32 Cond() : waiter_mutex(NULL) {
33 int r = pthread_cond_init(&_c,NULL);
37 pthread_cond_destroy(&_c);
40 int Wait(Mutex &mutex) {
41 // make sure this cond is used with one mutex only
42 assert(waiter_mutex == NULL || waiter_mutex == &mutex);
43 waiter_mutex = &mutex;
45 assert(mutex.is_locked());
48 int r = pthread_cond_wait(&_c, &mutex._m);
53 int WaitUntil(Mutex &mutex, utime_t when) {
54 // make sure this cond is used with one mutex only
55 assert(waiter_mutex == NULL || waiter_mutex == &mutex);
56 waiter_mutex = &mutex;
58 assert(mutex.is_locked());
61 when.to_timespec(&ts);
64 int r = pthread_cond_timedwait(&_c, &mutex._m, &ts);
70 int WaitInterval(Mutex &mutex, utime_t interval) {
71 utime_t when = ceph_clock_now();
73 return WaitUntil(mutex, when);
76 template<typename Duration>
77 int WaitInterval(Mutex &mutex, Duration interval) {
78 ceph::real_time when(ceph::real_clock::now());
81 struct timespec ts = ceph::real_clock::to_timespec(when);
84 int r = pthread_cond_timedwait(&_c, &mutex._m, &ts);
91 int r = pthread_cond_broadcast(&_c);
95 // make sure signaler is holding the waiter's lock.
96 assert(waiter_mutex == NULL ||
97 waiter_mutex->is_locked());
99 int r = pthread_cond_broadcast(&_c);
103 // make sure signaler is holding the waiter's lock.
104 assert(waiter_mutex == NULL ||
105 waiter_mutex->is_locked());
107 int r = pthread_cond_signal(&_c);
111 // make sure signaler is holding the waiter's lock.
112 assert(waiter_mutex == NULL ||
113 waiter_mutex->is_locked());
115 int r = pthread_cond_broadcast(&_c);
121 * context to signal a cond
123 * Generic context to signal a cond and store the return value. We
124 * assume the caller is holding the appropriate lock.
126 class C_Cond : public Context {
127 Cond *cond; ///< Cond to signal
128 bool *done; ///< true if finish() has been called
129 int *rval; ///< return value
131 C_Cond(Cond *c, bool *d, int *r) : cond(c), done(d), rval(r) {
134 void finish(int r) override {
142 * context to signal a cond, protected by a lock
144 * Generic context to signal a cond under a specific lock. We take the
145 * lock in the finish() callback, so the finish() caller must not
148 class C_SafeCond : public Context {
149 Mutex *lock; ///< Mutex to take
150 Cond *cond; ///< Cond to signal
151 bool *done; ///< true after finish() has been called
152 int *rval; ///< return value (optional)
154 C_SafeCond(Mutex *l, Cond *c, bool *d, int *r=0) : lock(l), cond(c), done(d), rval(r) {
157 void finish(int r) override {
168 * Context providing a simple wait() mechanism to wait for completion
170 * The context will not be deleted as part of complete and must live
171 * until wait() returns.
173 class C_SaferCond : public Context {
174 Mutex lock; ///< Mutex to take
175 Cond cond; ///< Cond to signal
176 bool done; ///< true after finish() has been called
177 int rval; ///< return value
179 C_SaferCond() : lock("C_SaferCond"), done(false), rval(0) {}
180 void finish(int r) override { complete(r); }
182 /// We overload complete in order to not delete the context
183 void complete(int r) override {
184 Mutex::Locker l(lock);
190 /// Returns rval once the Context is called
192 Mutex::Locker l(lock);