一个基于ACE的线程池的实现(转)

这是一个基于ACE的线程库实现,属于半同步半异步类型的线程池,感觉实现得非常优雅,代码是由网上下的好几份代码拼凑而成的(ACE的源码包中的tests目录下有大量的实例,研究这些例子是学习ACE的好办法,只是由于注释都是一堆堆的英文,有时候感觉头疼,就懒得去看它了)。这个线程池由一个线程池管理器管理着五个线程来处理消息,当五个处理线程都在处理消息时,接收新的消息将导致线程管理器被阻塞。消息处理线程处理完发给自己的消息后将被阻塞,其将重新被管理器管理器放入队列中。越发感觉到ACE的强大,只可惜我们的程序用不上。一个原因是我们程序本身处理的数据量并不会太大;另外我们的程序只要求跑在Solaris上面,不会出现异构的平台;最后ACE库本身太繁杂了,很多地方比如网络相关的函数我们是不会用的,不过如果现在我们正在使用的网络库也使用ACE的话,那么使用ACE简直再好不过了。
#include  " ace/OS.h "
#include 
" ace/Task.h "
#include  
" ace/Thread.h "
#include 
" ace/Synch.h "

class  Worker;

class  IManager
{
public :
    
virtual   int  return_to_work (Worker  * worker)  =   0 ;
};

class  Worker :  public  ACE_Task < ACE_MT_SYNCH >
{
public :
    Worker (IManager 
* manager) : manager_(manager) { }

    
// 线程启动之后进入本函数
     virtual   int  svc ( void )
    {
        thread_id_ 
=  ACE_Thread::self();

        
// 工作线程启动之后只有收到MB_HANGUP类型的消息它才会退出
         while  ( 1 )
        {
            ACE_Message_Block 
* mb  =   0 ;

            
// 如果队列中没有数据,本线程将被阻塞
             if  ( this -> getq(mb)  ==   - 1 )
                ACE_ERROR_BREAK((LM_ERROR, ACE_TEXT (
" %p  " ), ACE_TEXT ( " getq " )));

            
//  如果是MB_HANGUP消息,就结束线程
             if  (mb -> msg_type()  ==  ACE_Message_Block::MB_HANGUP)
            {
                ACE_DEBUG ((LM_INFO,
                    ACE_TEXT (
" (%t) Shutting down  " )));
                    mb
-> release();

                
break ;
            }

            
//  Process the message.
            process_message (mb);

            
//  Return to work.
            
//  这里会将自己放到线程池中,并通过workers_cond_来通知manager
             this -> manager_ -> return_to_work ( this );
        }

        
return   0 ;
    }

    ACE_thread_t thread_id(
void )
    {
        
return  thread_id_;
    }

private :

    
// 处理消息
     void  process_message (ACE_Message_Block  * mb)
    {
        ACE_TRACE (ACE_TEXT (
" Worker::process_message " ));

        
int  msgId;

        ACE_OS::memcpy (
& msgId, mb -> rd_ptr(),  sizeof ( int ));

        mb
-> release();

        ACE_DEBUG ((LM_DEBUG,
            ACE_TEXT (
" (%t) Started processing message %d  " ),
            msgId));

        ACE_OS::sleep(
3 );

        ACE_DEBUG ((LM_DEBUG,
            ACE_TEXT (
" (%t) Finished processing message %d  " ),
            msgId));
    }

    
// 指向线程池管理器
    IManager  * manager_;

    
// 保存本线程id号
    ACE_thread_t thread_id_;
};

class  Manager :  public  ACE_Task < ACE_MT_SYNCH > public  IManager
{
public :
    
enum  {POOL_SIZE  =   5 , MAX_TIMEOUT  =   5 };

