Ceph 中回调类简介(class Context 简介)

Context 类

在 Ceph 的代码中, 随处可见通过异步回调的模式, 对这些回调的流程有充分的理解, 能够帮助我们更好的理解 Ceph

Ceph 中提到回调, 不得不说的就是 Context 类, 它是回调的顶层抽象类,其实现了回调的基本逻辑. Context 有大量的子类, 这些子类继承 Context 并实现各自的业务.

Context 有两个重要的成员函数, finishcomplete, 子类继承 Context 后只需要实现自己的 finish, 然后就可以通过调用 complete, 实现了对自身 finish 的回调.

Context 本身代码比较简单

class Context {
  Context(const Context& other);
  const Context& operator=(const Context& other);

 protected:
  virtual void finish(int r) = 0; // 派生类实现接口
  virtual bool sync_finish(int r) {
    return false;
  }
 public:
  Context() {}
  virtual ~Context() {}  
    
  virtual void complete(int r) { /// 调用者调用接口,函数执行结束后销毁对象
    finish(r); // int r 一般用来让子类决定是否执行
    delete this;
  }
    
  virtual bool sync_complete(int r) {
    if (sync_finish(r)) {
      delete this;
      return true;
    }
    return false;
  }
};

回调适配器

通过会回调适配器, 可以将一个普通的成员函数封装成一个可回调函数

C_CallbackAdapter 为例, 先来看下代码

template <typename T, void (T::*MF)(int)>
class C_CallbackAdapter : public Context {
  T *obj;
public:
  C_CallbackAdapter(T *obj) : obj(obj) {}
protected:
  void finish(int r) override {
    (obj->*MF)(r);
  }
};

C_CallbackAdapter 继承自 Context 并且实现了 finish 。 其模板参数未类型 TT 中的一个成员指针 MF, 一般回调适配器这里的 T 就是要被回调的 class, 对应的成员指针 MF也就是一个普通成员函数的指针。然后通过传入一个 T 类型的对象 obj, 就可以在 finish 中调用到成员函数 T::MF

一般的回调适配器还会有一个对应的注册函数如 C_CallbackAdapter 的注册函数*create_context_callback(T *obj)

template <typename T, void(T::*MF)(int) = &T::complete>
Context *create_context_callback(T *obj) {
  return new detail::C_CallbackAdapter<T, MF>(obj);
}

Demo

可以写个小 Demo 来方便理解毁掉的流程, 这个 Demo 实现了一个完成的回调的流程
filename context.cpp

#include <iostream>

using namespace std;
// 简化的简陋版 Context
class Context {
public:
    virtual void finish(int r) = 0;
    virtual void complete(int r) {
        finish(r);
        delete this;
    }
};

// 回调适配器
template<typename T, void (T::*MF)(int)>
class C_CallbackAdapter : public Context {
    T *obj;
public:
    explicit C_CallbackAdapter(T *obj) : obj(obj) {};
    void finish(int r) override {
        (obj->*MF)(r);
    }
};

// 回调适配器的注册函数
template<typename T, void(T::*MF)(int)>
Context *create_context_callback(T *obj) {
    return new C_CallbackAdapter<T, MF>(obj);
}

// 被回调的类
class MyContext {
public:
    void be_call(int r) {
        std::cout << "this is be call " << std::endl;
    }
};

int main() {
    auto *test_callback = new MyContext;
    Context *ctx = create_context_callback<MyContext, &MyContext::be_call>(test_callback);
    int r = 0;
    ctx->complete(r); // 有了 Context ctx 指针就可以将其传到各种接受 Context 类型的地方, 然后随时调用其中的 test_callback.complete() 了,这也就是费劲包装 MyContext 类型的意义所在, 然后调用 complete() 就可以执行 MyContext 中的 be_call
    return 0;
}

执行

[root@centos7 context]# g++ context.cpp 
[root@centos7 context]# ls
a.out  main.cpp
[root@centos7 context]# ./a.out 
this is be call 
[root@centos7 context]# 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值