ACE线程管理---ACE_Thread_Manager  

   使用ACE_Thread_Manager类进行线程管理:



    虽然ACE_Task<>接口已经提供了相当丰富的的功能,但是ACE还是提供了一个工作在"幕后"的线程管理器类:ACE_Thread_Manager;这个线程管理器类用于帮助你管理ACE所创建的所有任务;这个管理器类提供了丰富的接口;ACE_Thread_Manager类还与ACE Streams框架紧密地集成在一起;
    ACE允许程序员登记数量不限的退出函数(或退出仿函数functor),这些退出函数或退出仿函数将在线程退出时被自动调用,以用于进行线程退出前的"最后一秒"的清理,或者说是线程退出前的善后清理,或者是通知其它线程,某个线程的结束已经临近.退出处理器的一个优点是:它们总是会被调用,即使是线程因为调用了一个低级的ACE_Thread::exit()方法而突然退出(这个方法会使线程立即退出),也同样如此;
    要设置退出functor,就必须要创建ACE_At_Thread_Exit类的一个子类,实现apply()方法,然后向ACE_Thread_Manager登记这个退出functor的一个实例.
    注意:必须在退出functor所属的线程的上下文中,向线程管理器登记这个退出functor.使用ACE_Thread_Manager::at_exit()方法登记退出functor;
    ACE_Thread_Manager::wait()会等待所有的子线程退出,而不管与那些线程相关联的是哪个任务,当你有不止一个任务正在执行的时候,使用这个特性将会很方便;
    注意:我们要把ACE_Thread_Manager类的实例当作一个单体对象使用;其原因是:在默认情况下,ACE会通过这个单体对象来管理所有的线程;尽管在大多数情况下,你会发现默认行为已经足够,你可以创建并使用多个线程管理器对象;

   线程启动挂钩:
    ACE提供了一个全局的启动挂钩,可以用于拦截对线程启动函数的调用.所以,你能够针对你的应用正在使用的线程,进行任意种类的初始化.要给线程增加线程专有的数据,线程的启动挂钩是一个很好的地方;
    要设置线程启动挂钩,就必须从ACE_Thread_Hook派生出来一个子类,并实现start()虚方法.这个方法的参数是一个指向线程进入点函数的指针,以及一个必须传入的void*类型的指针参数.在大多数情况下,你将执行你的特殊的启动代码,然后调用通过参数传入的进入点函数.

    例如:

