ACE基本的多線程編程(Basic Multithreaded Programming)

 

ACE基本的多線程編程(Basic Multithreaded Programming)

標籤Programming  ACE  Basic  線程  2008-12-10 19:23
ACE_Task_BaseACE_Task派生你的線程對象,重載virtual int svc (void);虛函數,那就是線程的入口函數。
#include <ace/OS.h>
#include <ace/Task.h>

class HA_CommandHandler : public ACE_Task_Base
{
public:
    virtual int svc(void)
    {
        ACE_DEBUG((LM_DEBUG,
                   ACE_TEXT("(%t) Handler Thread running/n")));
        ACE_OS::sleep(4);
        return 0;
    }
};

int ACE_TMAIN(int, ACE_TCHAR *[])
{
    ACE_DEBUG((LM_DEBUG,
               ACE_TEXT("(%t) Main Thread running/n")));

    HA_CommandHandler handler;
    int result = handler.activate();
    ACE_ASSERT(result == 0);

    handler.wait();
    return 0;
}

在激活線程
(activate()方法)之後,主線程會調用處理器對象上的wait()方法,等待其線程完成,然後在繼續執行,並退出main()函數。


使用線程互斥體ACE_Thread_Mutex
如果成功獲得互斥體,進行獲取的線程(acquire())繼續向前執行;否則它就會阻塞,直到該互斥體的持有者釋放它(release())爲止。
#include <ace/OS.h>
#include <ace/Log_Msg.h>
#include <ace/Task.h>
#include <ace/Thread_Mutex.h>

class HA_Device_Repository
{
public:
    HA_Device_Repository()
    { }

    void update_device(int device_id)
    {
        //使用守衛
        //ACE_GUARD(ACE_Thread_Mutex, mon, mutex_);
        ACE_Guard<ACE_Thread_Mutex> guard(this->mutex_);

        //mutex_.acquire();
        ACE_DEBUG((LM_DEBUG,
                   ACE_TEXT("(%t) Updating device %d/n"),
                   device_id));
        ACE_OS::sleep(1);
        //mutex_.release();
    }
private:
    ACE_Thread_Mutex mutex_;
};
class HA_CommandHandler : public ACE_Task_Base
{
public:
    enum {NUM_USES = 10};

    HA_CommandHandler(HA_Device_Repository& rep) : rep_(rep)
    { }

    virtual int svc(void)
    {
        ACE_DEBUG((LM_DEBUG,
                   ACE_TEXT("(%t) Handler Thread running/n")));
        for (int i=0; i < NUM_USES; i++)
            this->rep_.update_device(i);
        return 0;
    }

private:
    HA_Device_Repository& rep_;
};

int ACE_TMAIN(int, ACE_TCHAR *[])
{
    HA_Device_Repository rep;
    HA_CommandHandler handler1(rep);
    HA_CommandHandler handler2(rep);
    handler1.activate();
    handler2.activate();

    handler1.wait();
    handler2.wait();

    return 0;
}


使用守衛(
Using Guards
當然你在上面的代碼中你已經看到了我已經使用了守衛(
Guards)。
在許多的情況下,異常情況會在本可以完好運行的代碼中造成死鎖(忽略了某個異常路經、忘記釋放互斥體)。
守衛(Guards)基於一種常見的C++慣用手法:把構造器和析構器用於資源的獲取和釋放。
在棧上使用
守衛(Guards),你就總能保證鎖的釋放,不管你的代碼所走的是什麼樣的非正常路徑。
ACE Guard Classes

Guard

 

Description

 

ACE_Guard<T>

Uses the acquire() and release() methods of lock class T during guard creation and destruction. Thus, you get the semantics of acquire() and release() methods for the specified type T.

ACE_Read_Guard<T>

Uses acquire_read() for acquisition instead of the regular acquire().

ACE_Write_Guard<T>

Uses acquire_write() for acquisition instead of the regular acquire().

ACE_TSS_Guard<T>

Allocates the guard on the heap and keeps a reference to it in thread-specific storage. This ensures that the lock is always released even if the thread exits explicitly, using ACE_Thread::exit().

ACE_TSS_Read_Guard<T>

Read version of a thread-specific guard.

ACE_TSS_Write_Guard<T>

Write version of a thread-specific guard.

當然這裏有相應的宏

The following guard macros do not return values:

  • ACE_GUARD (LockType, GuardName, LockObject)

  • ACE_WRITE_GUARD (LockType, GuardName, LockObject)

  • ACE_READ_GUARD (LockType, GuardName, LockObject)

These guard macros return ReturnValue on an error:

  • ACE_GUARD_RETURN (LockType, GuardName, LockObject, ReturnValue)

  • ACE_WRITE_GUARD_RETURN (LockType, GuardName, LockObject, ReturnValue)

  • ACE_READ_GUARD_RETURN (LockType, GuardName, LockObject, ReturnValue)

LockType用作守衛類模板中的T,GuardName是所創建的守衛對象名稱,LockObject是守衛所引用的鎖對象,而ReturnValue是出錯時的返回值(so你的函數需要有返回值)。


任務間的通信
兩個寬泛的範疇:
1)狀態變化或事件通知;
使用條件變量ACE_Condition模板類。
獲取互斥體,檢查系統是否處在所需狀態中,所需條件爲真----如果是這樣,就執行所需操作,然後釋放互斥體,完成後更新後,調用條件變量signal()方法;所需條件爲假----調用條件變量的wait()方法,等待系統狀態發生變化。
#include <ace/OS.h>
#include <ace/Log_Msg.h>
#include <ace/Thread_Mutex.h>
#include <ace/Condition_T.h>
#include <ace/Task.h>

