Mbed Callback模板类分析

 

 

模板首个简单构造函数:

template <typename R>
class Callback<R()> {
public:
    /** Create a Callback with a static function
     *  @param func     Static function to attach
     */
    Callback(R (*func)() = 0) {
        if (!func) {
            memset(this, 0, sizeof(Callback));
        } else {
            generate(func);
        }
    }
}


 

  在对Callback实例化时,可以不带<>模板参数,编译器可以根据Callback构造函数的入参自动补充, 比如
          callback(this, &cCallBackTest::CallBackFunc);
  或者如果 cCallBackDerived继承 cCallBackTest,声明一个对象如:cCallBackDerived ObjCallBackDerived;
       则 callback(&ObjCallBackDerived, &cCallBackTest::CallBackFunc);

    注意这里模板参数U和T是继承关系,即U继承了T,结合method_context可以清楚看到

   
    template<typename T, typename U>
    Callback(U *obj, R (T::*method)()) {
        generate(method_context<T, R (T::*)()>(obj, method));
    }

  

 
  method_context用到了()操作符重载, 使用()时会调用obj的method

 //从上面generate的调用看到,这里模板参数O为上面的T,而入参为U的obj,即T为U的基类
     template <typename O, typename M>
    struct method_context {
        M method;
        O *obj;

        method_context(O *obj, M method)
            : method(method), obj(obj) {}

        R operator()() const {
            return (obj->*method)();
        }
    };

 从上面调用可知道,generate的模板参数 F 为struct method_context, f为实例入参。 function_call为静态成员函数,具有固定函数指针入口,初始化到ops。 对本callback对象占用的内存进行清零,memset(this, 0, sizeof(Callback)); 然后该内存初始化为F(f),即已经实例化的struct method_context(上面的method_context<T, R (T::*)()>(obj, method))复制到本对象的内存中。
    此时的callback内存大小应该包括method_context + _ops。

template <typename F>
    void generate(const F &f) {
        static const ops ops = {
            &Callback::function_call<F>,
            &Callback::function_move<F>,
            &Callback::function_dtor<F>,
        };

        MBED_STATIC_ASSERT(sizeof(Callback) - sizeof(_ops) >= sizeof(F),
                "Type F must not exceed the size of the Callback class");
        memset(this, 0, sizeof(Callback));
        new (this) F(f);
        _ops = &ops;
    }

  方法call将会调用_ops->call(this); 亦即 function_call(this)

    R call() const {
        MBED_ASSERT(_ops);
        return _ops->call(this);
    }

    /** Call the attached function
     */
    R operator()() const {
        return call();
    }

 
  function_call(this),  如function_call代码所示,入参this被强制转换为F(即struct method_context)。 return (*(F*)p)(); 展开为:  (*(struct method_context *) this) 为上文中的struct method_context 实例,  而this也即是上文中method_context<T, R (T::*)()>(obj, method)复制来的对象指针,此时使用struct method_context 的()操作符重载函数, 
R operator()() const {
            return (obj->*method)();

} ,即实现了最终调用struct method_context 里的obj和method功能。

 template <typename F>
    static R function_call(const void *p) {
        return (*(F*)p)();
    }

    template <typename F>
    static void function_move(void *d, const void *p) {
        new (d) F(*(F*)p);
    }

    template <typename F>
    static void function_dtor(void *p) {
        ((F*)p)->~F();
    }

 thunk 为静态成员函数,对callback  类型的func进行强制转换然后调用call,过程同上。

 static R thunk(void *func) {
        return static_cast<Callback*>(func)->call();
    }

demo如下:


class cCallBackTest
{
	public:
	cCallBackTest(){
            m_Callback = Callback(this, &cCallBackTest::CallBackFunc);
        }
	~cCallBackTest(){}
	
	void CallBackFunc()
	{
		while (1)
		{
			printf("CallBackFunc~~~~~~~~~~\n\n");
		}
	}
        void call()
        {
          //使用了callback的()操作符重载函数
            m_Callback();
        }
	private:
	mbed::Callback<void()> m_Callback;

};

另外,函数struct function_context的实现流程也和struct method_context 类似。  Callback 模板类使用起来比较方便,但是里面的具体实现流程比较烧脑。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值