peakzhang 发表于 2007-12-22 21:40:53

Reactor事件的问题!

我把ACE_Reactor::instance()->run_reactor_event_loop();放在我的主线程中,我的定时器就正常!
如果我把ACE_Reactor::instance()->run_reactor_event_loop();放在子线程中,为什么我的定时器就不起作用了呢?
定时器也不会出错!!!

peakzhang 发表于 2007-12-22 21:41:23

//
// 这是测试代码!
//
#include
#include
#include "ace/Task_T.h"
#include "ace/Reactor.h"
#include "ace/Event_Handler.h"

class A : public ACE_Task
{
public:
int svc(void)
{
while(ACE_Reactor::instance()->reactor_event_loop_done() == 0)
   ACE_Reactor::instance()->run_reactor_event_loop();

return 0;
}

int stop(void)
{
ACE_Reactor::instance()->end_reactor_event_loop();
return 0;
}

int start(int nThread = 1)
{
this->activate(THR_NEW_LWP|THR_JOINABLE|THR_INHERIT_SCHED, nThread);
return 0;
}


};

class B : public ACE_Event_Handler
{
public:
   virtual int handle_timeout (const ACE_Time_Value ¤t_time,
                              const void *act = 0)
   {
    ACE_DEBUG((LM_DEBUG, "..................\n"));
    return 0;
   }
};

int ACE_TMAIN(int argc, ACE_TCHAR *argv[])
{
A a;
B b;
a.start();

ACE_Time_Value const timeout(3);
if (ACE_Reactor::instance()->schedule_timer(&b, 0, timeout, timeout) == -1)
ACE_ERROR((LM_ERROR, ACE_TEXT("(%t) %p\n"), ACE_TEXT("schedule_timer")));


a.wait();// 用这个,定时器就无效!
//ACE_Reactor::instance()->run_reactor_event_loop();// 用这个没有问题!正常!
return 0;
}

peakzhang 发表于 2007-12-22 21:41:33

修改你的

int A::svc(void),增加

ACE_Reactor::instance()->owner(ACE_OS::self());

peakzhang 发表于 2007-12-22 21:42:00

补上完整的测试代码,VC2005/xp下通过
/**
test.cpp
Stone jiang
*/

#include "ace/OS_NS_time.h"
#include "ace/Log_Msg.h"
#include "ace/Reactor.h"
#include "ace/Event_Handler.h"
#include "ace/Task.h"
#include "ace/Thread_Manager.h"
#include "ace/TP_Reactor.h"
#include "ace/WFMO_Reactor.h"

class MyTimerHandler : public ACE_Event_Handler
{
public:
    int handle_timeout (const ACE_Time_Value ¤t_time,
      const void * = 0)
    {
      time_t epoch = ((timespec_t)current_time).tv_sec;

      ACE_DEBUG ((LM_INFO,
            ACE_TEXT ("(%t) handle_timeout: %s\n"),
            ACE_OS::ctime (&epoch)));

      return 0;
    }
};

class SigintHandler : public ACE_Event_Handler
{
public:
    int handle_signal (int signum, siginfo_t * = 0,
      ucontext_t * = 0)
    {
      if (signum == SIGINT)
      {
            ACE_Reactor::instance ()->end_reactor_event_loop ();
      }
      return 0;
    }
};

class ReactorThread :public ACE_Task
{
public:
    ReactorThread(void* r)
    {
      reactor_ = (ACE_Reactor*) r;

      ACE_DEBUG ((LM_INFO,
            ACE_TEXT ("ReactorThread::ReactorThread()\n")));
      this->activate(THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED,3);
    }
    virtual int svc()
    {
      ACE_DEBUG ((LM_INFO,
            ACE_TEXT (" (%t) ReactorThread::svc()\n")));
         reactor_->owner (ACE_OS::thr_self ());
         reactor_->run_reactor_event_loop();
         return 0;
    }

private:
   ACE_Reactor* reactor_;

};
int ACE_TMAIN (int, ACE_TCHAR *[])
{
      
    ACE_DEBUG ((LM_INFO,
      ACE_TEXT ("(%t) main::start \n")));

    ACE_WFMO_Reactor this_reactor;
    ACE_Reactor reactor (&this_reactor);
    auto_ptr delete_instance
    (ACE_Reactor::instance (&reactor));

    ReactorThread thread(ACE_Reactor::instance());
    MyTimerHandler * timer = new MyTimerHandler ();
    ACE_Time_Value initialDelay (1);
    ACE_Time_Value interval (2);
    ACE_Reactor::instance()->schedule_timer (timer,
      0,
      initialDelay,
      interval);
   
    SigintHandler * handleExit = new SigintHandler ();
    ACE_Reactor::instance()->register_handler (SIGINT,
      handleExit);

thread.wait();

    ACE_DEBUG ((LM_INFO,
      ACE_TEXT ("main::exit \n")));
    return 0;
}

peakzhang 发表于 2007-12-22 21:42:15

stone正解,测试了一下,的确如此。
svc改成:
while(ACE_Reactor::instance()->reactor_event_loop_done() == 0)
{
   ACE_Reactor::instance()->owner(ACE_OS::thr_self ());
   ACE_Reactor::instance()->run_reactor_event_loop();
}
即完全正常。

原因是:
set the owner of the reactor to the identity of the thread that runs the event loop

peakzhang 发表于 2007-12-22 21:42:52

The thread which is "owner" of the WFMO_Reactor. The owner
concept is used because we don't want multiple threads to try to
expire timers. Therefore the "owner" thread is the only one
allowed to expire timers. Also, the owner thread is the only
thread which waits on the notify handle. Note that the ownership
can be transferred.
页: [1]
查看完整版本: Reactor事件的问题!