ZeroC ICE的远程调用框架 Callback(一)-AMI异步方法调用框架
Ice框架提供了不少回调设施,其中一些是使用Ice远程调用进行ami模式或amd模式的支撑。本篇来看一下用于代理端的回调设施。
Ice代码中有好几个Callback相关命名的基类,并且slice还会为你描述的接口,每个接口方法生成好几个回调类,让人眼花缭乱。其实认真整理归纳一下,就会发现,为我们提供的代理调用回调接口只有两个,一个是较为底层一点的,你需要解释Future,另一个是较为高级一点的,框架为你解释好Future,并以输出参数回调。而回调的挂接点是在网络层的io读写完成事件。较为底层一点的回调接口有两个函数,分别是sent(const AsyncResultPtr&)和completed(const AsyncResultPtr&),这两个回调函数分别挂接在网络层的io写完成事件以及io读完成事件上。较为高级一点的回调接口,有sent,response和exception三个函数入口,底层的回调处理completed将读出的响应结果分类为exception或正常输出参数,分别递交给exception或response回调入口。它们的关系如下图:
OutgoingAsync是所有具体Future类的直接基类(,继承树最后一层基类),本身就是一个Callback类,挂接回调在网络层。当ConnectionI对网络io事件进行dispatch调度时,就会满足条件下相应回调OutgoingAsync。OutgoingAsync自身有一套回调框架,可以使回调同步在io执行dispatch调度的线程上,或异步执行在其它线程上。不论那种情况,Outgoing最后将回调委托在基类CallbackCompletion。CallbackCompletion再委托给上层提供的回调。通过回调离开Future层进入的是由Slice为我们生成的框架代码,这时使用的回调接口,才是我们上面说的较为底层的回调接口sent(const AsyncResultPtr&)和completed(const AsyncResultPtr&)。Future以参数方式委托给上层代码进行事件回调处理。这个委托我们是可以在创建一个Future进行指定的。我们有两种选择,一是提供较为底层的回调方式的委托,二是提供较为高级方式的版本。Slice为我们生成的5个begin_Method函数中,有两个是指定底层次版本回调,另两个是指定高级版本回调的,最一个是不使用回调的。我们看一下slice生成的begin_Method函数模板:
::Ice::AsyncResultPtr begin_Method(const ::Ice::Context& context = ::Ice::noExplicitContext);
::Ice::AsyncResultPtr begin_Method(const ::Ice::CallbackPtr& del, const ::Ice::LocalObjectPtr& cookie = );
::Ice::AsyncResultPtr begin_Method(const ::Ice::Context& context, const ::Ice::CallbackPtr& del, const ::Ice::LocalObjectPtr& cookie = );
::Ice::AsyncResultPtr begin_Method(const ::Test::Callback_MyClass_opOnewayPtr& del, const ::Ice::LocalObjectPtr& cookie = );
::Ice::AsyncResultPtr begin_Method(const ::Ice::Context& context, const ::Test::Callback_MyClass_opOnewayPtr& del, const ::Ice::LocalObjectPtr& cookie = );
::Ice::AsyncResultPtr _iceI_begin_Method(const ::Ice::Context&, const ::IceInternal::CallbackBasePtr& del, const ::Ice::LocalObjectPtr& cookie = , bool sync = false);
在每个函数的都有一个参数,类型为Callback相关,命名为del,其实就是delegate,我们提供的Callback是回调处理中的委托目标,而这个委托又会委托给我们自定义的Callback中去。
我们要如何使用代理端的远程调用的回调呢,请看下图:
红色的类,就是我们要提供给Ice的回调类,这里要注意的是,我们的自定义的回调类并不继承于任何一个Callback基类。因为我们自定义的回调类是蓝色的框架提供的回调类委托的目标,而蓝色的由框架提供的回调类,却是OutgoingAsync(基类为AsyncResult的Future)的回调委托目标。其实我们提供的回调类,到最后回调到达已经是第二层委托了。我们提供的回调类唯一要继承的就是Shared。蓝色的类就像一个Binder绑定我们的提供的回调类以及我们选择为这个回调的函数。蓝色类继承树上的子类实例是我们调用Slice为我们生成begin_Method需要传入的回调委托,它绑定我们自定义的回调类和我们选用作本次远程调用回调的函数。蓝色类的继承自CallbackBase,CallbackBase也定义了回调虚接口sent和completed,为什么我们自定义的回调不是直接继承这个有回调虚接口呢?原因是那样的话,我们的自定义的回调类就必然会很多,不利于我们维护。尽管Slice为我们生成了许多我们压根都不会使用到的类,但是我们是不用去维护这些类的。使用绑定(binder,绑定target和function selector)以及委托的方式,我们就可以方便开发出处理多种回调函数的回调类。我们的回调委托并不是固定绑定到某一个对象调用的上,而是只对应某一次对象调用,并且我们可以为每次对象调用选用自定义回调类的不同成员函数进行绑定回调处理。
我们的回调起源于网络服务层的io读写完成事件,经过AsyncResult(Future层)的回调框架最后委托到我们回调代码。那么AsyncResult(Future层)的回调框架又为我们做了些什么工作呢?首先总览AsyncResult的类图:
所有具体的Future类都多继承自两个基类CallbackCompletion和OutgoingAsync,可参考最下方同一水平层次的三个类。最顶层的基类有两员分别是,OutgoingAsyncCompletionCallback和AsyncResult,AsyncResult是一个提供给上层访问的接口,基本与回调框架无关。我们将无关的繁枝冗节去除,只留下回调框架相关的方法接口以及依赖关系,如下图:
白色的类是我们上面Future类图中的成员,并且借用OC对类(@interface)的分类声明,我们将一个类的方法按功能聚集成一个分类。
分类中的方法名与我们本篇开始提到的回调接口sent,response和exception相关。相关的方法有
sent,sentImpl,invokeSent,invokeSentAsync,handleSent, handleInvokeSent ;
response,responseImpl,invokeResponse,invokeResponseAsync,handleResponse,handleInvokeResponse ;
exception,exceptionImpl,invokeException,invokeExceptionAsync, handleException,handleInvokeException ;
这些函数的命名相当迷惑人,如果你不知道它们的真正作用又没有文档的话。sent,response和exception分别必须调用它们对应的(sent|response|exception)Impl版本,它们的Impl版本实质在调用它们各自对应的handle(Sent|Response|Exception)方法。但是这三组方法,根本不是回调处理,而只是三组查询方法,它们都返回一个bool值,表示是否支持回调。剩下的方法则都带invoke词根,但是它与AsyncResult的invoke并没有关系,而是真正要调用事件回调。invokeSent,invokeResponse和invokeException分别依赖调用handleInvokeSent,handleInvokeResponse和handleInvokeException,它们就是最后委托上层回调的地方。至于invokeSentAsync,invokeResponseAsync和invokeExceptionAsync则是将invokeSent,invokeResponse和invokeException方法委托给嵌套类,dispatch(和OC的GCD中语义一样)到线程池异步执行。invokeSent,invokeResponse和invokeException方法集是枢纽点,上面图用红字显示。当执行一次带回调需要的同步远程调用,就有一条最小的依赖路径,即上图中红色类和红字类,ConnectionI和OutgoingAsyncBase。网络服务层的Connection在调用io事件时,回调Future(OutgoingAsyncBase,which is a AsyncResult)的回调处理,再通过OutgoingAsyncCompletionCallback接口服务委托回调到上层。
ZeroC ICE的远程调用框架 Callback(一)-AMI异步方法调用框架的更多相关文章
- ZeroC ICE的远程调用框架 Slice如何帮助我们进行Ice异步编程(AMI,AMD)
Slice最大的用处就是为我们使用Ice进行编程,代劳绝大部分的重复性代码,并提供一些帮助性的框架代码,如用于AMI和AMD方式进行异步编程的回调框架. 当Slice不为我们生成代码时,我们仍然可以按 ...
- ZeroC ICE的远程调用框架 AMD
继上一篇<ZeroC ICE的远程调用框架>,本篇再来说其中的AMD.(本篇需要重写) 当在ice文件中声明某个接口方法Method为["amd"]后,接口方法在stu ...
- ZeroC ICE的远程调用框架
想搞清楚slice为我们生成了什么样的框架代码,就先搞明白Ice的远程调用框架暗中为我们做了些什么? Ice将Ice Object的方法调用分为三个阶段(或步骤),分别是begin,process和e ...
- ZeroC ICE的远程调用框架 AMI与AMD -Why?
在Ice有两种异步使用的方式,AMI和AMD.AMI是异步方法调用,AMD是异步方法调度(分派).前者用在代理端,后者用在饲服实现端. AMI其实就是在代理端,使用Future机制进行异步调用,而不阻 ...
- ZeroC ICE的远程调用框架 class与interface
我们在ice文件中定义的class或interface,slice都会为我们生成stub存根类和skeleton骨架类.在这里要注意slice并没有分别生成两份单独用在客户端或服务端的接口给开发分发. ...
- ZeroC ICE的远程调用框架 ServantLocator与Locator
ServantLocator定位的目标是Servant,而Locator定位的目标是“Ice Object”,即一个可定位的“Ice Object”代理.Servant是::Ice::Object的继 ...
- ZeroC ICE的远程调用框架 ThreadPool
ThreadPool提供Reactor/Proactor服务,并且强偶合了Reactor(反应器)/Proactor(前摄器).不同于Reactor/Proactor使用线程池 进行事件处理的设计.如 ...
- ZeroC ICE的远程调用框架 代理引用地址
在官方文档中称为Binding,协议-地址对的绑定.在Proxy模式中,一般地有三个参与者,Proxy,Subject以及RealSubject.Subject定义了Proxy(代理)和RealSub ...
- ZeroC ICE的远程调用框架 ASM与defaultServant,ServantLocator
ASM与defaultServant,ServantLocator都是与调用调度(Dispatch)相关的. ASM是ServantManager中的一张二维表_servantMapMap,默认Ser ...
随机推荐
- 05jmeter正则表达式
1.必须掌握的正则字符 "^" :^会匹配行或者字符串的起始位置,有时还会匹配整个文档的起始位置."$" :$会匹配行或字符串的结尾."\w" ...
- 别再让你的微服务裸奔了,基于 Spring Session & Spring Security 微服务权限控制
微服务架构 网关:路由用户请求到指定服务,转发前端 Cookie 中包含的 Session 信息: 用户服务:用户登录认证(Authentication),用户授权(Authority),用户管理(R ...
- stream流篇
流是C#中比较重要的一个概念,很多关键技术都需要用到流.何为流呢?可以理解流为江河中水的流动,不过C#中则为信息流,我们可以把信息写入流,也可以读出.比如以文件读写操作为例,首先以某种方式(如只读)打 ...
- js实现一个简单的链式操作
如何实现一个链式操作 function person() {} person.prototype = { setname: function(name) { this.name = name retu ...
- 【阿里云IoT+YF3300】8.物联网设备用户脚本开发
除了我们必须熟悉的网页脚本,比如JavaScript.其实在工业自动化中,组态软件是必备脚本的,只是有的脚本语言风格类似C或类似Basic而已.比如昆仑通泰的组态屏中的组态软件.通过安装组态软件可以简 ...
- 构造函数语义学——Copy Constructor 的构造操作
前言 在三种情况下,会以一个 object 的内容作为另一个 class object 的初值: object明确初始化 class X{...}; X x; X xx = x; object 被当作 ...
- 《JavaScript设计模式与开发实践》-- 发布-订阅模式
详情个人博客:https://shengchangwei.github.io/js-shejimoshi-fabudingyue/ 发布-订阅模式 1.定义 发布-订阅模式:发布-订阅模式又叫观察者模 ...
- 前端技术之:JSON.stringfy详细说明
JSON.stringify() 语法JSON.stringify(value[, replacer[, space]]) value 被序列化为字符串的对象 replacer 根据类型不同,其行为也 ...
- Java自动化测试框架-09 - TestNG之依赖注入篇 (详细教程)
1.-依赖注入 TestNG支持两种不同类型的依赖项注入:本机(由TestNG本身执行)和外部(由诸如Guice的依赖项注入框架执行). 1.1-本机依赖项注入 TestNG允许您在方法中声明其他参数 ...
- C函数库errno.h概况
在linux中使用c语言编程时,errno是个很有用的动动.他可以把最后一次调用c的方法的错误代码保留.但是如果最后一次成功的调用c的方法,errno不会改变.因此,只有在c语言函数返回值异常时,再检 ...