Mbed Callback模板类分析

 

 

模板首个简单构造函数:

template 
class Callback {
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
    Callback(U *obj, R (T::*method)()) {
        generate(method_context(obj, method));
    }

  

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

 //从上面generate的调用看到,这里模板参数O为上面的T,而入参为U的obj,即T为U的基类
     template 
    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(obj, method))复制到本对象的内存中。
    此时的callback内存大小应该包括method_context + _ops。

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

        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(obj, method)复制来的对象指针,此时使用struct method_context 的()操作符重载函数, 
R operator()() const {
            return (obj->*method)();

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

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

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

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

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

 static R thunk(void *func) {
        return static_cast(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 m_Callback;

};

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

 

你可能感兴趣的:(Mbed Callback模板类分析)