class HA_Device_Repository
{
private:
    ACE_Task_Base* owner_;
    //ACE_Thread_Mutex mutex_;
public:
    HA_Device_Repository() : owner_(0)
    { }

    void update_device(int device_id)
    {
        ////使用守衛
        //ACE_Guard<ACE_Thread_Mutex> guard(this->mutex_);

        ACE_DEBUG((LM_DEBUG,
            ACE_TEXT("(%t) Updating device %d/n"),
            device_id));
        ACE_OS::sleep(1);
    }

    int is_free(void)
    {
        return (this->owner_ == 0);
    }

    int is_owner (ACE_Task_Base* tb)
    {
        return (this->owner_ == tb);
    }

    ACE_Task_Base* get_owner(void)
    {
        return this->owner_;
    }

    void set_owner(ACE_Task_Base* owner)
    {
        this->owner_ = owner;
    }
};
class HA_CommandHandler : public ACE_Task_Base
{
private:
    HA_Device_Repository& rep_;
    ACE_Thread_Mutex& mutex_;
    ACE_Condition<ACE_Thread_Mutex>& waitCond_;

public:
    enum {NUM_USES = 10};

    HA_CommandHandler(HA_Device_Repository& rep,
                    ACE_Condition<ACE_Thread_Mutex>& wait,
                    ACE_Thread_Mutex& rep_mutex)
                    : rep_(rep),
                        waitCond_(wait),
                        mutex_(rep_mutex)
    { }

    virtual int svc(void)
    {
        ACE_DEBUG((LM_DEBUG,
            ACE_TEXT("(%t) Handler Thread running/n")));
        for (int i=0; i < NUM_USES; i++)
        {
            this->mutex_.acquire();
            while (!this->rep_.is_free())
                //阻塞,進入休眠
                this->waitCond_.wait();
            this->rep_.set_owner(this);
            this->mutex_.release();

            this->rep_.update_device(i);

            ACE_ASSERT(this->rep_.is_owner(this));
            this->rep_.set_owner(0);

            //讓阻塞的進程甦醒過來
            this->waitCond_.signal();
           
            //讓甦醒過來的進程有機會獲得條件變量
            ACE_OS::sleep(1);
       
        }
        return 0;
    }
};
int ACE_TMAIN(int, ACE_TCHAR *[])
{
    HA_Device_Repository rep;
    ACE_Thread_Mutex rep_mutex;
    ACE_Condition<ACE_Thread_Mutex> wait(rep_mutex);

    HA_CommandHandler handler1(rep, wait, rep_mutex);
    HA_CommandHandler handler2(rep, wait, rep_mutex);

    handler1.activate();
    handler2.activate();

    handler1.wait();
    handler2.wait();

    return 0;
}
2)消息(數據)傳遞(
Message Passing)。

消息塊(Message Blocks)
ACE_Message_Block 一種高效的數據容器,可以用來高效的存儲和共享消息。支持引用計數和數據共享特性。
rd_ptr()指針,指向要讀取的下一個字節,;
wr_prt()指針,指向下一個可用的空字節;
copy()方法把數據複製到消息塊;
msg_type()修改類型字段。
一旦你使用完了消息塊,要用release()方法釋放它,使引用計數減一,當引用計數到達0時,ACE會自動釋放這個塊分配的內存。

使用消息隊列
ACE_Message_Block
ACE_Task模板類含有一個
ACE_Message_Block,你可以傳入模板參數,ACE_MT_USE,讓ACE_Message_Block是多線程安全的FIFO。
ACE_Task::putq()消息塊入隊;
ACE_Task::getq()消息塊出隊。

這裏有多種ACE_Message_Block子類,有不同的特徵:

Name

 

Description

 

ACE_Dynamic_Message_Queue

A priority-queue implementation that dynamically readjusts the priority of a message, using variants of the earliest-deadline-first scheme and a laxity (time to deadline minus worst-case execution time) schemes. For details, see the ACE reference documentation.

ACE_Message_Queue_Vx

Wrapper around the Wind River VxWorks message queue facility.

ACE_Message_Queue_Ex

An even more type-safe version of ACE_Message_Queue.

ACE_Message_Queue_NT

Implementation that is built on Windows NT's I/O completion port features.[a]

發佈了12 篇原創文章 · 獲贊 4 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章