ACE默认的时钟实现依赖操作系统时钟(ACE_OS::gettimeofday),例如改小系统时间会造成时钟触发延时。该问题可通过修改timer_queue的gettimeofday函数来解决。
网上提及的一种办法是使用ACE_High_Res_Timer::gettimeofday_hr替换ACE_OS::gettimeofday,测试发现该方法在Windows XP上可用,在SUSE10上仍然不行;跟踪发现SUSE10上ACE_High_Res_Timer::gettimeofday_hr调用了::clock_gettime(),clockid为CLOCK_REALTIME——这样仍然会依赖OS时间。使用CLOCK_MONOTONIC调用::clock_gettime(),可得到不依赖OS时间的值,而这需要增加ACE的编译宏ACE_HAS_CLOCK_GETTIME_MONOTONIC(可以在config.h中增加定义)
另一个方法是自己实现一个替代函数,下面的getTime是一个例子:
#include <iostream>
#include <fstream>
#include <string>
#include <unistd.h>
#include <stdio.h>
#include "ace/Timer_Queue_Adapters.h"
#include "ace/Event_Handler.h"
#include "ace/Timer_Wheel.h"
#include "ace/reactor.h"
#include "ace/High_Res_Timer.h"
using namespace std;
ACE_Thread_Timer_Queue_Adapter<ACE_Timer_Wheel> active_timer_ ;
class CHandler: public ACE_Event_Handler
{
public:
virtual int handle_timeout (const ACE_Time_Value ¤t_time, const void *act)
{
cout<< "time out "<< endl;
return 0;
}
};
ACE_Time_Value getTime()
{
ifstream f("/proc/uptime");
string str;
f >> str;
string substr = str.substr(0, str.find("."));
string substr1 = str.substr(str.find(".")+1, 2);
int i = atoi(substr.c_str());
cout<<substr<<" "<<substr1<<endl;
return ACE_Time_Value(i, atoi(substr1.c_str())*10*1000);
}
void startTimer()
{
static CHandler hdl;
active_timer_.timer_queue()->gettimeofday(getTime);
const ACE_Time_Value curr_tv = getTime();
//active_timer_.timer_queue()->gettimeofday(ACE_High_Res_Timer::gettimeofday_hr);
//const ACE_Time_Value curr_tv = ACE_High_Res_Timer::gettimeofday_hr();
long timerID = active_timer_.schedule(&hdl, 0, curr_tv + ACE_Time_Value(1), ACE_Time_Value(1));
if(timerID < 0)
{
cout<<"schedule time failed"<<endl;
}
active_timer_.activate();
}
int main()
{
//ACE_High_Res_Timer::global_scale_factor();
startTimer();
for(;;)
{
sleep(7);
}
}
网上提及的一种办法是使用ACE_High_Res_Timer::gettimeofday_hr替换ACE_OS::gettimeofday,测试发现该方法在Windows XP上可用,在SUSE10上仍然不行;跟踪发现SUSE10上ACE_High_Res_Timer::gettimeofday_hr调用了::clock_gettime(),clockid为CLOCK_REALTIME——这样仍然会依赖OS时间。使用CLOCK_MONOTONIC调用::clock_gettime(),可得到不依赖OS时间的值,而这需要增加ACE的编译宏ACE_HAS_CLOCK_GETTIME_MONOTONIC(可以在config.h中增加定义)
另一个方法是自己实现一个替代函数,下面的getTime是一个例子:
#include <iostream>
#include <fstream>
#include <string>
#include <unistd.h>
#include <stdio.h>
#include "ace/Timer_Queue_Adapters.h"
#include "ace/Event_Handler.h"
#include "ace/Timer_Wheel.h"
#include "ace/reactor.h"
#include "ace/High_Res_Timer.h"
using namespace std;
ACE_Thread_Timer_Queue_Adapter<ACE_Timer_Wheel> active_timer_ ;
class CHandler: public ACE_Event_Handler
{
public:
virtual int handle_timeout (const ACE_Time_Value ¤t_time, const void *act)
{
cout<< "time out "<< endl;
return 0;
}
};
ACE_Time_Value getTime()
{
ifstream f("/proc/uptime");
string str;
f >> str;
string substr = str.substr(0, str.find("."));
string substr1 = str.substr(str.find(".")+1, 2);
int i = atoi(substr.c_str());
cout<<substr<<" "<<substr1<<endl;
return ACE_Time_Value(i, atoi(substr1.c_str())*10*1000);
}
void startTimer()
{
static CHandler hdl;
active_timer_.timer_queue()->gettimeofday(getTime);
const ACE_Time_Value curr_tv = getTime();
//active_timer_.timer_queue()->gettimeofday(ACE_High_Res_Timer::gettimeofday_hr);
//const ACE_Time_Value curr_tv = ACE_High_Res_Timer::gettimeofday_hr();
long timerID = active_timer_.schedule(&hdl, 0, curr_tv + ACE_Time_Value(1), ACE_Time_Value(1));
if(timerID < 0)
{
cout<<"schedule time failed"<<endl;
}
active_timer_.activate();
}
int main()
{
//ACE_High_Res_Timer::global_scale_factor();
startTimer();
for(;;)
{
sleep(7);
}
}