修改ACE的Reactor模式示例中的参数后测试,依据测试结果,猜测Reactor似乎可以突破62个事件的限制。但是...

45 篇文章 0 订阅
38 篇文章 0 订阅

修改ACE的Reactor模式示例中的参数后测试,依据测试结果,猜测Reactor似乎可以突破62个事件的限制。但当事件蜂拥而上时,Reactor会由于应对不及,而出现事件漏掉的现象。

下面是在 ACE 6.0.0 提供的示例 Reactors_Test  的部分源代码 (在 \ACE-6.0.0\ACE_wrappers\tests\ 目录下)。

Reactors_Test.cpp 文件部分内容:

#if defined (ACE_HAS_THREADS)

ACE_Thread_Manager *thr_mgr;

static const int MAX_TASKS = 20;
...

int
Test_Task::svc (void) 
{
  ACE_DEBUG ((LM_DEBUG,
              ACE_TEXT ("(%t) svc\n")));

  for (size_t i = 0; i < ACE_MAX_ITERATIONS; i++)
    {
      ACE_OS::thr_yield ();

      // Only wait up to 10 milliseconds to notify the Reactor.
      ACE_Time_Value timeout (0, 10 * 1000); 

      if (this->reactor ()->notify (this,
                                    ACE_Event_Handler::READ_MASK,
                                    &timeout) == -1)
        {
          if (errno == ETIME)
            ACE_DEBUG ((LM_DEBUG,
                        ACE_TEXT ("(%t) %p\n"),
                        ACE_TEXT ("notify() timed out")));
          else
            ACE_ERROR_RETURN ((LM_ERROR,
                               ACE_TEXT ("(%t) %p\n"),
                               ACE_TEXT ("notify")),
                              -1);
        }
  }

  return 0;
}

int
Test_Task::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
{
  return 0;
}

int
Test_Task::handle_input (ACE_HANDLE) 
{
  this->handled_++;

  if (this->handled_ == ACE_MAX_ITERATIONS)
    {
      done_count--;
      ACE_DEBUG ((LM_DEBUG,
                  ACE_TEXT ("(%t) handle_input, handled_ = %d, done_count = %d\n"),
                  this->handled_,
                  done_count.value ()));
    }

  ACE_OS::thr_yield ();
  return -1;
}

static void *
worker (void *args)
{
  ACE_Reactor *reactor = reinterpret_cast<ACE_Reactor *> (args);

  // Make this thread the owner of the Reactor's event loop.
  reactor->owner (ACE_Thread::self ());

  // Use a timeout to inform the Reactor when to shutdown.
  ACE_Time_Value timeout (4);

  for (;;)
    switch (reactor->handle_events(timeout))  
      {
      case -1:
        ACE_ERROR_RETURN ((LM_ERROR,
                           ACE_TEXT ("(%t) %p\n"),
                           ACE_TEXT ("reactor")),
                          0);
        /* NOTREACHED */
      case 0:
        ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Reactor shutdown\n")));
        return 0;
      }

  ACE_NOTREACHED (return 0);
}

#endif /* ACE_HAS_THREADS */

int
run_main (int, ACE_TCHAR *[])
{
  ACE_START_TEST (ACE_TEXT ("Reactors_Test"));

#if defined (ACE_HAS_THREADS)
  ACE_ASSERT (ACE_LOG_MSG->op_status () != -1);

  thr_mgr = ACE_Thread_Manager::instance ();

  ACE_Reactor reactor;
  ACE_ASSERT (ACE_LOG_MSG->op_status () != -1);

  Test_Task tt1[MAX_TASKS];
  Test_Task tt2[MAX_TASKS];

  // Activate all of the Tasks.

  for (int i = 0; i < MAX_TASKS; i++)
    {
      tt1[i].open (ACE_Reactor::instance ());  
      tt2[i].open (&reactor); 
    }

  // Spawn two threads each running a different reactor.

  if (ACE_Thread_Manager::instance ()->spawn
      (ACE_THR_FUNC (worker),
       (void *) ACE_Reactor::instance (),
       THR_BOUND | THR_DETACHED) == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       ACE_TEXT ("%p\n"),
                       ACE_TEXT ("spawn")),
                      -1);

  else if (ACE_Thread_Manager::instance ()->spawn
      (ACE_THR_FUNC (worker), (void *) &reactor,
       THR_BOUND | THR_DETACHED) == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       ACE_TEXT ("%p\n"),
                       ACE_TEXT ("spawn")),
                      -1);

  if (ACE_Thread_Manager::instance ()->wait () == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       ACE_TEXT ("%p\n"),
                       ACE_TEXT ("wait")),
                      -1);

  ACE_DEBUG ((LM_DEBUG,
              ACE_TEXT ("(%t) all threads are finished\n")));

#else
  ACE_ERROR ((LM_INFO,
              ACE_TEXT ("threads not supported on this platform\n")));
#endif /* ACE_HAS_THREADS */

  ACE_END_TEST;

  return 0;
}



test_config.h文件(在 \ACE-6.0.0\ACE_wrappers\tests\ 目录下)部分内容:

#ifndef ACE_TEST_CONFIG_H
#define ACE_TEST_CONFIG_H

...

size_t const ACE_NS_MAX_ENTRIES = 1000;
size_t const ACE_DEFAULT_USECS = 1000;
size_t const ACE_MAX_TIMERS = 4;
size_t const ACE_MAX_DELAY = 10;
size_t const ACE_MAX_INTERVAL = 0;
size_t const ACE_MAX_ITERATIONS = 10;
size_t const ACE_MAX_PROCESSES = 10;
size_t const ACE_MAX_THREADS = 4;

...

#endif /* ACE_TEST_CONFIG_H */


搭配修改下面三个参数测试:

1. MAX_TASKS

2. timeout        (在Test_Task::svc  函数里)

3. ACE_MAX_ITERATIONS

三个参数的原值:

static const int MAX_TASKS = 20;

ACE_Time_Value timeout (0, 10 * 1000); 

size_t const ACE_MAX_ITERATIONS = 10;

如果把 MAX_TASKS值设成大于62(比如 100),即把每个Reactor(示例中有两个Reactor)的事件数设置超过62个,如下:

 static const int MAX_TASKS = 100;

这样,如果 timeout 和 ACE_MAX_ITERATIONS 两个参数值搭配设置不当,在日志文件Reactors_Test.log(在\ACE-6.0.0\ACE_wrappers\tests\log目录下)中就会出现有事件漏掉的提示,如下:

LM_ERROR@(13432) notify: Resource temporarily unavailable

但如果搭配设置恰当,就没有这样的提示。

另外,跟踪调试发现,Reactor在相应事件时调用了ACE_WFMO_Reactor::poll_remaining_handles 函数(在\ACE-6.0.0\ACE_wrappers\ace\WFMO_Reactor.cpp文件中):

DWORD
ACE_WFMO_Reactor::poll_remaining_handles (DWORD slot)
{
  return ::WaitForMultipleObjects (this->handler_rep_.max_handlep1 () - slot,
                                   this->handler_rep_.handles () + slot,
                                   FALSE,
                                   0);
}


看函数字面意思是“响应余下的事件句柄”之意。

综上是否可猜测:

Reactor可以突破62个事件的限制,分批(最多62个一批)监视事件,但当事件蜂拥而上时,Reactor会由于应对不及,而出现事件漏掉的现象。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值