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.
16 #ifndef CEPH_CONTEXT_H
17 #define CEPH_CONTEXT_H
19 #include "common/dout.h"
21 #include <boost/function.hpp>
26 #include "include/assert.h"
27 #include "include/memory.h"
29 #define mydout(cct, v) lgeneric_subdout(cct, context, v)
32 * GenContext - abstract callback class
36 GenContext(const GenContext& other);
37 const GenContext& operator=(const GenContext& other);
40 virtual void finish(T t) = 0;
44 virtual ~GenContext() {} // we want a virtual destructor!!!
47 void complete(C &&t) {
48 finish(std::forward<C>(t));
54 using GenContextURef = std::unique_ptr<GenContext<T> >;
57 * Context - abstract callback class
60 Context(const Context& other);
61 const Context& operator=(const Context& other);
64 virtual void finish(int r) = 0;
68 virtual ~Context() {} // we want a virtual destructor!!!
69 virtual void complete(int r) {
76 * Simple context holding a single object
79 class ContainerContext : public Context {
82 ContainerContext(T &obj) : obj(obj) {}
83 void finish(int r) override {}
86 ContainerContext<T> *make_container_context(T &&t) {
87 return new ContainerContext<T>(std::forward<T>(t));
91 struct Wrapper : public Context {
94 Wrapper(Context *to_run, T val) : to_run(to_run), val(val) {}
95 void finish(int r) override {
102 RunOnDelete(Context *to_run) : to_run(to_run) {}
108 typedef ceph::shared_ptr<RunOnDelete> RunOnDeleteRef;
110 template <typename T>
111 struct LambdaContext : public Context {
113 LambdaContext(T &&t) : t(std::forward<T>(t)) {}
114 void finish(int) override {
118 template <typename T>
119 LambdaContext<T> *make_lambda_context(T &&t) {
120 return new LambdaContext<T>(std::move(t));
123 template <typename F, typename T>
124 struct LambdaGenContext : GenContext<T> {
126 LambdaGenContext(F &&f) : f(std::forward<F>(f)) {}
127 void finish(T t) override {
128 f(std::forward<T>(t));
131 template <typename T, typename F>
132 GenContextURef<T> make_gen_lambda_context(F &&f) {
133 return GenContextURef<T>(new LambdaGenContext<F, T>(std::move(f)));
137 * finish and destroy a list of Contexts
140 inline void finish_contexts(CephContext *cct, std::list<A*>& finished,
143 if (finished.empty())
147 ls.swap(finished); // swap out of place to avoid weird loops
150 mydout(cct, 10) << ls.size() << " contexts to finish with " << result << dendl;
151 typename std::list<A*>::iterator it;
152 for (it = ls.begin(); it != ls.end(); it++) {
155 mydout(cct,10) << "---- " << c << dendl;
160 inline void finish_contexts(CephContext *cct, std::vector<Context*>& finished,
163 if (finished.empty())
167 ls.swap(finished); // swap out of place to avoid weird loops
170 mydout(cct,10) << ls.size() << " contexts to finish with " << result << dendl;
171 for (std::vector<Context*>::iterator it = ls.begin();
176 mydout(cct,10) << "---- " << c << dendl;
181 class C_NoopContext : public Context {
183 void finish(int r) override { }
187 struct C_Lock : public Context {
190 C_Lock(Mutex *l, Context *c) : lock(l), fin(c) {}
194 void finish(int r) override {
205 * C_Contexts - set of Contexts
207 * ContextType must be an ancestor class of ContextInstanceType, or the same class.
208 * ContextInstanceType must be default-constructable.
210 template <class ContextType, class ContextInstanceType>
211 class C_ContextsBase : public ContextInstanceType {
214 std::list<ContextType*> contexts;
216 C_ContextsBase(CephContext *cct_)
220 ~C_ContextsBase() override {
221 for (auto c : contexts) {
225 void add(ContextType* c) {
226 contexts.push_back(c);
228 void take(std::list<ContextType*>& ls) {
229 contexts.splice(contexts.end(), ls);
231 void complete(int r) override {
232 // Neuter any ContextInstanceType custom complete(), because although
233 // I want to look like it, I don't actually want to run its code.
234 Context::complete(r);
236 void finish(int r) override {
237 finish_contexts(cct, contexts, r);
239 bool empty() { return contexts.empty(); }
241 static ContextType *list_to_context(list<ContextType *> &cs) {
242 if (cs.size() == 0) {
244 } else if (cs.size() == 1) {
245 ContextType *c = cs.front();
249 C_ContextsBase<ContextType, ContextInstanceType> *c(new C_ContextsBase<ContextType, ContextInstanceType>(0));
256 typedef C_ContextsBase<Context, Context> C_Contexts;
261 * ContextType must be an ancestor class of ContextInstanceType, or the same class.
262 * ContextInstanceType must be default-constructable.
264 * BUG:? only reports error from last sub to have an error return
266 template <class ContextType, class ContextInstanceType>
267 class C_GatherBase : public ContextType {
271 ContextType *onfinish;
273 std::set<ContextType*> waitfor;
275 int sub_created_count;
276 int sub_existing_count;
280 void sub_finish(ContextType* sub, int r) {
283 assert(waitfor.count(sub));
286 --sub_existing_count;
287 mydout(cct,10) << "C_GatherBase " << this << ".sub_finish(r=" << r << ") " << sub
289 << " (remaining " << waitfor << ")"
292 if (r < 0 && result == 0)
294 if ((activated == false) || (sub_existing_count != 0)) {
304 onfinish->complete(result);
310 class C_GatherSub : public ContextInstanceType {
311 C_GatherBase *gather;
313 C_GatherSub(C_GatherBase *g) : gather(g) {}
314 void complete(int r) override {
315 // Cancel any customized complete() functionality
316 // from the Context subclass we're templated for,
317 // we only want to hit that in onfinish, not at each
318 // sub finish. e.g. MDSInternalContext.
319 Context::complete(r);
321 void finish(int r) override {
322 gather->sub_finish(this, r);
325 ~C_GatherSub() override {
327 gather->sub_finish(this, 0);
332 C_GatherBase(CephContext *cct_, ContextType *onfinish_)
333 : cct(cct_), result(0), onfinish(onfinish_),
334 sub_created_count(0), sub_existing_count(0),
335 lock("C_GatherBase::lock", true, false), //disable lockdep
338 mydout(cct,10) << "C_GatherBase " << this << ".new" << dendl;
340 ~C_GatherBase() override {
341 mydout(cct,10) << "C_GatherBase " << this << ".delete" << dendl;
343 void set_finisher(ContextType *onfinish_) {
344 Mutex::Locker l(lock);
346 onfinish = onfinish_;
350 assert(activated == false);
352 if (sub_existing_count != 0) {
359 ContextType *new_sub() {
360 Mutex::Locker l(lock);
361 assert(activated == false);
363 sub_existing_count++;
364 ContextType *s = new C_GatherSub(this);
368 mydout(cct,10) << "C_GatherBase " << this << ".new_sub is " << sub_created_count << " " << s << dendl;
371 void finish(int r) override {
372 ceph_abort(); // nobody should ever call me.
375 inline int get_sub_existing_count() const {
376 Mutex::Locker l(lock);
377 return sub_existing_count;
380 inline int get_sub_created_count() const {
381 Mutex::Locker l(lock);
382 return sub_created_count;
387 * The C_GatherBuilder remembers each C_Context created by
388 * C_GatherBuilder.new_sub() in a C_Gather. When a C_Context created
389 * by new_sub() is complete(), C_Gather forgets about it. When
390 * C_GatherBuilder notices that there are no C_Context left in
391 * C_Gather, it calls complete() on the C_Context provided as the
392 * second argument of the constructor (finisher).
394 * How to use C_GatherBuilder:
396 * 1. Create a C_GatherBuilder on the stack
397 * 2. Call gather_bld.new_sub() as many times as you want to create new subs
398 * It is safe to call this 0 times, or 100, or anything in between.
399 * 3. If you didn't supply a finisher in the C_GatherBuilder constructor,
400 * set one with gather_bld.set_finisher(my_finisher)
401 * 4. Call gather_bld.activate()
405 * C_SaferCond all_done;
406 * C_GatherBuilder gb(g_ceph_context, all_done);
407 * j.submit_entry(1, first, 0, gb.new_sub()); // add a C_Context to C_Gather
408 * j.submit_entry(2, first, 0, gb.new_sub()); // add a C_Context to C_Gather
409 * gb.activate(); // consume C_Context as soon as they complete()
410 * all_done.wait(); // all_done is complete() after all new_sub() are complete()
412 * The finisher may be called at any point after step 4, including immediately
413 * from the activate() function.
414 * The finisher will never be called before activate().
416 * Note: Currently, subs must be manually freed by the caller (for some reason.)
418 template <class ContextType, class GatherType>
419 class C_GatherBuilderBase
422 C_GatherBuilderBase(CephContext *cct_)
423 : cct(cct_), c_gather(NULL), finisher(NULL), activated(false)
426 C_GatherBuilderBase(CephContext *cct_, ContextType *finisher_)
427 : cct(cct_), c_gather(NULL), finisher(finisher_), activated(false)
430 ~C_GatherBuilderBase() {
432 assert(activated); // Don't forget to activate your C_Gather!
438 ContextType *new_sub() {
440 c_gather = new GatherType(cct, finisher);
442 return c_gather->new_sub();
447 assert(finisher != NULL);
449 c_gather->activate();
451 void set_finisher(ContextType *finisher_) {
452 finisher = finisher_;
454 c_gather->set_finisher(finisher);
456 GatherType *get() const {
459 bool has_subs() const {
460 return (c_gather != NULL);
462 int num_subs_created() {
464 if (c_gather == NULL)
466 return c_gather->get_sub_created_count();
468 int num_subs_remaining() {
470 if (c_gather == NULL)
472 return c_gather->get_sub_existing_count();
477 GatherType *c_gather;
478 ContextType *finisher;
482 typedef C_GatherBase<Context, Context> C_Gather;
483 typedef C_GatherBuilderBase<Context, C_Gather > C_GatherBuilder;
485 class FunctionContext : public Context {
487 FunctionContext(boost::function<void(int)> &&callback)
488 : m_callback(std::move(callback))
492 void finish(int r) override {
496 boost::function<void(int)> m_callback;