X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fcommon%2FCond.h;fp=src%2Fceph%2Fsrc%2Fcommon%2FCond.h;h=aa53b60f2349e16ff488b9fcf6f827d564412041;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/common/Cond.h b/src/ceph/src/common/Cond.h new file mode 100644 index 0000000..aa53b60 --- /dev/null +++ b/src/ceph/src/common/Cond.h @@ -0,0 +1,199 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + + +#ifndef CEPH_COND_H +#define CEPH_COND_H + +#include "include/Context.h" + +class Cond { + // my bits + pthread_cond_t _c; + + Mutex *waiter_mutex; + + // don't allow copying. + void operator=(Cond &C); + Cond(const Cond &C); + + public: + Cond() : waiter_mutex(NULL) { + int r = pthread_cond_init(&_c,NULL); + assert(r == 0); + } + virtual ~Cond() { + pthread_cond_destroy(&_c); + } + + int Wait(Mutex &mutex) { + // make sure this cond is used with one mutex only + assert(waiter_mutex == NULL || waiter_mutex == &mutex); + waiter_mutex = &mutex; + + assert(mutex.is_locked()); + + mutex._pre_unlock(); + int r = pthread_cond_wait(&_c, &mutex._m); + mutex._post_lock(); + return r; + } + + int WaitUntil(Mutex &mutex, utime_t when) { + // make sure this cond is used with one mutex only + assert(waiter_mutex == NULL || waiter_mutex == &mutex); + waiter_mutex = &mutex; + + assert(mutex.is_locked()); + + struct timespec ts; + when.to_timespec(&ts); + + mutex._pre_unlock(); + int r = pthread_cond_timedwait(&_c, &mutex._m, &ts); + mutex._post_lock(); + + return r; + } + + int WaitInterval(Mutex &mutex, utime_t interval) { + utime_t when = ceph_clock_now(); + when += interval; + return WaitUntil(mutex, when); + } + + template + int WaitInterval(Mutex &mutex, Duration interval) { + ceph::real_time when(ceph::real_clock::now()); + when += interval; + + struct timespec ts = ceph::real_clock::to_timespec(when); + + mutex._pre_unlock(); + int r = pthread_cond_timedwait(&_c, &mutex._m, &ts); + mutex._post_lock(); + + return r; + } + + int SloppySignal() { + int r = pthread_cond_broadcast(&_c); + return r; + } + int Signal() { + // make sure signaler is holding the waiter's lock. + assert(waiter_mutex == NULL || + waiter_mutex->is_locked()); + + int r = pthread_cond_broadcast(&_c); + return r; + } + int SignalOne() { + // make sure signaler is holding the waiter's lock. + assert(waiter_mutex == NULL || + waiter_mutex->is_locked()); + + int r = pthread_cond_signal(&_c); + return r; + } + int SignalAll() { + // make sure signaler is holding the waiter's lock. + assert(waiter_mutex == NULL || + waiter_mutex->is_locked()); + + int r = pthread_cond_broadcast(&_c); + return r; + } +}; + +/** + * context to signal a cond + * + * Generic context to signal a cond and store the return value. We + * assume the caller is holding the appropriate lock. + */ +class C_Cond : public Context { + Cond *cond; ///< Cond to signal + bool *done; ///< true if finish() has been called + int *rval; ///< return value +public: + C_Cond(Cond *c, bool *d, int *r) : cond(c), done(d), rval(r) { + *done = false; + } + void finish(int r) override { + *done = true; + *rval = r; + cond->Signal(); + } +}; + +/** + * context to signal a cond, protected by a lock + * + * Generic context to signal a cond under a specific lock. We take the + * lock in the finish() callback, so the finish() caller must not + * already hold it. + */ +class C_SafeCond : public Context { + Mutex *lock; ///< Mutex to take + Cond *cond; ///< Cond to signal + bool *done; ///< true after finish() has been called + int *rval; ///< return value (optional) +public: + C_SafeCond(Mutex *l, Cond *c, bool *d, int *r=0) : lock(l), cond(c), done(d), rval(r) { + *done = false; + } + void finish(int r) override { + lock->Lock(); + if (rval) + *rval = r; + *done = true; + cond->Signal(); + lock->Unlock(); + } +}; + +/** + * Context providing a simple wait() mechanism to wait for completion + * + * The context will not be deleted as part of complete and must live + * until wait() returns. + */ +class C_SaferCond : public Context { + Mutex lock; ///< Mutex to take + Cond cond; ///< Cond to signal + bool done; ///< true after finish() has been called + int rval; ///< return value +public: + C_SaferCond() : lock("C_SaferCond"), done(false), rval(0) {} + void finish(int r) override { complete(r); } + + /// We overload complete in order to not delete the context + void complete(int r) override { + Mutex::Locker l(lock); + done = true; + rval = r; + cond.Signal(); + } + + /// Returns rval once the Context is called + int wait() { + Mutex::Locker l(lock); + while (!done) + cond.Wait(lock); + return rval; + } +}; + +#endif