class MyThreadHook: public ACE_Thread_Hook
     {
       public:
         virtual ACE_THR_FUNC_RETURN start(ACE_THR_FUNC func, void* arg)
         {
           ACE_DEBUG( (LM_DEBUG, ACE_TEXT("(%t) New thread spawned\n")) );
           //create the context on the thread's own stack;
           ACE_TSS<SecurityContext> secCtx;
           //special initialization
           add_sec_context_thr(secCtx);
           //call the thread-function
           return (*func)(args);
         }
         void add_sec_context_thr(ACE_TSS<SecurityContext>& secCtx);
     };
     在创建了新的线程启动挂钩对象之后,需要把它设置成新线程的启动挂钩.为此,只需要调用ACE_Thread_Hook::thread_hook()静态方法,把新挂钩的一个实例传递给它;例如:
     int ACE_TMAIN(int argc, ACE_TCHAR** argv)
     {
       MyThreadHook hook;
       ACE_Thread_Hook::thread_hook(&hook);
       MyThread thread;
       thread.active();
       thread.wait();
       return 0;
     };

    线程的取消:
    取消是一种你可以用以消灭(zap)正在运行线程的途径.任何线程退出处理器都不会被调用,线程专有存储空间也不会被释放.你的线程将消失.在某些情况下,取消也是一种"必要的邪恶":为了退出一个长时间运行的、只进行计算的线程,或是终止一个阻塞在阻塞式调用上的线程.在大多数情况下,应用终止时取消线程是有意义的;
    取消有以下几种模式:
    A、延迟取消:
       这种模式下,所有的取消操作都会被延迟到该线程的下一个取消点.取消点是代码中明确定义的点,在这个点上,线程或是已经阻塞,或是用ACE_Thread_Manager::testcancal()方法编写了显式的取消点.这种模式是用ACE构建的应用的默认模式;
    B、协作式取消:
       这种模式下,线程并没有被真正的取消,而是会在派生它们的ACE_Thread_Manager实例中被标记已取消.你可以调用ACE_Thread_Manager::testcalcel()方法来确定线程是否处在已取消状态.如果这样,你可以选择退出线程.这种模式避免了常规取消所带来的大多数讨厌的副作用.如果你想构建可移植的应用,就最好坚持使用这种取消模式;    
    C、异步取消:
       这种模式下,取消操作可以在任意时刻被处理;运行在这种模式下的线程可能会难以管理.你可以把任何线程的取消状态从启用改为禁用,以确保线程不会在执行关键代码时被取消.你还可以使用线程清理处理器,它们将在线程取消时被调用,以确保线程的各不变项在取消过程中得以维持.
    D、禁用取消:
       调用ACE_Thread::disablecancel(),可以完全禁止取消某个线程;    
    ACE_Thread_Manager::cancel_task()方法可以用来取消一个线程;
    下面的方法可以把线程的取消模式设置为异步取消模式:
    cancel_state new_state;
    new_state.cancelstate = PTHREAD_CANCEL_ENABLE;
    new_state.canceltype  = PTHREAD_CANCEL_ASYNCHRONOUS;
    ACE_Thread::setcancelstate(new_state, 0);

关于ACE_At_Thread_Exit类的例子:

#include "ace/Log_Msg.h"
 #include "ace/OS.h"
 #include "ace/Thread.h"
 #include "ace/Task.h"class ExitHandler: public ACE_At_Thread_Exit
 {
  virtual void apply(void)
  {
   ACE_DEBUG( (LM_INFO, ACE_TEXT("ExitHandler::apply()-->thread %t do exiting ...\n")) );
  }
 };//class CommandHandler: public ACE_Task<ACE_SYNCH>
 class CommandHandler: public ACE_Task_Base
 {
   private:
   static int nThreadNum;
   ExitHandler& m_oExitHandler; public:
   CommandHandler(ExitHandler& exit): m_oExitHandler(exit)
   {}  virtual int svc(void)
   {
    int nThreadID = 0;
    int i = 0;this->thr_mgr()->at_exit(this->m_oExitHandler);
   nThreadNum++;
    nThreadID = nThreadNum;
    ACE_DEBUG( (LM_INFO, ACE_TEXT("thread[%t] %d start\n"), nThreadID) );
    ACE_OS::sleep(1);   while(i <= 10)
    {
     ACE_DEBUG( (LM_INFO, ACE_TEXT("thread[%t] %d print %d\n"), nThreadID, i) );
     i++;
     ACE_OS::sleep(1);
    }ACE_Thread::exit(4);
    return nThreadID;
   }
 };int CommandHandler::nThreadNum = 0;
int ACE_TMAIN(int argc, ACE_TCHAR** argv)
 {
  ACE_DEBUG( (LM_INFO, ACE_TEXT("Test Thread from ACE_Task_Base is running ...\n")) ); int nReturn = 0;
  ExitHandler exit;
  CommandHandler cmd(exit);
  ACE_Thread_Manager tm;
  cmd.thr_mgr(&tm); nReturn = cmd.activate(THR_NEW_LWP);
  if(nReturn != 0)
  {
   ACE_DEBUG( (LM_ERROR, ACE_TEXT("failed to active this thread[%d] %p\n"), nReturn, ACE_TEXT("active")) );
   return -1;
  } ACE_OS::sleep(3);
  ACE_DEBUG( (LM_INFO, ACE_TEXT("Suspend this thread ......\n")) );
  cmd.suspend();
  ACE_OS::sleep(3);
  ACE_DEBUG( (LM_INFO, ACE_TEXT("Resume this thread ......\n")) );
  cmd.resume();
  tm.wait();
  //ACE_Thread_Manager::instance()->wait();
  getchar();
  return 0;
 }

