Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1950988
  • 博文数量: 77
  • 博客积分: 2175
  • 博客等级: 大尉
  • 技术积分: 2491
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-20 20:49
个人简介

欢迎光临我的博客

文章分类

全部博文(77)

文章存档

2023年(1)

2018年(4)

2017年(1)

2016年(2)

2015年(2)

2013年(5)

2012年(29)

2010年(33)

分类: C/C++

2010-05-01 16:27:55


3.1  概念



该模型来自于ACE(Adaptive Communication Environment)源码库。

客户端是服务请求方,一个简单的例子:

Proxy proxy(100); //构造最大容量100个消息的proxy

while(receive data from network)

{

    MyMessage mymsg(…);  //构造消息

            proxy.Put(mymsg);//把消息递交给后台线程处理

 

            //同步调用,等待处理结果。如果不需要处理结果,可不调用

            Future *result = proxy.Get();

}

主动对象是内部拥有自己的控制线程的对象。为了简化异步调用的复杂性,主动对象模型模式分离了方法的执行和调用。使用这个模型,一个对象中无论是否有独立的线程,客户从外部访问它时,感觉是一样的。生产者/消费者,读者/写者,这两个应用广泛的模型中,这种策略非常适合。这个模式常用在多线程的,分布式系统中,比如应用服务器(Application Server)。它可以很好地实现多线程并发异步处理。

我在以前所开发的某应用服务器项目中就曾用过该模型。

3.2  6个角色

主动对象模型由6个角色组成:

          代理者(Proxy)

          调用请求(Method Request

          活动队列(Activation Queue

          调度者(Scheduler

          伺服器(Servant

          预约容器(Future

 

3.3  示例实现

下面是主动对象模型的一个实现代码(这可能和一些通用实现有所不同,因为作者做了一些修改以支持Proxy::Get可从多个内部线程获得对应处理结果,也就是Future)。

 

3.3.1  Method_Request/ My_Request


class Method_Request
{
public:
    virtual bool guard() const = 0;
    virtual void call() = 0;
};

class My_Request : public Method_Request
{
public:
    My_Request(Servant *servant, MyMessage &msg)
    {
        m_servant = servant;
        m_msg = msg;
    }
    virtual bool guard() const;
    virtual void call();
    
private:
    Servant *m_servant;
    MyMessage &m_msg;
};

bool My_Request::guard() const
{
    return servant != NULL;
}

void My_Request::call()
{
    //Do the handling for m_msg

    m_servant->Put(new Future());
}


3.3.2  Proxy



class Proxy

{

public:

            Proxy(int iReqQueueSize)

            {

                        m_scheduler = new Scheduler(iReqQueueSize);

                        //m_servant = new Servant(iReqQueueSize);


            }

           

            Servant *Put(const MyMessage &msg)

            {

                        Servant *serv = new Servant();

                        Method_Request *method_request = new My_Request(serv, msg);

            m_scheduler->Enqueue(method_request);

            return serv;

            }

           

            //Get the handling result


            Future *Get(Servant *serv)

            {

                        return serv->Get();

            }

protected:

            //Servant *m_servant;


            Scheduler *m_scheduler;

};



3.3.3  Servant




class Servant
{
public:
    Servant()
    {
        //Init m_cond

    }
    
    void Put(Future *future)
    {
        m_future = future;
        //set m_cond

    }
    
    Future *Get()
    {
        //wait m_cond

        return m_future;
    }
private:
    Condition m_cond;
    Future *m_future;
};



3.3.4  Mutex/Guard/Condition



//Mutex and Guard. For platform compatible, can use bridge pattern to refine.

class Mutex
{
public:
    Mutex()
    {
        //create m_mutex

    }
    
    int Acquire()
    {
        //require m_mutex;

    }
    
    int Release()
    {
        //release m_mutex;

    }
protected:
    m_sysmutex //standart system mutex

};
        
class Guard
{
public:
    Guard(Mutex &mutex)
    {
        m_mutex = mutex;
        m_mutex.Acquire ();
    }
    ~Guard()
    {
        m_mutex.Release ();
    }
    
private:
    Mutex &m_mutex;
};

class Condition
{
public:
    void Set();
    void Wait();
private:
    m_syscond     //system condition

};


3.3.5  AO_Queue



class AO_Queue
{
public:
    AO_Queue(int size)
    {
    }
    
    void Enqueue(Method_Request *request)
    {
        Guard guard(m_mutex); //Do some full handling...

        m_queue.add(request);
        m_cond.Set();
    }
    
    Method_Request *Dequeue()
    {
        bool bEmpty = false;
        do
        {
            Guard guard(m_mutex);
            bEmpty = m_queue.empty();
            if(bEmpty)
            {
                guard.~Guard();
                m_cond.Wait();
            }
            else
            {
                return m_queue.pop();
            }
        }while(bEmtpy);
    }
    
protected:
    std::list<Method_Request *> m_queue;
    Mutex m_mutex;
    Condition m_cond;
};



3.3.6  Scheduler

class Scheduler

{

public:

            Scheduler(int iReqQueueSize)

            {

                        m_queue = new AO_Queue(iReqQueueSize);

                        //init m_pWorkers and lauch them


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

                        {

                                    m_pWorkers[i] = new ThreadWorker(this);

                                    m_pWorkers[i]->Run();

                        }

            }

           

            virtual void Enqueue(Method_Request *request);

            virtual Dispatch();

protected:

            Thread *m_pWorkers[MAX_WORKER_THREADS];

            AO_Queue *m_queue;

};

 

void Scheduler::Enqueue(Method_Request *request)

{

            m_queue->Enqueue(request);

}

 

 

void Scheduler::Dispatch()

{

            Method_Request *request = m_queue->Dequeue();

            request->call();

            delete request;

}



3.3.7  Thread/ThreadWorker


class Thread
{
public:
    Thread(void *param):m_param(param)
    {
        //create system thread with arg = this

    }
        
    virtual void Run() = 0;
    static void ThreadEntry(void *arg);
protected:
    void *m_param;    
};

//The system thread entry

void Thread::ThreadEntry(void *arg)
{
    ((Thread *)arg)->Run();
}
    
class ThreadWorker
{
public:
    ThreaderWorker(void *param):Thread(param)
    {
    }
    virtual void Run();
};

void ThreadWorker::Run()
{
    Scheduler *sche = (Scheduler *)m_param;
    while(true)
        sche->Dispatch();
}


3.3.8  Future

User specified.


参考资源

Design Patterns-----------------------------------------------------------------------Erich Gamma

C++编程思想》-------------------------------------------------------------------------Bruce Eckel

作者以前做过的一些项目。




《返璞归真--UNIX技术内幕》在全国各大书店及网城均有销售:
                         
                       


阅读(13280) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~