ceph源码中的几处语法分析

本文深入分析了Ceph中MDSContext::vec、C_IO_Wrapper及MDSGatherBuilder的代码实现,详细解读了模板别名、回调机制及gather构建器的工作原理。

本文选取了ceph中的几处代码进行分析,旨在读懂代码的基础之上,提炼出关键知识点和思想进行学习。

1. MDSContext::vec

目标代码
class MDSContext : public Context
{
   
   
public:
template<template<typename> class A>
  using vec_alloc = std::vector<MDSContext*, A<MDSContext*>>;
  using vec = vec_alloc<std::allocator>;

};
关键词
  • Template template parameter(模板模板参数)
  • alias templates(模板别名)
语法分析

在分析这段代码之前,先来看两个更简单的例子:

template<class T>
struct Alloc
{
   
   
    // 实现自己的内存分配器
};
template<class T>
using Vec = std::vector<T, Alloc<T>>;

int main()
{
   
   
    Vec<int> as;
    return 0;
}
template<class T>
struct Base
{
   
   
    int val;
};
//没什么实际意义,只是为了说明用法
template<class T>
using A = Base<T>;

int main()
{
   
   
    Base<int> inst1;
    A<int> inst2;
    return 0;
}

以上两个例子,就是C++11新增的特性——模板别名,通过using语句为复杂的模板格式起一个简单的别名,极大的简化后续使用时的书写复杂度。

而这里的MDSContext::vec要比以上两个例子更复杂些,一是有模板嵌套,二是两次别名,但其实原理还是一样的,拆开来看就可以了。具体分析直接见下方代码注释吧:

class MDSContext
{
   
   
public:
template<template<typename> class A> // A是一个模板,就这么简单
  // 用std::alocator来实例化vec_alloc,即vec_alloc<std::allocator>,allocator即替换A来进行实例化
  using vec_alloc = std::vector<MDSContext*, A<MDSContext*>>;
  using vec = vec_alloc<std::allocator>;

// 上面的最后一个using其实就是最后一步的彻底特例化了,如果去除这步,手动传参也是可以的
template<template<typename> class A>
  using vec_alloc = std::vector<MDSContext*, A<MDSContext*>>;
    
// 一句话总结,其实就是定义了std::vector<MDSContext*, std::allocator<MDSContext*>>的别名
};


int main()
{
   
   
    // 等价的定义,第一种写法最简单
    MDSContext::vec a;
    MDSContext::vec_alloc<std::allocator> b;
    std::vector<MDSContext*, std::allocator<MDSContext*>> c;
    return 0;
}

用法就是如上面所示,借此部分代码学习了模板别名的知识点,但是对于这部分的代码,以我目前的认知来看是没看出有什么好处的,因为这段代码绕了一圈,其实vec就是vector<MDSContext*>,第一个using允许用户自定义allocator,但是第二个using又显示使用了std::allocator,这还有什么意义呢?把本来泛型的东西又给特例化了,MDSContext::vec相比vector<MDSContext*>的并没有更简单,而且可读性也差了很多。后面再看有没有新的理解吧。

2. C_IO_Wrapper

目标代码

下面这段代码做了什么?

Context *fin = new C_IO_Wrapper(this, new C_MDS_BootStart(this, MDS_BOOT_INITIAL));

  bool const ready = objecter->wait_for_map(
      mdsmap->get_last_failure_osd_epoch(),
      fin);

其中类的继承体系如下:

graph BT
MDSContext-->Context
tmp[MDSHolder<MDSIOContextBase>]-->MDSContext
MDSIOContext-->tmp
C_IO_Wrapper-->MDSIOContext
MDSInternalContext-->tmp
C_MDS_BootStart-->MDSInternalContext

为了省去再去翻代码,这里直接把相关类定义的源码列出来了。

/*
 * Context - abstract callback class
 */
class Context {
   
   
  Context(const Context& other);
  const Context& operator=(const Context& other);

 protected:
  virtual void finish(int r) = 0;

  // variant of finish that is safe to call "synchronously."  override should
  // return true.
  virtual bool sync_finish(int r) {
   
   
    return false;
  }

 public:
  Context() {
   
   }
  virtual ~Context() {
   
   }       // we want a virtual destructor!!!
  virtual void complete(int r) {
   
   
    finish(r);
    delete this;
  }
  virtual bool sync_complete(int r) {
   
   
    if (sync_finish(r)) {
   
   
      delete this;
      return true;
    }
    return false;
  }
};

/**
 * Completion which has access to a reference to the global MDS instance.
 *
 * This class exists so that Context subclasses can provide the MDS pointer
 * from a pointer they already had, e.g. MDCache or Locker, rather than
 * necessarily having to carry around an extra MDS* pointer. 
 */
class MDSContext : public Context
{
   
   
public:
template<template<typename> class A>
  using vec_alloc = std::vector<MDSContext*, A<MDSContext*>>;
  using vec = vec_alloc<std::allocator>;

template<template<typename> class A>
  using que_alloc = std::deque<MDSContext*, A<MDSContext*>>;
  using que = que_alloc<std::allocator>;

  void complete(int r) override;
  virtual MDSRank *get_mds() = 0;
};

void MDSContext::complete(int r) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值