ACE_Task介绍
ACE_Task 是ACE 中的任務或主動對象“處理結構”的基類。在ACE 中使用了此類來實現主動對象模式。所有希望成為“主動對象”的對象都必須從此類派生。你也可以把ACE_Task看作是更高級的、更為面向對象的線程類。相當于我們具體業務是繼承ACE_Task這個類進行實現的。
ACE_Task處理的是對象,因而在構造OO程序時更便于思考。因此,在大多數情況下,當你需要構建多線程程序時,較好的選擇是使用ACE_Task 的子類。這樣做有若干好處。首要的是剛剛所提到的,這可以產生更好的OO軟件。其次,你不必操心你的線程入口是否是靜態的,因為ACE_Task 的入口是一個常規的成員函數。而且,我們會看到ACE_Task 還包括了一種用于與其他任務進行通信的易于使用的機制。
要創建任務,需要進行以下步驟:
open()方法應該包含所有專屬于任務的初始化代碼。其中可能包括諸如連接控制塊、鎖和內存這樣的資源。close()方法是相應的終止方法。
在主動對象實例化后,你必須通過調用activate()啟用它。要在主動對象中創建的線程的數目,以及其他一些參數,被傳遞給activate()方法。activate()方法會使svc()方法成為所有它生成的線程的啟動點。
如上面所提到的,在主動對象被啟用后,各個新線程在svc()方法中啟動。應用開發者必須在子類中定義此方法。
ACE 中的每個任務都有一個底層消息隊列(ACE_Message_Block),這個消息隊列被用作任務間通信的一種方法。當一個任務想要與另一任務“談話”時,它創建一個消息,并將此消息放入它想要與之談話的任務的消息隊列使用putq方法。接收任務通常用getq () 從消息隊列里獲取消息。如果隊列中沒有數據可用,它就進入休眠狀態。如果有其他任務將消息插入它的隊列,它就會蘇醒過來,從隊列中拾取數據并處理它。因而,在這種情況下,接收任務將從發送任務那里接收消息,并以應用特定的方式作出反饋。
putq()?方法
將消息插入到另一任務的消息隊列中
getq()方法
將消息提取出來
這樣的體系結構大大簡化了多線程程序的編程模型下一個例子演示兩個任務怎樣使用它們的底層消息隊列進行通信。這個例子包含了經典的生產者-消費者問題的實現。生產者任務生成數據,將它發送給消費者任務。消費者任務隨后消費這個數據。使用ACE_Task 構造,我們可將生產者和消費者看作是不同的ACE_Task 類型的對象。這兩種任務使用底層消息隊列進行通信。
生產者消費者實例1:生產者和消費者共享同一個內部消息隊列
消費者實現,主要是任務的接受數據進行處理,svc函數表示線程的啟動的入口,putq方法傳輸進來的底層數據。 #include "ace/Task.h"class ProduceAudio : public ACE_Task<ACE_MT_SYNCH> { public:ProduceAudio(ACE_Thread_Manager *thr_man=0,ACE_Message_Queue<ACE_MT_SYNCH> *mq=0);~ProduceAudio(void);int open(void*);int svc(void); }; #include "ProduceAudio.h"#include "ace/Log_Msg.h" #include "ace/OS.h" #include "Converter.h" #include <string> using namespace std;ProduceAudio::ProduceAudio(ACE_Thread_Manager *thr_man,ACE_Message_Queue<ACE_MT_SYNCH> *mq):ACE_Task<ACE_MT_SYNCH>(thr_man,mq) { }ProduceAudio::~ProduceAudio(void) {ACE_DEBUG((LM_DEBUG, "(%t) ~ProduceAudio()\n")); }int ProduceAudio::open(void*) { ACE_DEBUG((LM_DEBUG, "(%t) ProduceAudio task opened\n")); activate(THR_NEW_LWP,1); return 0; } int ProduceAudio::svc(void) {ACE_DEBUG((LM_DEBUG, "(%t) ProduceAudio::svc() running\n")); string s("message");for ( int i=0;i<3;++i){ACE_Message_Block * blk = new ACE_Message_Block(10);blk->copy( (s + lexical_cast<string>(i)).c_str());this->putq(blk);//this->put(blk);ACE_DEBUG((LM_DEBUG, "(%t) ProduceAudio::svc() put(%s),now msg_queue()->message_count()[%d]\n",blk->rd_ptr(),this->msg_queue()->message_count())); ACE_OS::sleep(1);}ACE_DEBUG((LM_DEBUG, "(%t) ProduceAudio::svc() return\n")); return 0; }消費者類 獲取從其他線程putq傳送過來的底層數據,就是不同線程間的通信
#include "ace/Task.h"class SendToServer : public ACE_Task<ACE_MT_SYNCH> { public:SendToServer(ACE_Thread_Manager *thr_man=0,ACE_Message_Queue<ACE_MT_SYNCH> *mq=0);~SendToServer(void);int open(void*);int svc(void); };#include "SendToServer.h"#include "ace/OS.h" #include <string> using namespace std;SendToServer::SendToServer(ACE_Thread_Manager *thr_man,ACE_Message_Queue<ACE_MT_SYNCH> *mq):ACE_Task<ACE_MT_SYNCH>(thr_man,mq) { }SendToServer::~SendToServer(void) {ACE_DEBUG((LM_DEBUG, "(%t) ~SendToServer()\n")); }int SendToServer::open(void*) { ACE_DEBUG((LM_DEBUG, "(%t) SendToServer task opened\n")); activate(THR_NEW_LWP,1); return 0; } int SendToServer::svc(void) {ACE_DEBUG((LM_DEBUG, "(%t) SendToServer::svc() running\n")); ACE_Message_Block * blk = NULL;int count =0;for ( ; count<3;){if (this->msg_queue()->message_count()>0){this->getq(blk);++count;ACE_DEBUG((LM_DEBUG,"SendToServer get :%s\n",blk->rd_ptr()));blk->release();}ACE_OS::sleep(1);}ACE_DEBUG((LM_DEBUG, "(%t) SendToServer::svc() return\n")); return 0; }main函數
#include "ace/Thread_Manager.h" #include "SendToServer.h" #include "ProduceAudio.h"#ifdef _DEBUG #pragma comment (lib,"ACEd.lib") #else #pragma comment (lib,"ACE.lib") #endif int main(int argc, char* argv[]) {SendToServer consumer(NULL,NULL);ProduceAudio producer(NULL,consumer.msg_queue());producer.open(NULL);consumer.open(NULL);ACE_Thread_Manager::instance()->wait();return 0; }
總結
以上是生活随笔為你收集整理的ACE_Task介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ACE Lock类介绍
- 下一篇: linux硬件设备操作函数 open