有两种方法等待子线程的退出:
1、使用ACE_Thread_Manager类的一个单件实例来等待所有子线程退出(见蓝色代码);
   如:
   ACE_Thread_Manager::instance()->wait();
2、可以自定义一个ACE_Thread_Manager类的对象,并把这个对象通过ACE_Task_Base::thr_mgr()方法关联到一个线程对象上,以等待这个线程退出(见红色代码);
   如:

ACE_Thread_Manager tm;
    ACE_Task_Base::thr_mgr(&tm);
    tm.wait();

关于ACE_Thread_Hook类的例子:

#include "ace/Log_Msg.h"
 #include "ace/OS.h"
 #include "ace/Thread.h"
 #include "ace/Task.h"
 #include "ace/Sig_Handler.h"
 #include "ace/Thread_Hook.h"class MyThreadHook: public ACE_Thread_Hook
 {
  public:
   virtual ACE_THR_FUNC_RETURN start(ACE_THR_FUNC func, void* arg)
   {
    ACE_DEBUG( (LM_INFO, ACE_TEXT("%t: execute new thread hook\n")) );
    return (*func)(arg);
   }
 };class ExitHandler: public ACE_At_Thread_Exit
 {
  virtual void apply(void)
  {
   ACE_DEBUG( (LM_INFO, ACE_TEXT("ExitHandler::apply()-->thread %t do exiting ...\n")) );
  }
 };class CommandHandler: public ACE_Task<ACE_SYNCH>
 //class CommandHandler: public ACE_Task_Base
 {
   private:
   static int nThreadNum;
   ExitHandler& m_oExitHandler; public:
   CommandHandler(ExitHandler& exit): m_oExitHandler(exit)
   {}  virtual int handle_signal(int signum, siginfo_t* siginfo, ucontext_t* cont)
   {
    if(signum == SIGUSR1)
    {
     ACE_DEBUG( (LM_INFO, ACE_TEXT("thread %t recv sig %S\n")) );
    }
    return 0;
   }  virtual int svc(void)
   {
    int nThreadID = 0;
    int i = 0;   this->thr_mgr()->at_exit(this->m_oExitHandler);
   nThreadNum++;
    nThreadID = nThreadNum;
    ACE_DEBUG( (LM_INFO, ACE_TEXT("thread[%t] %d start\n"), nThreadID) );
    ACE_OS::sleep(1);   while(i <= 10)
    {
     ACE_DEBUG( (LM_INFO, ACE_TEXT("thread[%t] %d print %d\n"), nThreadID, i) );
     i++;
     ACE_OS::sleep(1);
    }   ACE_OS::sleep(10);
    ACE_Thread::exit();
    return nThreadID;
   }
 };int CommandHandler::nThreadNum = 0;
int ACE_TMAIN(int argc, ACE_TCHAR** argv)
 {
  ACE_DEBUG( (LM_INFO, ACE_TEXT("Test Thread from ACE_Task_Base is running ...\n")) ); int nReturn = 0;
 ExitHandler exit;
  CommandHandler cmd(exit);
  ACE_Thread_Manager tm;
  cmd.thr_mgr(&tm); ACE_Sig_Handler sh;
  sh.register_handler(SIGUSR1, &cmd); //set thread start hook
  MyThreadHook hook;
  ACE_Thread_Hook::thread_hook(&hook); nReturn = cmd.activate(THR_NEW_LWP);
  if(nReturn != 0)
  {
   ACE_DEBUG( (LM_ERROR, ACE_TEXT("failed to active this thread[%d] %p\n"), nReturn, ACE_TEXT("active")) );
   return -1;
  } ACE_OS::sleep(3);
  ACE_DEBUG( (LM_INFO, ACE_TEXT("Suspend this thread ......\n")) );
  cmd.suspend();
  ACE_OS::sleep(3);
  ACE_DEBUG( (LM_INFO, ACE_TEXT("Resume this thread ......\n")) );
  cmd.resume(); ACE_Thread_Manager::instance()->kill_grp(cmd.grp_id(), SIGUSR1);
 tm.wait();
  ACE_Thread_Manager::instance()->wait();
  getchar();
  return 0;
 }