    Manager ()
        : shutdown_(
0 ), workers_lock_(), workers_cond_(workers_lock_)
    {
        ACE_TRACE (ACE_TEXT (
" Manager::Manager " ));
    }

    
/*  线程处理函数  */
    
int  svc ( void )
    {
        ACE_TRACE (ACE_TEXT (
" Manager::svc " ));

        ACE_DEBUG ((LM_INFO, ACE_TEXT (
" (%t) Manager started  " )));

        
//  Create pool.
        create_worker_pool();

        
while  ( true )
        {
            ACE_Message_Block 
* mb  =   0 ;
            ACE_Time_Value tv ((
long )MAX_TIMEOUT);
            tv 
+=  ACE_OS::time ( 0 );

            
//  Get a message request.
             if  ( this -> getq (mb,  & tv)  <   0 )
            {
                shut_down ();
                
break ;
            }

            
//  Choose a worker.
            Worker  * worker  =   0 ;

            
/*  
            这对大括号中的代码从worker线程池中获取一个工作线程,线程池由
            this->workers_lock_互斥体加以保护,如果没有worker可用,manager
            会阻塞在workers_lock_条件变量上,等待某个线程回来工作
            
*/
            {
                ACE_GUARD_RETURN (ACE_Thread_Mutex,
                    worker_mon, 
this -> workers_lock_,  - 1 );

                
/*  
                阻塞在workers_lock_.wait()上直到有worker可用,当某个worker回来后
                会把自己放到线程池队列上,同时通过触发workers_cond_来通知manager
                
*/
                
while  ( this -> workers_.is_empty ())
                    workers_cond_.wait ();

                
/*  将获取的worker从线程池队列中删除  */
                
this -> workers_.dequeue_head (worker);
            }

            
//  Ask the worker to do the job.
            
//  将请求消息放入到worker的消息队列中
            worker -> putq (mb);
        }

        
return   0 ;
    }

    
int  shut_down ( void )
    {
         ACE_TRACE (ACE_TEXT (
" ACE_ThreadPool::DestroyPool " ));

         ACE_Unbounded_Queue
< Worker *   > ::ITERATOR iter  =   this -> workers_.begin();

        Worker
**  worker_ptr  =  NULL;

         
do
        {
            iter.next (worker_ptr);

            Worker 
* worker  =  ( * worker_ptr);

            
//  Send the hangup message.
            ACE_Message_Block  * mb;
            ACE_NEW_RETURN(
                mb,
                ACE_Message_Block(
0 ,
                ACE_Message_Block::MB_HANGUP),
                
- 1 );

            worker
-> putq(mb);

            
//  Wait for the exit.
            worker -> wait();

            ACE_ASSERT (worker
-> msg_queue() -> is_empty ());

            delete worker;
         }
while  (iter.advance());

         
return   0 ;
    };

    ACE_thread_t thread_id (Worker 
* worker);

    
/*  提供给worker的接口,用于在worker完成处理后,将自己放入到线程池队列,并通知manager  */
    
virtual   int  return_to_work (Worker  * worker)
    {
        ACE_GUARD_RETURN (ACE_Thread_Mutex,
            worker_mon, 
this -> workers_lock_,  - 1 );

        ACE_DEBUG ((LM_DEBUG,
            ACE_TEXT (
" (%t) Worker %u returning to work.  " ),
            worker
-> thr_mgr() -> thr_self()));

        
//  将worker放入到线程池队列
         this -> workers_.enqueue_tail (worker);

        
//  触发条件变量,通知manager
         this -> workers_cond_.signal ();

        
return   0 ;
    }

private :
//  创建worker线程池
     int  create_worker_pool ( void )
    {
        ACE_GUARD_RETURN (ACE_Thread_Mutex,
            worker_mon,
            
this -> workers_lock_,
            
- 1 );

        
for  ( int  i  =   0 ; i  <  POOL_SIZE; i ++ )
        {
            Worker 
* worker;

            
//  创建worker
            ACE_NEW_RETURN (worker, Worker ( this ),  - 1 );

            
//  放入线程池队列
             this -> workers_.enqueue_tail (worker);

            
//  激活线程,调用该函数后,worker线程被创建,由于worker
            
//  是ACE_Task的子类,线程激活后,从svc函数开始执行
            worker -> activate ();
        }

        
return   0 ;
    }

private :
    
int  shutdown_;

    
/*  workers_lock_ 线程池队列的互斥体,在对线程池进行操作时,需要通过互斥锁来保护
    所以在所有的线程池队列队列操作前都有这样的语句:
        ACE_GUARD_RETURN (ACE_Thread_Mutex,
        worker_mon, this->workers_lock_, -1);
        
*/
    ACE_Thread_Mutex workers_lock_;
    ACE_Condition
< ACE_Thread_Mutex >  workers_cond_;

    
/*  线程池队列  */
    ACE_Unbounded_Queue
< Worker *   >  workers_;
};

int  ACE_TMAIN ( int , ACE_TCHAR  * [])
{
    Manager tp;
    tp.activate ();

    
//  Wait for a moment every time you send a message.
    ACE_Time_Value tv;
    tv.msec (
100 );

    ACE_Message_Block 
* mb;
    
for  ( int  i  =   0 ; i  <   10 ; i ++ )
    {
        ACE_NEW_RETURN(mb, ACE_Message_Block(
sizeof ( int )),  - 1 );

        ACE_OS::memcpy (mb
-> wr_ptr(),  & i,  sizeof ( int ));

        ACE_OS::sleep(tv);

        
//  Add a new work item.
        
//  这里将请求消息首先发到了manager线程,由manager线程负责分发
        tp.putq (mb);
    }

    
//  主线程等待子线程结束
    ACE_Thread_Manager::instance() -> wait();

    
return   0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值