公开/公告号CN101770395A
专利类型发明专利
公开/公告日2010-07-07
原文格式PDF
申请/专利权人 上海科泰世纪科技有限公司;
申请/专利号CN200810208053.7
申请日2008-12-29
分类号G06F9/46(20060101);
代理机构
代理人
地址 201203 上海市张江高科技园区碧波路177号华虹科技园C区4层
入库时间 2023-12-18 00:05:42
法律状态公告日
法律状态信息
法律状态
2017-02-22
未缴年费专利权终止 IPC(主分类):G06F9/46 授权公告日:20140402 终止日期:20151229 申请日:20081229
专利权的终止
2014-04-02
授权
授权
2010-09-08
实质审查的生效 IPC(主分类):G06F9/46 申请日:20081229
实质审查的生效
2010-07-07
公开
公开
技术领域
本发明是关于一种计算机构件化软件之间的调用方法,尤其是指构件之间的基于一种线程模型的调用方法及该种线程模型。
背景技术
每个Applet构件可以看作是一个独立的应用,一个自封闭的运行空间,即便是同一个进程内的Applets,它们之间的数据也是相对独立的,各自有专属的线程执行各自的代码,有着清晰的Applet边界。
但是当Applet之间发生调用关系时,比如一个通讯录的Applet可能会调用Email的Applet来完成“点击通讯录中Email地址直接弹出编辑新邮件”的功能,类似的Applet之间调用可能还有很多,对于一个Applet来说,如果它的功能实现可能被多个Applet并发调用,或者说它的代码可能会运行在不同的Applet这中,可能会给Applet实现者造成诸多难以预计的困难和假设。首先要考虑多线程并发调用的互斥关系,对于一个功能简单的Applet来说,它可能只需要一个Applet主线程即可完成所有功能,但却要为了防止被其它Applet调用而考虑多线程问题;再比如,进程内所有线程都属于某个Applet,那么任意Applet的成员方法里调用Api获得当前Applet的句柄都应该是它所属的Applet,但由于Applet可能被其它Applet调用,所以它获得的Applet句柄不确定是哪个Applet,如果它的功能实现方法对此有依赖,处理起来就比较复杂。因此Applet在互相调用存在多线程并发调用的问题。
其实Applet可以看作一个轻量级的进程。而进程之间的调用过程是这样的:跨进程调用时,发起调用的一方的调用线程等待在被调用一方的进程边界,由被调用一方的进程内线程完成调用,并将结果返回给调用一方等待中的线程,完成一次跨进程调用。
发明内容
鉴于以上内容,有必要提供一种Applet线程模型及基于该线程模型的构件调用的方法。
所述Applet线程模型包括:Applet构件和具有Applet属性的构件;属于该Applet构件的消息队列及回调线程。
其中,Applet构件和具有Applet属性的构件都具备夹壁墙和一个Event对象。所述夹壁墙用来拦截和存放调用方构件的调用请求线程。所述Applet构件用于将调用请求打包成一个调用消息包,通过投递回调机制将该调用消息包投递到所述消息队列等待处理;所述回调线程用于当从消息队列接收到该调用消息包时,调用并执行所述目标接口方法,将执行结果返回给等待在所述构件夹墙壁中的调用请求线程,并激发该构件的Event对象;所述Event对象用于被回调线程激发后,通知被拦截在所述构件夹壁墙里进行等待的调用请求线程去获取执行结果以将该执行结果返回给调用方构件。
所述基于该Applet线程模型的构件调用方法包括步骤:目标构件利用编译工具生成打包函数,该打包函数经编译生成DLL可执行文件;创建该目标构件对象,调用方构件向该创建的目标构件对象发出调用请求;拦截该调用请求并将其存放在目标构件的夹壁墙,由打包函数将该调用请求打包成一个调用消息包;目标构件对象利用投递回调事件的机制将上述调用消息包投递到其所属的消息队列中;当消息队列处理到该调用消息包时,回调线程从该消息队列接收该调用消息包;该回调线程调用并执行所述的目标接口方法,将执行结果返回给等待在所述夹壁墙里的调用请求,并触发该目标构件对象的Event对象;该Event对象通知该调用请求去获取返回的执行结果,该调用请求将获取的执行结果返回给调用方构件。
本发明利用构件所特有的夹壁墙技术,将所有针对Applet和具有Applet属性的构件对象的接口方法的调用,都在夹壁墙中拦截,再将调用的参数和被调用的接口方法的信息一起打包,通过投递回调事件的机制向被调用的Applet的消息队列中投递此次调用事件。此时调用线程进入等待状态,当被调用的Applet的消息循环处理到这次调用事件时,由Applet的回调线程执行目标接口方法,执行完成后再将结果返回给等待在夹壁墙的调用线程,再由它返回给调用方的Applet,由此完成一次完整的调用。
利用本发明可以解决Applet彼此调用时多线程问题,加强Applet之间的独立性,使得外界对Applet数据结构的访问和接口方法的调用只能通过Applet自己的线程来完成。
附图说明
图1是本发明较佳实施例的线程模型示意图。
图2是本发明应用Applet线程模型调用构件目标接口方法的流程图。
具体实施方式
如图1所示,是本发明较佳实施例的Applet线程模型1的示意图。需要说明的是该Applet线程模型1适用于所有的Applet构件和所有被Applet属性修饰的普通构件。
从其他Applet构件或者从“外部”调用一个Applet构件的方法,或者调用一个具有Applet属性的构件的方法,都会应用Applet线程模型。在本较佳实施例中,将被调用的Applet构件或具有Applet属性的构件称为目标Applet构件,将调用该目标Applet构件的其他Applet构件或“外部”的构件称为调用方构件。
所述的Applet线程模型1包括Applet构件/具有Applet属性的构件(也即目标构件10)、属于该Applet构件/具有Applet属性的构件的消息队列11和回调线程12。其中每个Applet构件都有属于自己的消息队列11和回调线程12。
其中,每个构件都具备夹壁墙101和一个Event对象102。所述夹壁墙101用来存放所有调用该构件的调用方的请求线程,也即是说所有调用该构件的调用请求线程都会被拦截在该构件的夹壁墙101里。
例如用下面的一段程序代码(aa)实现目标构件TMail的夹壁墙101的功能:
_TMail::GetMailer(IMail**ppMailer)//夹壁墙函数;
{
TMailGetMailerParam param;//创建一个调用消息包的对象;
ECode ec=CEvent::New(¶m._pEvent);//创建一个操作系统
Event对象,当这次调用被回调线程处理完以后通过设置这个事件通
知调用者;
if(FAILED(ec))return ec;
param._ec=NOERROR;
param._pThis=this;//设置调用参数;
param._ppMailer=ppMailer;//设置调用参数;
ec=PostCallbackEvent(MAKE_PARAMETER(&_TMail_GetMailer,
¶m));//将这次“调用消息包”投递到消息队列;
if(FAILED(ec)){//如果投递“调用消息包”失败;
param._pEvent->Release();//释放先前创建的对象;
return ec;//返回错误码;
}
param._pEvent->Wait(INFINITE);//无限期等待这个Event对象被
触发,当回调线程处理完这次调用时会触发这个Event;
param._pEvent->Release();//等待结束,不再需要这个Event对
象,释放它;
if(param._ec==NOERROR){//如果调用成功则获取out参数;
ppMailer=param._ppMailer;//获取out参数;
}
return param._ec;//将调用结果的返回值返回;
}
该程序代码段(aa)可以看作是目标构件TMail的的夹壁墙函数。
所述Event对象102是在该夹壁墙函数中被设置的,以用于当所调用的目标构件的方法被执行完后,通过触发该设置的Event对象通知被拦截在夹壁墙101里进行等待的调用方的调用请求线程。
所述消息队列11是一个属于该目标构件的Applet消息队列,用来存放所有的调用该目标构件的调用消息包。所述的在消息队列中等待的调用消息包所包括的信息如下:调用参数及被调用的目档构件的接口方法。目标构件利用打包函数将调用方的调用请求中的调用参数及被调用的目标构件的接口方法等信息一起打包成一个调用消息包,再通过投递回调事件机制将该调用消息包投递到该消息队列中排队等待处理。如打包函数所用的打包调用参数的数据结构可以用下面的一段程序代码(bb)实现:
TMail::GetMailer(IMail**ppMailer)//GetMailer的声明;
typedef struct_TMail_GetMailer_Param{//这是TMail构件的GetMailer方法的调用消息包的数据结构定义,该结构由编译工具根据GetMailer的参数自动生成;
IMail**_ppMailer;//对应函数声明中的ppMailer;
_TMail*_pThis;//被调用的TMail对象的this指针;
ECode_ec;//当调用结束后,保存GetMailer的返回值;
IEvent*_pEvent;//调用者创建Event对象,被调用的回调线程在调用结束后触发这个Event对象,使调用者知道该次调用已经结束;
}TMailGetMailerParam;
所述回调线程12即是Applet的主线程,与Applet一一对应,而Applet里可以包含很多构件对象。该回调线程12用于当消息队列11的消息循环处理流程处理到该调用消息包时,调用所注册的回调函数,该回调函数是自动生成的代码,由该回调函数再调用所述目标构件的接口方法并执行该接口方法,将执行结果返回给等待在目标构件10的夹墙壁101中的调用方构件的调用请求线程,并激发该目标构件的Event对象,让该Event对象通知等待在夹墙壁101里的调用请求线程去获取返回的执行结果。该调用请求线程将所获取的结果返回给调用方构件。由此完成一次目标构件的接口方法的调用。
例如,当调用的目标构件是TMailer时,可以用下面的一段程序代码(cc)实现所述回调函数的功能:
ECode_TMail_GetMailer(TMailGetMailerParam*pParam)
{//这个函数由编译工具自动生成,当回调线程从消息队列里收到对GetMailer的“调用消息包”时,调用此函数;
pParam->_ec=pParam->_pThis->TMail::GetMailer(&pParam->
_ppMailer);//调用TMail的GetMailer方法,并将返回值保存在
消息包参数ec里;
pParam->_pEvent->SetEvent();//调用结束,触发Event对象;
return NOERROR;
}
其中消息队列11的消息循环处理流程会按顺序处理在消息队列中等待的调用消息包,并通知回调线程接收所述调用消息包,直到消息队列为空。这个过程是一个循环过程。
从其它Applet或者从“外部”调用一个Applet构件的方法,或者调用一个具有Applet属性的构件的方法,都会应用“Applet线程模型”,这次调用会被打包成一个调用消息包,投递到目标Applet的消息队列,再由目标Applet的回调线程完成调用,并保存调用结果,最终调用者获得调用结果返回,完成一次调用。
参阅图2所示,是应用Applet线程模型调用目标构件方法的流程图。
步骤S200,目标构件利用编译工具生成打包函数,如上述程序代码段bb。在此所述目标构件为具有Applet属性的普通构件类对象,所述之目标接口方法为Applet对象所实现的所有接口方法。
步骤S202,该打包函数经编译生成DLL可执行文件。
步骤S204,在本较佳实施例中,该调用方构件需向目标构件TMail调用其GetMailer接口方法,则创建该目标构件对象,如TMail对象,并向该TMail对象发出包含调用参数及被调用的接口方法信息的调用请求。
步骤S206,该调用请求线程被拦截在目标构件的夹壁墙101中,并由上述打包函数将该调用请求线程中的调用参数及被调用的接口方法等信息打包成一个调用消息包。
步骤S208,目标构件对象利用投递回调事件的机制将上述调用消息包投递到其所属的消息队列中。此时该调用请求线程在目标构件对象的夹壁墙101中进行等待。所述调用消息包在该消息队列中排队等待处理。
步骤S210,当消息队列的消息循环处理流程处理到该调用消息包时,回调线程12从该消息队列接收该调用消息包,也即该回调线程接收到了该调用方构件向目标构件对象发出的调用请求事件。
步骤212,该回调线程12调用回调函数以调用并执行所述的目标接口方法,如GetMailer。所述的回调函数如上述之程序代码段cc。该回调线程12将执行目标接口方法的结果返回给等待在目标构件对象的夹壁墙101里的调用请求线程,然后触发该目标构件对象的Event对象102。
步骤S214,该Event对象通知该调用请求线程去获取返回的执行结果,该调用请求线程获取返回的执行结果并将该执行结果返回给调用方构件。
下面通过几段代码片断来说明应用本发明的Applet线程模型的优点。在下面所述的几段代码片断中,目标构件对象是TMail构件和一个具有Applet属性的构件对象CMail,所需调用的接口方法分别的TMail的GetMailer方法和CMail的SendMail方法。
(1)Mail.car//一个邮件发送接收服务的构件定义文件
Interface IMail{//定义构件的接口
SendMail(WString title,WString to,WString context);(//声明所定义的构件的接口方法
}
interface IManager{//定义构件接口
GetMailer([out]IMail**mailer);//声明所定义的构件的接口方法
}
[applet]
class CMail{//定义一个构件类
interface IMail;//声明该构件类实现该(IMail)的接口方法
}
applet TMail{
interface Imanager;
}
上述这段代码是对所调用的目标接口方法的定义、描述及需向目标接口方法传递参数的定义。
(2)Mail.cpp
ECode TMail::Main(...)
{
printf(“TMail::Main():current thread is 0x%x\n”,
CThread::GetCurrent());
return NOERROR;
}
ECode TMail::GetMailer(IMail**ppMailer)
{
ECode ec=CMail::New(ppMailer);
if(FAILED(ec))return ec;
printf(“TMail::GetMailer():current thread is 0x%x\n”,
CThread::GetCurrent());
return NOERROR;
}
ECode CMail::SendMail(WString title,WString to,WString context)
{
......//send mail
printf(“CMail::SendMail():current thread is 0x%x\n”,
CThread::GetCurrent());
return NOERROR;
}
在对附图1的描述时所述的程序代码段(aa),(bb)及(cc)所生成的打包参数的数据结构、回调函数和夹壁墙函数在编译在时候会包含在该TMail.cpp主程序里,所以可以认为它们是生成在主程序里的。
(3)Client.cpp//这是一个调用构件的客户端程序
......
IManager*pIManager;
IMail*pIMail;
TMail::New(&pIManager);//创建一个TMail构件对象,TMail是一个Applet构件
......
printf(“In Caller Applet:current thread is 0x%x\n”,CThread::GetCurrent());//打印当前的线程句柄,每个运行时的线程句柄是唯一的;
pIManager->GetMailer(&pIMail);//调用TMail的GetMailer方法,也就是调用了一个Applet构件的方法,并获得一个IMail接口指针,其指向CMail构件对象,它是一个具有Applet属性的构件对象;
pIMail->SendMail(......);//再调用CMail的SendMail方法,也就是调用一个具有Applet属性的构件对象的方法;
......
(4)Console output//运行程序后,控制台的输出
TMail::Main():current thread is 0x40001000//Applet构件TMail的主线程的线程句柄是0x40001000。这个线程同时也是它的回调线程。
In Caller Applet:current thread is 0x40002000//调用Applet的客户端程序的线程的句柄是0x40002000。
TMail::GetMailer():current thread is 0x40001000//构件用户实现的GetMailer方法运行时所在的线程的句柄是0x40001000。
CMail::SendMail():current thread is 0x40001000//构件用户实现的SendMail方法运行时所在的线程的句柄是0x40001000。
从上面的四个代码片断可以看出,被调用的GetMail方法和SendMail方法都是在0x40001000这个线程里执行的,而这个线程是Applet的Mail线程,而与调用者是什么线程没有关系。
因此可以确定,即便有多个外部线程同时调用Applet构件对象的方法,也不必考虑多线程问题,因为所有调用都会进入消息队列,由消息线程逐个按序调用,具有线程安全性。
对Applet实现的接口方法的调用一定是采用Applet线程模型的方式实现;对于使用Applet属性关键字修饰的普通构件类的调用,也采用Applet线程模型完成。并且,由哪个Applet创建的它,就由哪个Applet负责完成对它接口方法的调用请求。
如果Applet向外导出某个内部构件类对象也不必考虑多线程问题,或者破坏Applet独立性,它可以使用Applet属性修饰该构件类。
对于调用Applet接口方法的一方来说,整个调用过程也是透明的,它仍然是同步方式调用这些方法,当这些接口方法返回时就代表目标代码已执行完成,与调用其它构件对象的接口方法并无不同。
机译: 通过applet和远程方法调用进行Java客户端代理身份验证过程的系统和方法
机译: 基于applet的账户安全保护方法和系统
机译: 基于applet的服务运营系统及其方法