贝贝花花包包店,精品555皮具,钱夹,皮夹

字体: | 推荐给好友 上一篇 | 下一篇

ACE程序员教程-第5章 任务和主动对象:并发编程模式

发布: 2008-6-13 14:26 | 作者: Umar Syyid | 来源: 转载 | 查看: 308次

 

5.2.3 任务间通信

  如前面所提到的,ACE中的每个任务都有一个底层消息队列(参见上面的图示)。这个消息队列被用作任务间通信的一种方法。当一个任务想要与另一任务“谈话”时,它创建一个消息,并将此消息放入它想要与之谈话的任务的消息队列。接收任务通常用getq()从消息队列里获取消息。如果队列中没有数据可用,它就进入休眠状态。如果有其他任务将消息插入它的队列,它就会苏醒过来,从队列中拾取数据并处理它。因而,在这种情况下,接收任务将从发送任务那里接收消息,并以应用特定的方式作出反馈。

  下一个例子演示两个任务怎样使用它们的底层消息队列进行通信。这个例子包含了经典的生产者-消费者问题的实现。生产者任务生成数据,将它发送给消费者任务。消费者任务随后消费这个数据。使用ACE_Task构造,我们可将生产者和消费者看作是不同的ACE_Task类型的对象。这两种任务使用底层消息队列进行通信。

 

5-2

#include "ace/OS.h"

#include "ace/Task.h"

#include "ace/Message_Block.h"

 

//The Consumer Task.

class Consumer:

public ACE_Task

{

public:

int open(void*)

{

ACE_DEBUG((LM_DEBUG, "(%t) Producer task opened \n"));

 

//Activate the Task

activate(THR_NEW_LWP,1);

 

return 0;

}

 

//The Service Processing routine

int svc(void)

{

//Get ready to receive message from Producer

ACE_Message_Block * mb =0;

do

{

mb=0;

 

//Get message from underlying queue

getq(mb);

ACE_DEBUG((LM_DEBUG,

"(%t)Got message: %d from remote task\n",*mb->rd_ptr()));

}while(*mb->rd_ptr()<10);

 

return 0;

}

 

int close(u_long)

{

ACE_DEBUG((LM_DEBUG,"Consumer closes down \n"));

return 0;

}

};

 

class Producer:

public ACE_Task

{

public:

Producer(Consumer * consumer):

consumer_(consumer), data_(0)

{

mb_=new ACE_Message_Block((char*)&data_,sizeof(data_));

}

 

int open(void*)

{

ACE_DEBUG((LM_DEBUG, "(%t) Producer task opened \n"));

 

//Activate the Task

activate(THR_NEW_LWP,1);

return 0;

}

 

//The Service Processing routine

int svc(void)

{

while(data_<11)

{

//Send message to consumer

ACE_DEBUG((LM_DEBUG,

"(%t)Sending message: %d to remote task\n",data_));

consumer_->putq(mb_);

 

//Go to sleep for a sec.

ACE_OS::sleep(1);

data_++;

}

 

return 0;

}

 

int close(u_long)

{

ACE_DEBUG((LM_DEBUG,"Producer closes down \n"));

return 0;

}

 

private:

char data_;

Consumer * consumer_;

ACE_Message_Block * mb_;

};

 

int main(int argc, char * argv[])

{

Consumer *consumer = new Consumer;

Producer * producer = new Producer(consumer);

 

producer->open(0);

consumer->open(0);

 

//Wait for all the tasks to exit. ACE_Thread_Manager::instance()->wait();

}

 

在此例中,生产者和消费者任务非常相似。它们都没有任何服务初始化或是终止代码。但两个类的svc()方法是不同的。生产者在open()方法中被启用后,svc()方法会被调用。在此方法中,生产者生成一个消息,将它插入消费者的队列。消息是使用ACE_Message_Block类来生成的(要更多地了解如何使用ACE_Message_Block,请阅读此教程及在线ACE指南中有关消息队列的章节)。生产者维护指向消费者任务(对象)的指针。它通过该指针来将消息放入消费者的消息队列中。该指针在main()函数中通过生产者的构造器设置。

  消费者驻留在它的svc()方法的循环中,等待数据到达它的消息队列。如果队列中没有数据,消费者就会阻塞并休眠(这是由ACE_Task类魔术般地自动完成的)。一旦数据到达消费者的队列,它就会苏醒并消费此数据。

  在此例中,生产者发送的数据由一个整数组成。生产者每次将这个整数加一,然后发送给消费者。

  如你所看到的,生产者-消费者问题的解决方案十分简单,并且是面向对象的。在编写面向对象的多线程程序时,使用ACE_Task是比使用低级线程API更好的方法。

42/4<1234>
 

评分:0

我来说两句

seccode