summaryrefslogtreecommitdiffstats
path: root/src/common/Cond.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/Cond.h')
-rw-r--r--src/common/Cond.h122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/common/Cond.h b/src/common/Cond.h
new file mode 100644
index 000000000..f41d0bf40
--- /dev/null
+++ b/src/common/Cond.h
@@ -0,0 +1,122 @@
+// -*- 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 <sage@newdream.net>
+ *
+ * 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