分享
 
 
 

ACE例子之APG例子的Active_Objects示例

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

APG例子的Active_Objects示例

md,硬着头皮上,分析一把这个只有100多行的程序。

遇到的问题列表:

ACE_TRACE的不起作用:在调试中并没有看到有关的ACE_TRACE的输出,经过GOOGLE,发现需要定义ACE_NTRACE 为0,这样就可以打开TRACE跟踪了。

ACE自动指针的问题:在看程序的时候有这样的一段代码:

在Scheduler类的svc函数中,有这样的代码:

auto_ptr<ACE_Method_Request> request (this->activation_queue_.dequeue());

恩,这是一个循环内部的代码,每次从activation_queue_中取得的块,都会在auto_ptr下次构造这个reqeust的时候被释放,或者最终销毁request的时候被释放。这个是auto_ptr的用处所在。自己不是特别习惯这样的用法。因为不是那样的直观,不过这样的用法确实能够避免很多问题。代价是一些不够透明的影响。

到底ACE_Future是一个什么样的东西?为了能够彻底解决这个疑惑,俺决定把ACE_Future拿出来看看。ACE_Future 是一个为了异步返回结果所设计的模版。他允许一个写,多个读。经过深入的分析,ACE_Future是一个用来装载结果引用的一个容器,如果引用的数量为0,那么就会销毁这个结果。这个比较拗口一点,具体来讲,就是这样的,我们可以定义一堆的ACE_Future的东西,这些东西可以互相指来指去,每指一次,那么就增加一个引用次数。当销毁这个ACE_Future的时候,如果引用次数不为0,那么这个对象实际上是没有销毁。并且对于写来说是有保护的。这样,可以很容易的写出很简单的代码。为了更加清楚地说明这点,我们用这个例子里的实际应用来说明:

在例子程序中,主程序定义了一个ACE_Future<int> results[10]的数组,用来保存工作线程的工作结果。在一般的设计中,要么使用把这10个数组元素传入工作线程中,要么这10个数组元素用来保存工作线程内部暴露的结果。可是,例子是怎样做的呢?

ACE_Future<int> results[10];

for(int i=0;i<10;i++)

results[i] = controller.status_update();

难道这个controller.status_update返回了线程内部的结果?我们看看这个status_update的实现。

ACE_Future<int> status_update()

{

ACE_Future<int> result;

This->scheduler_.enqueue(new StatusUpdate(this->controller_, result));

return result;

}

俺的脑海中,疑窦顿生,shit,这个不是摆明了说这里定义的result其实是跨越了生命周期的么,也就是说,这里定义的result,并不会随着函数的终止而销毁,而会带到调用者(实际上是有3个地方,一个是这里的result,一个是给StatusUpdate的result,还有一个,就是返回去的result)当这三个地方的result都销毁的时候,最后一个result销毁的时候发现自己的引用数量变成了0,于是销毁自己。这样就变相的延长了结果的生命周期。

不过这样也会引入一个问题,就是说,由于返回的时候,会为了返回值而重新创建一个ACE_Future<int> r=result;然后才会销毁这个result,然后调用者Results[j]=r。然后再销毁这个临时的返回变量r。

为了清晰的鉴定,俺作了一个函数来决定:

ACE_Future<int> stupid(void)

{

ACE_Future<int> result(5);

Return result;

}

调用者是这样的:

ACE_Future<int> rs;

Rs = stupid();

如果是这样,那么这个结果(在ACE_Future<int> result(5))定义的result),会在rs销毁的时候才真正销毁。

如果俺就直接调用stupid()而没有rs=stupid();那么这个结果在执行完stupid()之后就立刻销毁。

这个程序何时创建线程的?在HA_ControllerAgentProxy类中,有一个成员Scheduler scheduler_这个成员函数的构造函数中调用了activate(),这里创建的线程。并且开始从svc函数开始工作。

这几个问题解决以后,这个程序的结构就迎刃而解。这个程序是演示ACE的多线程任务调度的。主要是演示ACE_Method_Request和ACE_Task_Base之间的任务配合,以及使用ACE_Future作返回值传递的演示。还有关于auto_ptr的使用范例。

程序分析

根据传统的分析方法,我们从ACE_TMAIN主函数开始进行分析这个例子。

int ACE_TMAIN (int, ACE_TCHAR *[])

{

HA_ControllerAgentProxy controller;

ACE_Future<int> results[10];

for (int i = 0 ; i < 10; i++)

results[i] = controller.status_update ();

ACE_DEBUG ((LM_DEBUG,

ACE_TEXT ("begin sleep 5 seconds\n")));

ACE_OS::sleep (5); // Do other work.

ACE_DEBUG((LM_DEBUG,

ACE_TEXT("sleep end,and begin get results\n")));

// Get results...

for (int j = 0; j < 10; j++)

{

int result;

results[j].get (result);

ACE_DEBUG ((LM_DEBUG,

ACE_TEXT ("New status_update %d\n"), result));

}

// Cause the status_updater threads to exit.

controller.exit ();

ACE_Thread_Manager::instance ()->wait ();

return 0;

}