关于ACE_Thread类的例子:

#include "ace/Log_Msg.h"
 #include "ace/Thread.h"
 #include "ace/Thread_Manager.h"
 #include "ace/OS.h"const int THRD_NUM = 3;
struct thread_param
 {
  int nIdxThrd;
 };ACE_THR_FUNC_RETURN MyThrdFunc(void* param)
 {
  int i = 0, nThrdIdx = 0;
  thread_param* lpParam = NULL; if(param)
  {
   lpParam = (thread_param*)param;
   nThrdIdx = lpParam->nIdxThrd;
  } ACE_DEBUG( (LM_INFO, ACE_TEXT("thread MyThrdFunc[%d] start\n"), nThrdIdx) );
  while(i <= 10)
  {
   ACE_OS::sleep(1);
   ACE_DEBUG( (LM_INFO, ACE_TEXT("thread MyThrdFunc[%d] is run %d\n"), nThrdIdx, i) );
   i++;
  }
  ACE_DEBUG( (LM_INFO, ACE_TEXT("thread MyThrdFunc[%d] exit\n"), nThrdIdx) );
  //ACE_Thread::exit((ACE_THR_FUNC_RETURN)nThrdIdx);
  return (ACE_THR_FUNC_RETURN)nThrdIdx;
 }ACE_THR_FUNC_RETURN MyThrdFunc2(void* param)
 {
  int i = 0; ACE_DEBUG( (LM_INFO, ACE_TEXT("thread MyThrdFunc[%t] start\n")) );
  while(i <= 10)
  {
   ACE_OS::sleep(1);
   ACE_DEBUG( (LM_INFO, ACE_TEXT("thread MyThrdFunc is run %d\n"), i) );
  }
  ACE_DEBUG( (LM_INFO, ACE_TEXT("thread MyThrdFunc[%t] exit")) );
  return 0;
 }int ACE_TMAIN(int argc, ACE_TCHAR** argv)
 {
  int nReturn = 0, i = 0;
  ACE_thread_t tids[THRD_NUM];
  ACE_hthread_t htids[THRD_NUM];
  ACE_THR_FUNC_RETURN thrdExitCode = 0;
  thread_param astThrdParam[THRD_NUM]; ACE_OS::memset(tids, 0, sizeof(tids));
  for(i = 0; i < THRD_NUM; i++)
  {
   astThrdParam[i].nIdxThrd = i;
   nReturn = ACE_Thread::spawn((ACE_THR_FUNC)MyThrdFunc, (void*)&astThrdParam[i], THR_NEW_LWP|THR_JOINABLE, &tids[i], &htids[i]);
  } ACE_OS::sleep(3);
  ACE_Thread::suspend(htids[2]);
  ACE_Thread::suspend(htids[1]);
  ACE_DEBUG( (LM_DEBUG, ACE_TEXT("thread 2 supended\n")) );
  ACE_DEBUG( (LM_DEBUG, ACE_TEXT("thread 1 supended\n")) ); ACE_OS::sleep(3);
  ACE_Thread::resume(htids[1]);
  ACE_DEBUG( (LM_DEBUG, ACE_TEXT("thread 1 resume\n")) );
  ACE_Thread::resume(htids[2]);
  ACE_DEBUG( (LM_DEBUG, ACE_TEXT("thread 2 resume\n")) ); getchar();
 for(i = 0; i < THRD_NUM; i++)
  {
   ACE_Thread::join(tids[i], NULL, &thrdExitCode);
   ACE_DEBUG( (LM_DEBUG, ACE_TEXT("thread %d exit with code %d\n"), i, thrdExitCode) );
  }
  ACE_Thread_Manager::instance()->wait();
  getchar();
  return 0;
 }

