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) |