首先是定义了一个用于控制用的类,这个类中,会有一个任务调度器,这个任务调度器会创建一个线程。在这个类中,还有一个用于控制用的类对象,这个类对象就是用于每次花费两秒钟对返回值加一。不过一开始的时候,这个控制用的类对象并不会自行工作,而是等到工作线程接下来调用。在主程序定义了这个变量之后,就已经创建了用于工作的线程,并且开始等待工作队列上的任务对象。

接下来定义了10个返回值。并且用一个循环设置10个任务(更新任务)。在设置更新任务的同时,工作线程从工作队列上得到了这个任务(见svc函数),并且调用这个任务对象的call方法。调用call方法目前就是调用的是StatusUpdate类的call方法。执行StatusUpdate的call方法会执行到用于控制类里边的加一操作,并且设置对应任务对象的返回值。

同时,主线程会休眠5秒钟,在休眠完成以后,主线程会依次取得返回值,很快的(由于前边sleep了5秒钟,所以,应当有两个已经执行完毕,有了返回值),会出现两个返回值,以后的返回值就是成对出现的了。

最后,通过往任务队列里边压一个退出任务通知svc函数退出。然后用ACE_Thread_Manager来等待所有的线程都结束。

难点

在StatusUpdate类里边,构造函数的定义:

StatusUpdate(HA_ControllerAgent & controller,ACE_Future<int> &returnval):controller_(controller),returnVal_(returnval)

而我们看见:定义的成员变量controller_和returnVal_却并非都是引用定义:

一个是:HA_ControllerAgent & controller_;一个是ACE_Future<int> returnVal_;

我们就有了疑惑,为何定义有区别?是否参数设计上一定都是引用设计?

对于controller来说,是需要引用设计的,要不然就是指针设计,因为不同的StatusUpdate对象需要同一个controller控制对象,所以,需要引用设计或者指针设计,同样的,这就要求成员变量controller的定义是引用或者指针。

但是注意的是对于ACE_Future<int>这个参数的设计。由于这个对象可能是跨作用域的,所以,如果用引用的方式赋值,就会导致成员变量指向一个已经释放的对象,所以,不能用引用赋值,只能用直接赋值,通过ACE_Future<int>模板本身来进行对象的引用。所以在参数上,既可以是&也可以不是引用。只要赋值不是引用赋值就可以了。

执行细节分析

1. 执行HA_ControllerAgentProxy controller.

2. 执行ACE_Future<int> results[10];

3. 执行controller.status_update();

主线程

创建controller.scheduler对象

Scheduler.Schedule{activate();}

创建controller.controller_对象

初始化了计数器(用于返回值)

创建10个ACE_Future<int>用于返回值

执行第一个controller.status_update()

创建ACE_Future<int>返回值

创建StatusUpdate对象(使用刚创建的返回值和controller.controller_对象)

压入schedule的工作队列(这时候就发现为什么有必要Scheduler类继承一个压队列方法了)

设置第一个返回值=刚创建的返回值

执行第二个到第10个controller.status_update

等待5秒钟

子线程

线程创建了

开始等待activation_queue_的队列

(由于队列空,则一直等待)

接收到队列里边的StatusUpdate对象

执行StatusUpdate.Call()

设置controller_的返回值+1

等待2秒钟

输出返回值

接收到队列里边的StatusUpdate对象

执行StatusUpdate.Call()

设置controller_的返回值+1

等待2秒钟

主线程

继续等待中

执行等待一个返回结果

立刻返回了

执行等待第二个返回结果

立刻返回了

执行等待第三个返回结果

等待中

返回了

执行等待第四个返回结果

等待中

返回了

<依次类推>

执行controller.exit

压入schedule的工作队列一个退出对象。这个退出对象的Call方法只是简单返回一个-1

执行等待线程管理器本instance所有的线程结束。

程序结束了

子线程

等待2秒钟

输出返回值

执行StatusUpdate.Call()

设置返回值=controller_的返回值

设置controller_的返回值+1

等待2秒钟

输出返回值

执行StatusUpdate.Call()

设置返回值=controller_的返回值

设置controller_的返回值+1

等待2秒钟

输出返回值。

<依次类推>

接收到推出对象ExitMethod,执行ExitMethod.Call返回-1,于是从svc返回

线程终止了

小结

本例子的关键词:ACE_Future,ACE_Task_Base,ACE_Method_Request,auto_ptr

还不是很习惯这样的思维方式。不过已经渐渐有点明白了。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有