关于ACE_Thread类的例子2:

#include "ace/Log_Msg.h"
 #include "ace/Thread.h"
 #include "ace/Thread_Manager.h"
 #include "ace/OS.h"const int THRD_NUM = 3;
struct thread_param
 {
  int nIdxThrd;
 };ACE_THR_FUNC_RETURN MyThrdFunc(void* param)
 {
  int i = 0; ACE_DEBUG( (LM_INFO, ACE_TEXT("thread MyThrdFunc[%t] start\n")) );
  while(i <= 10)
  {
   ACE_OS::sleep(1);
   ACE_DEBUG( (LM_INFO, ACE_TEXT("thread MyThrdFunc[%t] is run %d\n"), i) );
   i++;
  }
  ACE_DEBUG( (LM_INFO, ACE_TEXT("thread MyThrdFunc[%t] exit\n")) );
  return 0;
 }int ACE_TMAIN(int argc, ACE_TCHAR** argv)
 {
  size_t spawnRet = 0;
  ACE_thread_t tids[THRD_NUM];
  ACE_hthread_t htids[THRD_NUM];
  ACE_THR_FUNC_RETURN thrdExitCode = 0;
  thread_param astThrdParam[THRD_NUM]; spawnRet = ACE_Thread::spawn_n((size_t)THRD_NUM, (ACE_THR_FUNC)MyThrdFunc);
  spawnRet = ACE_Thread::spawn_n(tids, (size_t)THRD_NUM, (ACE_THR_FUNC)MyThrdFunc, NULL, THR_NEW_LWP|THR_JOINABLE); ACE_Thread_Manager::instance()->wait();
  getchar();
  return 0;
 }

关于ACE_Thread_Manager类的例子:

#include "ace/Log_Msg.h"
 #include "ace/Thread.h"
 #include "ace/Thread_Manager.h"
 #include "ace/OS.h"const int THRD_NUM = 3;
struct thread_param
 {
  int nIdxThrd;
 };ACE_THR_FUNC_RETURN MyThrdFunc(void* param)
 {
  int i = 0; ACE_DEBUG( (LM_INFO, ACE_TEXT("thread MyThrdFunc[%t] start\n")) );
  while(i <= 10)
  {
   ACE_OS::sleep(1);
   ACE_DEBUG( (LM_INFO, ACE_TEXT("thread MyThrdFunc[%t] is run %d\n"), i) );
   i++;
  }
  ACE_DEBUG( (LM_INFO, ACE_TEXT("thread MyThrdFunc[%t] exit\n")) );
  return 0;
 }int ACE_TMAIN(int argc, ACE_TCHAR** argv)
 {
  int nReturn = 0;
  size_t spawnRet = 0;
  ACE_thread_t tids[THRD_NUM]; ACE_Thread_Manager* lpThrdMgr = ACE_Thread_Manager::instance();
  nReturn  = lpThrdMgr->spawn((ACE_THR_FUNC)MyThrdFunc);
  spawnRet = lpThrdMgr->spawn_n((size_t)THRD_NUM, (ACE_THR_FUNC)MyThrdFunc);
  spawnRet = lpThrdMgr->spawn_n(tids, (size_t)THRD_NUM, (ACE_THR_FUNC)MyThrdFunc, NULL, THR_NEW_LWP|THR_JOINABLE);
  lpThrdMgr->wait();
  getchar();
  return 0;
 }