// -*- 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 "common/Clock.h" #include "common/ceph_mutex.h" #include "include/Context.h" /** * 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 { ceph::condition_variable& cond; ///< Cond to signal bool *done; ///< true if finish() has been called int *rval; ///< return value public: C_Cond(ceph::condition_variable &c, bool *d, int *r) : cond(c), done(d), rval(r) { *done = false; } void finish(int r) override { *done = true; *rval = r; cond.notify_all(); } }; /** * 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 { ceph::mutex& lock; ///< Mutex to take ceph::condition_variable& cond; ///< Cond to signal bool *done; ///< true after finish() has been called int *rval; ///< return value (optional) public: C_SafeCond(ceph::mutex& l, ceph::condition_variable& c, bool *d, int *r=0) : lock(l), cond(c), done(d), rval(r) { *done = false; } void finish(int r) override { std::lock_guard l{lock}; if (rval) *rval = r; *done = true; cond.notify_all(); } }; /** * 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 { ceph::mutex lock; ///< Mutex to take ceph::condition_variable cond; ///< Cond to signal bool done = false; ///< true after finish() has been called int rval = 0; ///< return value public: C_SaferCond() : C_SaferCond("C_SaferCond") {} explicit C_SaferCond(const std::string &name) : lock(ceph::make_mutex(name)) {} void finish(int r) override { complete(r); } /// We overload complete in order to not delete the context void complete(int r) override { std::lock_guard l(lock); done = true; rval = r; cond.notify_all(); } /// Returns rval once the Context is called int wait() { std::unique_lock l{lock}; cond.wait(l, [this] { return done;}); return rval; } /// Wait until the \c secs expires or \c complete() is called int wait_for(double secs) { return wait_for(ceph::make_timespan(secs)); } int wait_for(ceph::timespan secs) { std::unique_lock l{lock}; if (done) { return rval; } if (cond.wait_for(l, secs, [this] { return done; })) { return rval; } else { return ETIMEDOUT; } } }; #endif