callback的实现
Callback.h
继承层次
- CallBack实现类
| 基类 | 第一层子类 | 第二层子类 | 第三层子类 |
|---|---|---|---|
| SimpleRefCount | CallbackImplBase | CallbackImpl | FunctorCallbackImpl |
| MemPtrCallbackImpl | |||
| BoundFunctorCallbackImpl | |||
| TwoBoundFunctorCallbackImpl | |||
| ThreeBoundFunctorCallbackImpl |
- Callback封装类
- CallbackBase
封装Ptr<CallbackImplBase> m_impl - Callback
CallbackBase的子类。根据传入的不同实参,构造不同类型的callback。

- CallbackBase
模板整体说明
- CallbackImpl:有不同的特化子模板
- 根据重载()操作符时需要的形参类型个数将Ti~Tk特化为empty类,调用是根据传入的模板形参个数匹配相应的模板
- R:回调返回值
- FunctorCallbackImpl:CallbackImpl没有默认值,
- T:泛函的类型(配套的,包括泛函返回类型,泛函形参类型)
- MemPtrCallbackImpl:CallbackImpl
- OBJ_PTR:object的类型
- MEM_PTR:object成员泛函的类型(包括泛函返回类型,泛函形参类型)
BoundFunctorCallbackImpl: CallbackImpl
- T:泛函类型
- R:回调返回值
- Tx:绑定的类型
- 回调时,总有一个类型为Tx的值作为回调的形参
CallBack:T1~T9:默认值为empty类
MakeCallback<>模板函数:根据传入不同的形参,实例化不同版本
- 形参:泛函指针
- 根据传入的普通泛函涉及的类型个数(返回值类型,形参类型个数)匹配不同回调形参个数的模板
- 形参:类成员泛函指针,类对象指针
- 根据传入的类成员泛函的涉及的类型(返回值类型,形参类型个数)匹配不同回调形参的模板
- 形参:泛函指针,绑定的值(1~3个)
- 形参:泛函指针
CallbackTraits
- 模板1
c++
template <typename T>
struct CallbackTraits;
- 将指针转化为引用,用于MemPtrCallBackImpl
c++
template <typename T>
struct CallbackTraits<T *>
{
static T & GetReference (T * const p){
return *p; }
};
CallbackImplBase
class CallbackImplBase : public SimpleRefCount<CallbackImplBase>
{
public:
virtual ~CallbackImplBase () {}
// Equality test
virtual bool IsEqual (Ptr<const CallbackImplBase> other) const = 0;
};
CallbackImpl
通过重载函数操作符"()"实现
- 模板声明,该模板限定了最多能传入9个形参给callback
template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
class CallbackImpl;
- 无参数特化模板
template <typename R>
class CallbackImpl<R,empty,empty,empty,empty,empty,empty,empty,empty,empty> : public CallbackImplBase {
public:
virtual ~CallbackImpl () {}
virtual R operator() (void) = 0; //!< Abstract operator
};
- 将模板形参T2~T9特例话为空
这是将基类模板中模板形参T2到T9特化为empty类型的一个例子(部分特化)
template <typename R, typename T1>
class CallbackImpl<R,T1,empty,empty,empty,empty,empty,empty,empty,empty> : public CallbackImplBase {
public:
virtual ~CallbackImpl () {}
virtual R operator() (T1) = 0; //!< Abstract operator
};
- 其他类似
- CallbackImpl的定义
template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
class CallbackImpl : public CallbackImplBase {
public:
virtual ~CallbackImpl () {}
virtual R operator() (T1, T2, T3, T4, T5, T6, T7, T8, T9) = 0; //!< Abstract operator
};
FunctorCallbackImpl
CallbackImpl with functors
R:回调返回类型;
T :m_functor类型,T是一个函数指针的类型(包括函数形参列表,以及函数返回类型。而处于兼容性考虑,T应该是这样的类型 R(*)(T1,T2.......)
template <typename T, typename R, typename T1, typename T2, typename T3, typename T4,typename T5, typename T6, typename T7, typename T8, typename T9>
class FunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,T8,T9> {
public:
FunctorCallbackImpl (T const &functor):m_functor(functor){}
virtual ~FunctorCallbackImpl () {}
//无输入参数的回调,
R operator() (void) {return m_functor (); }
//带一个形参的回调
R operator() (T1 a1) {return m_functor (a1); }
// 其他形参个数的回调类似
.......
virtual bool IsEqual (Ptr<const CallbackImplBase> other) const{
FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5,T6,T7,T8,T9>const *otherDerived =dynamic_cast<FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5,T6,T7,T8,T9> const *> (PeekPointer (other));//把其他类型的CallbackImpl转换成FunctorCallbackImpl类
if (otherDerived == 0){return false;}
else if (otherDerived->m_functor != m_functor){
return false;}
return true;
}
private:
T m_functor; //!< the functor
};
MemPtrCallbackImpl
CallbackImpl for pointer to member functions
模板形参MEM_PTR:类成员泛函的类型(涉及泛函返回类型,形参类型表等)
template <typename OBJ_PTR, typename MEM_PTR, typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
class MemPtrCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,T8,T9> {
public:
MemPtrCallbackImpl (OBJ_PTR const&objPtr, MEM_PTR memPtr)
: m_objPtr (objPtr), m_memPtr (memPtr) {}
virtual ~MemPtrCallbackImpl () {}
//无形参成员函数回调实现
R operator() (void) {
return ((CallbackTraits<OBJ_PTR>::GetReference (m_objPtr)).*m_memPtr)();//将m_objPtr转换成引用并调用其成员函数(*m_memPtr)
//其他参数个数的成员函数的回调实现类似
}
.......
virtual bool IsEqual (Ptr<const CallbackImplBase> other) const {
MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5,T6,T7,T8,T9> const *otherDerived=dynamic_cast<MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5,T6,T7,T8,T9> const *> (PeekPointer (other));
if (otherDerived == 0){ return false; }
else if (otherDerived->m_objPtr != m_objPtr||therDerived->m_memPtr != m_memPtr){return false;}
return true;
}
private:
OBJ_PTR const m_objPtr; //!< the object pointer
MEM_PTR m_memPtr; //!< the member function pointer
};
BoundFunctorCallbackImpl
CallbackImpl for functors with first argument bound at construction
template <typename T, typename R, typename TX, typename T1, typename T2, typename T3, typename T4,typename T5, typename T6, typename T7, typename T8>
class BoundFunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,T8,empty> {
public:
template <typename FUNCTOR, typename ARG>
BoundFunctorCallbackImpl (FUNCTOR functor, ARG a)
: m_functor (functor), m_a (a) {}
virtual ~BoundFunctorCallbackImpl () {}
//没有可变类型形参的函数调用
R operator() (void) { return m_functor (m_a); }
//有一个Arg的函数回调
R operator() (T1 a1) { return m_functor (m_a,a1); }
//其他Arg个数的模板类似
virtual bool IsEqual (Ptr<const CallbackImplBase> other) const{
//实现和上面类似,先转换,然后比较
}
private:
T m_functor; //!< The functor
typename TypeTraits<TX>::ReferencedType m_a; //!< the bound argument
};
TwoBoundFunctorCallbackImpl
CallbackImpl for functors with first two arguments bound at construction
template <typename T, typename R, typename TX1, typename TX2, typename T1, typename T2, typename T3, typename T4,typename T5, typename T6, typename T7>
class TwoBoundFunctorCallbackImpl : public CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,empty,empty> {
....
private:
T m_functor; //!< The functor
typename TypeTraits<TX1>::ReferencedType m_a1; //!< first bound argument
typename TypeTraits<TX2>::ReferencedType m_a2; //!< second bound argument
};
}
ThreeBoundFunctorCallbackImpl
和上述类似
CallbackBase
class CallbackBase {
public:
CallbackBase () : m_impl () {}
Ptr<CallbackImplBase> GetImpl (void) const { return m_impl; }
protected:
CallbackBase (Ptr<CallbackImplBase> impl) : m_impl (impl) {}
Ptr<CallbackImplBase> m_impl; //!< the pimpl
static std::string Demangle (const std::string& mangled);
//符号重组?这个干什么的呢?
};
CallBack类
- 模板的示例化具有POD语义:需要的内存是自动管理的,并且允许用户传递一个CallBack实例
- 模板使用pimpl idiom,传递CallBack类的值并将实现传递给其pimpl指针
- CallbackImpl和 FunctorCallbackImpl的子类可用于任何functor-type,而 MemPtrCallbackImpl 可用于某一个类的成员函数指针
- 通过reference list implementation实现CallBack类的值语义
####Callback的构造函数 - 空构造函数
Callback () {} - 根据 Ptr构建Callback
c++
Callback (Ptr<CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,T8,T9> > const &impl): CallbackBase (impl){}
- 内置类型为FunctorCallbackImpl
创建一个FunctorCallbackImpl的实例(第一参数特化为iFUNCTOR类型,其他分别是R,T1等)。创建Create模板函数的此FunctorCallbackImpl的实例,给函数传入实参functor,创建对应的Ptr的关于FunctorCallbackImpl的实例,将此Ptr对象作为CallBackBase类的构造函数实参
template <typename FUNCTOR>
Callback (FUNCTOR const &functor, bool, bool)
: CallbackBase(Create<FunctorCallbackImpl<FUNCTOR,R,T1,T2,T3,T4,T5,T6,T7,T8,T9> > (functor)){}
- 内置类型为MemPtrCallbackImpl
实例化MemPtrCallbackImpl,创建一个此类型的ptr,传给Create函数的实参为objPtr和memPtr
template <typename OBJ_PTR, typename MEM_PTR>
Callback (OBJ_PTR const &objPtr, MEM_PTR memPtr):CallbackBase (Create<MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5,T6,T7,T8,T9> > (objPtr, memPtr)){}
Callback的绑定
- Bind
- 构造一个绑定第一个Arg的回调
- 实例化一个BoundFunctorCallbackImpl,实例化传入的模板实参解释
Callback<R,T1,T2,T3,T4,T5,T6,T7,T8,T9>:BoundFunctorCallbackImpl内置泛函类型- R:回调的返回类型
- T1:绑定的类型
- T2~T9:其他可控的函调形参类型
- 创建上述BoundFunctorCallbackImpl实例类的一个对象
- 传给类的构造函数的实参:(*this):BoundFunctorCallbackImpl的内部泛函
- a :绑定的值
- 创建Ptr>对象impl
- 传给Ptr构造函数的实参:上面创建的BoundFunctorCallbackImpl实例类临时对象和false
- 以impl为实参构建Callback对象
template <typename T>
Callback<R,T2,T3,T4,T5,T6,T7,T8,T9> Bind (T a) {
Ptr<CallbackImpl<R,T2,T3,T4,T5,T6,T7,T8,T9,empty> > impl =
Ptr<CallbackImpl<R,T2,T3,T4,T5,T6,T7,T8,T9,empty> > (
new BoundFunctorCallbackImpl<
Callback<R,T1,T2,T3,T4,T5,T6,T7,T8,T9>,
R,T1,T2,T3,T4,T5,T6,T7,T8,T9> (*this, a), false);
return Callback<R,T2,T3,T4,T5,T6,T7,T8,T9> (impl);
}
- 绑定前两个
实现与Bind类似
template <typename TX1, typename TX2>
Callback<R,T3,T4,T5,T6,T7,T8,T9> TwoBind (TX1 a1, TX2 a2){..}
绑定前三个
实现与上面类似
template <typename TX1, typename TX2, typename TX3>
Callback<R,T4,T5,T6,T7,T8,T9> ThreeBind (TX1 a1, TX2 a2, TX3 a3){...}
Callback的其他成员函数函数
template<typename R,typename T1 = empty, typename T2 = empty,typename T3 = empty, typename T4 = empty,typename T5 = empty, typename T6 = empty,typename T7 = empty, typename T8 = empty,typename T9 = empty>
class Callback : public CallbackBase {
public:
bool IsNull (void) const {
return (DoPeekImpl () == 0) ? true : false;
}
void Nullify (void) {
m_impl = 0;
}
//无输入参数的回调
R operator() (void) const {
return (*(DoPeekImpl ()))();
}
//输入一个参数的回调
R operator() (T1 a1) const {
return (*(DoPeekImpl ()))(a1);
}
// 其他输入参数个数的回调与上述类似
bool IsEqual (const CallbackBase &other) const {
return m_impl->IsEqual (other.GetImpl ());
}
//如果other能转换成我这种类型,返回true
bool CheckType (const CallbackBase & other) const {
return DoCheckType (other.GetImpl ());
}
void Assign (const CallbackBase &other) {
DoAssign (other.GetImpl ());
}
private:
CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,T8,T9> *DoPeekImpl (void) const {
return static_cast<CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,T8,T9> *> (PeekPointer (m_impl));
}
//如果other能转换成我这种类型,返回true
bool DoCheckType (Ptr<const CallbackImplBase> other) const {
if (other != 0 && dynamic_cast<const CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,T8,T9> *> (PeekPointer (other)) != 0)
{ return true; //不为空且能转换 }
else if (other == 0){ return true; //传入的Ptr为空 }
else{ return false; }
}
void DoAssign (Ptr<const CallbackImplBase> other) {
if (!DoCheckType (other))
{
Ptr<CallbackImpl<R,T1,T2,T3,T4,T5,T6,T7,T8,T9> > expected;
NS_FATAL_ERROR (....);
}
m_impl = const_cast<CallbackImplBase *> (PeekPointer (other));
}
}
MakeCallback模板函数
针对不同形参个数的函数指针的 MakeCallback函数模板
template <typename R>
Callback<R> MakeCallback (R (*fnPtr)()) {
return Callback<R> (fnPtr, true, true);
}
template <typename R, typename T1>
Callback<R,T1> MakeCallback (R (*fnPtr)(T1)) {
return Callback<R,T1> (fnPtr, true, true);
}
//其他类型函数指针的MakeCallback类似
针对不同形参个数的类成员函数指针的 MakeCallback函数模板
template <typename T, typename OBJ, typename R>
Callback<R> MakeCallback (R (T::*memPtr)(void), OBJ objPtr) {
return Callback<R> (objPtr, memPtr);
}//const版本类似
template <typename T, typename OBJ, typename R, typename T1>
Callback<R,T1> MakeCallback (R (T::*memPtr)(T1), OBJ objPtr) {
return Callback<R,T1> (objPtr, memPtr);
}
//其他类似
!= 符号的重载
MakeNullCallback的定义
MakeBoundCallback的定义(包括绑定一个,两个等)
CallBack类的和属性系统相关的东西
class CallbackValue : public AttributeValue
{
public:
CallbackValue ();
CallbackValue (const CallbackBase &base);
virtual ~CallbackValue ();
void Set (CallbackBase base);
template <typename T>
bool GetAccessor (T &value) const;
virtual Ptr<AttributeValue> Copy (void) const;
virtual std::string SerializeToString (Ptr<const AttributeChecker> checker) const;
virtual bool DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker);
private:
CallbackBase m_value; //!< the CallbackBase
};
ATTRIBUTE_ACCESSOR_DEFINE (Callback);
ATTRIBUTE_CHECKER_DEFINE (Callback);
//Assign和CheckType函数是callback的成员函数。因此T应该也是一张callback又是哪里定义的
template <typename T>
bool CallbackValue::GetAccessor (T &value) const
{
if (value.CheckType (m_value))
{
value.Assign (m_value);
return true;
}
return false;
}
Callback.cc
- CallbackValue类成员函数的一些定义
- 定义和Callback相关的checker
ATTRIBUTE_CHECKER_IMPLEMENT (Callback);
callback的实现的更多相关文章
- JAVA回调机制(CallBack)详解
序言 最近学习java,接触到了回调机制(CallBack).初识时感觉比较混乱,而且在网上搜索到的相关的讲解,要么一言带过,要么说的比较单纯的像是给CallBack做了一个定义.当然了,我在理解了回 ...
- 如何利用ansible callback插件对执行结果进行解析
最近在写一个批量巡检工具,利用ansible将脚本推到各个机器上执行,然后将执行的结果以json格式返回来. 如下所示: # ansible node2 -m script -a /root/pyth ...
- 带callback的future实现
jdk暂时不支持,所以只有自己实现带callback的future. 完成后callback的 final TaskPromise promise = new DefaultTaskPromise() ...
- 理解callback function in javascript
以下内容主要摘自[1,2] (1)In javascript, functions are first-class objects, which means functions can be used ...
- CallBack实践。
第一:它的应用场景是什么? if you call me ,i will call back.目前我接触到两种需要回调的需求 1.系统管理平台登录,登录所需要的人员和部门数据都是在另一个基础信息系统中 ...
- 如何把 Callback 接口包装成 Promise 接口
最近一段时间一直在看Node.js,在开发过程中经常要调用一些异步接口,通常在接口的最后一个参数会传入一个回调函数,可以用来处理异常,非异常情况.大致模式如下: var fs = require(“f ...
- callback 转换到 promise
最近项目迭代,从express到koa,面对callback,想偷懒,就想到了Proxy对象 new Proxy(docker,{ get : function (obj,name) { return ...
- callback res.end 记得return(Javascript需要养成的良好习惯)
错误示例: app.get('do',function(req,res,next){ getUserId(function(err,userId){ if(err){ res.end(err);//错 ...
- Node.js的process.nextTick(callback)理解
Node.js是单线程的,基于事件循环,非阻塞 IO的.事件循环中使用一个事件队列,在每个时间点上,系统只会处理一个事件,即使电脑有多个CPU核心,也无法同时并行的处理多个事件.因此,node.js适 ...
- $.grep(array, callback, [invert])过滤,常用
$.grep(array, callback, [invert])过滤,常用 解释: 使用过滤函数过滤数组元素.此函数至少传递两个参数(第三个参数为true或false,对过滤函数返回值取反,个人觉得 ...
随机推荐
- asp.net中Ajax控件的用途(二)
1.个人觉得对于新手最为实用的PopupControlExtender,弹出层载体,在实例中可以弹出登录框,百度的登陆页面基本都用的这种形式,可以把浮动的panel宽高都设置为100%,以屏蔽底层操作 ...
- C# 重载的几种实现
算法重用是非常普遍的需求,在C#中可以使用如下手段实现,非常简单,自己记录一下,方便查询. 以一个小功能为例来说明一下:打印1-5这5个数,和A-E这5个字符. 重载方式 static void Ma ...
- 实现在Android 进程和线程
进程和线程 如果某个应用程序组件是第一次被启动,且这时应用程序也没有其他组件在运行,则Android系统会为应用程序创建一个包含单个线程的linux进程.默认情况下,同一个应用程序的所有组件都运行在同 ...
- 2016 年青岛网络赛---Tea
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5881 Problem Description Tea is good. Tea is life. Te ...
- FreeBSD-安装与配置(10.3@VMware)
(#今天尝试了一天,装上了FreeBSD:记录几个重要的地方 bsdinstall/bsdconfig 善用ports,本地源 善用handbook以及doc pkg install XXX,装上Xo ...
- get传递中文产生乱码的解决方式汇总
1 最基本的乱码问题. 这个乱码问题是最简单的乱码问题.一般新会出现.就是页面编码不一致导致的乱码. <%@ page language="java" pageEncodin ...
- 使用loadrunner进行压力测试之----post请求
1. 发送post请求时使用web_submit_data 如: web_submit_data("create",//事务名 "Action=http://bizhi. ...
- SQL 行列转换简单示例
SQLSERVER 2005 以后提供了新的方式进行行列转换,下面是一个实例供参考: if object_id('tb') is not null drop table tbTest go ),季度 ...
- java多线程-线程创建
Java 线程类也是一个 object 类,它的实例都继承自 java.lang.Thread 或其子类. 可以用如下方式用 java 中创建一个线程,执行该线程可以调用该线程的 start()方法: ...
- com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure 解决办法
09:00:30.307 [http-8080-6] ERROR org.hibernate.transaction.JDBCTransaction -JDBC begin failed com.my ...