ACE handle_timeout 事件重入

多线程运行反应器事件时, 注意handle_timeout会重入,单独线程不存在下列问题!

1. 一个timer事件

// test_ace_timer.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "ace/Time_Value.h"
#include "ace/Log_Msg.h"
#include "ace/Synch.h"
#include "ace/Reactor.h"
#include "ace/Event_Handler.h"
#include "ace/Dev_Poll_Reactor.h"
#include "ace/Thread_Manager.h"
#include <ace/Dev_Poll_Reactor.h>
#include "ace/TP_Reactor.h"

long timer10 = 0;
long timer15 = 0;

class Timer_Handler : public ACE_Event_Handler
{
public:
    virtual int handle_timeout(const ACE_Time_Value &current_time, 
        const void *act /* = 0 */)
    {
        const int *num = ACE_static_cast(const int*,act);
        
        ACE_DEBUG((LM_INFO, ACE_TEXT("time: %d  in  --------\n"),num));
        
        int n = 0 ;
        for (int i=0; i < 50000000; i++)
        {
            n++;
        }
        ACE_DEBUG((LM_INFO, ACE_TEXT("time: %d  out ###########\n"),num));
        return 0;
    }
protected:
private:
};

ACE_THR_FUNC_RETURN thread_func(void *arg) 
{
    ACE_TRACE("thread_func(void *)");

    ACE_Reactor::instance()->run_reactor_event_loop();
    
    return 0;
}

int Start()
{
    // Create a reactor from a tp reactor.
    ACE_TP_Reactor reactor_impl;
    ACE_Reactor reactor(&reactor_impl);
    ACE_Reactor::instance(&reactor);

    // Spawn some threads which run the reactor event loop(s)
    ACE_Thread_Manager::instance()->spawn_n(5,     thread_func, 0, THR_NEW_LWP | THR_JOINABLE | THR_SCHED_RR);
    //ACE_Thread_Manager::instance()->spawn_n(1,     thread_func, 0, THR_NEW_LWP | THR_JOINABLE | THR_SCHED_RR);


    Timer_Handler *timer = new Timer_Handler;
    
    ACE_Time_Value time_delay1(0, 10); //10ms
    ACE_Time_Value time_delay2(0, 15); //15ms

    timer10 = ACE_Reactor::instance()->schedule_timer(timer, (void *)&timer10, time_delay1, time_delay1);

    //timer15 = ACE_Reactor::instance()->schedule_timer(timer, (void *)&timer15, time_delay2, time_delay2);
    
    // Let the thread manager wait for all threads
    ACE_Thread_Manager::instance()->wait();


    return 0;
}

int ACE_TMAIN(int argc, ACE_TCHAR *argv[]) 
{
    // Make sure we ignore SIGPIPE.
    
    Start();


    // Parse arguments.
    return 0;
}

 

测试结果: 

time_out事件多次被调用, 此时可以改用一次性超时规避此问题,在启用timer任务时,handle_timeout分别改为调用下面这句。

 

timer10 = ACE_Reactor::instance()->schedule_timer(timer, (void *)&timer10, time_delay1);

 

2.多个timer事件

 每个都注册一次性timer, 下列代码handle_timeout会重入, 若是存在其他共享资源,则有问题。

 避免这样问题,如是多个timer, 可加锁处理。

// test_ace_timer.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "ace/Time_Value.h"
#include "ace/Log_Msg.h"
#include "ace/Synch.h"
#include "ace/Reactor.h"
#include "ace/Event_Handler.h"
#include "ace/Dev_Poll_Reactor.h"
#include "ace/Thread_Manager.h"
#include <ace/Dev_Poll_Reactor.h>
#include "ace/TP_Reactor.h"

class Timer_Handler;

long timer10 = 0;
long timer15 = 0;
ACE_Time_Value time_delay1(0, 10);
ACE_Time_Value time_delay2(0, 15);

Timer_Handler *timer = NULL; 

class Timer_Handler : public ACE_Event_Handler
{
public:
    virtual int handle_timeout(const ACE_Time_Value &current_time, 
        const void *act /* = 0 */)
    {
        const int *num = ACE_static_cast(const int*,act);
        
        ACE_DEBUG((LM_INFO, ACE_TEXT("time: %d  in  --------\n"),*num));
        
        int n = 0 ;
        for (int i=0; i < 50000000; i++)
        {
            n++;
        }
        ACE_DEBUG((LM_INFO, ACE_TEXT("time: %d  out ###########\n"),*num));

        if (*num == timer10)
        {
            timer10 = ACE_Reactor::instance()->schedule_timer(timer, (void *)&timer10, time_delay1);
        }
        else if(*num == timer15)
        {
            timer15 = ACE_Reactor::instance()->schedule_timer(timer, (void *)&timer15, time_delay2);
        }

        return 0;
    }
protected:
private:
};

ACE_THR_FUNC_RETURN thread_func(void *arg) 
{
    ACE_TRACE("thread_func(void *)");

    ACE_Reactor::instance()->run_reactor_event_loop();
    
    return 0;
}

int Start()
{
    // Create a reactor from a tp reactor.
    ACE_TP_Reactor reactor_impl;
    ACE_Reactor reactor(&reactor_impl);
    ACE_Reactor::instance(&reactor);

    // Spawn some threads which run the reactor event loop(s)
    ACE_Thread_Manager::instance()->spawn_n(5,     thread_func, 0, THR_NEW_LWP | THR_JOINABLE | THR_SCHED_RR);
    //ACE_Thread_Manager::instance()->spawn_n(1,     thread_func, 0, THR_NEW_LWP | THR_JOINABLE | THR_SCHED_RR);


    timer = new Timer_Handler;

    timer10 = ACE_Reactor::instance()->schedule_timer(timer, (void *)&timer10, time_delay1);

    timer15 = ACE_Reactor::instance()->schedule_timer(timer, (void *)&timer15, time_delay2);
    
    // Let the thread manager wait for all threads
    ACE_Thread_Manager::instance()->wait();


    return 0;
}

int ACE_TMAIN(int argc, ACE_TCHAR *argv[]) 
{
    // Make sure we ignore SIGPIPE.
    
    Start();


    // Parse arguments.
    return 0;
}

 

测试结果:

 

posted on 2014-08-29 16:25  偏爱省略号  阅读(1536)  评论(0编辑  收藏  举报

导航