操作系统现有的API
linux的定时器:
1. 基于信号的setitimer系列
----- 信号是进程域,对于同一种信号,只能有一个处理函数;如果别的模块也扑捉同一种信号,那么后面设置的信号处理会覆盖前面的处理方法。
2. 基于文件描述符的timer_create系列
----- 稍显复杂;而且会"消耗"文件描述符,这不适合于文件描述符需求大且系统文件描述符不足的情景。
windows的定时器:
1. 基于消息机制的SetTimer系列
----- 此消息的响应优先级很低,意味着精度可能不行;感觉底层库用这个来实现也不适合。
2. timeSetEvent系列
----- 没用过,听说不用多线程;但是只在xp上才有这个。
所以,还是考虑用多线程来轮询:
采用的是nanosleep+gettimeofday / Sleep+GetLocalTime来控制精度,理想精度为1ms
因为针对每个定时器(定时任务)都涉及到增加、删除、开启、停止操作,所以,感觉用最小堆来做不合适(删除、开启、停止指定任务不方便),至于时间轮方式,则是没想通怎么来定义这个结构与轮询过程,所以目前采用的数据结构是有序链表
文中所谓精度,都是在任务"不"耗时的前提下才可能好的了的
class TimerManager : public BaseUncopy
{
public:
TimerManager();
~TimerManager();
public:
bool init();
void exit();
public:
template <typename T, typename F, typename P>
size_t create_timer_mem(T & t, F f, const P & p);
template <typename T, typename F>
size_t create_timer_mem(T & t, F f);
template <typename F, typename P>
size_t create_timer_ptr(F f, P p);
template <typename F>
size_t create_timer_ptr(F f);
void destroy_timer(size_t id);
bool start_timer(size_t id, bool once, size_t period);
bool stop_timer(size_t id);
};
测试代码:
class Test
{
public:
void test() const
{
std::cout << "void Test::test(void) const" << std::endl;
}
void test(int) volatile
{
std::cout << "void Test::test(int)" << std::endl;
}
};
void test(void)
{
std::cout << "void test(void)" << std::endl;
}
void test(int)
{
std::cout << "void test(int)" << std::endl;
}
struct TEST
{
void operator () (void) const
{
std::cout << "void TEST::operator () (void) const" << std::endl;
}
void operator () (int)
{
std::cout << "void TEST::operator () (int)" << std::endl;
}
};
void test_base_timer_manager(void)
{
TimerManager timer_manager;
if (!timer_manager.init())
{
printf("timer manager init failed\n");
return;
}
void (*ptr1) (void) = test;
void (*ptr2) (int) = test;
void (Test::*mem1) (void) const = &Test::test;
void (Test::*mem2) (int) volatile = &Test::test;
Test t;
TEST f;
size_t id1 = timer_manager.create_timer_ptr(ptr1);
size_t id2 = timer_manager.create_timer_ptr(ptr2, 0);
size_t id3 = timer_manager.create_timer_mem(t, mem1);
size_t id4 = timer_manager.create_timer_mem(t, mem2, 0);
size_t id5 = timer_manager.create_timer_ptr(f);
size_t id6 = timer_manager.create_timer_ptr(f, 0);
timer_manager.start_timer(id1, false, 200);
timer_manager.start_timer(id2, false, 300);
timer_manager.start_timer(id3, false, 400);
timer_manager.start_timer(id4, false, 600);
timer_manager.start_timer(id5, false, 1200);
timer_manager.start_timer(id6, false, 2400);
printf("sleep 5000ms begin...\n");
base_millisecond_sleep(5000);
printf("sleep 5000ms end...\n");
timer_manager.stop_timer(id1);
timer_manager.stop_timer(id2);
timer_manager.stop_timer(id3);
timer_manager.stop_timer(id4);
timer_manager.stop_timer(id5);
timer_manager.stop_timer(id6);
printf("sleep 1000ms begin...\n");
base_millisecond_sleep(1000);
printf("sleep 1000ms end...\n");
timer_manager.exit();
}
其中:
printf("sleep 1000ms begin...\n");
base_millisecond_sleep(1000);
printf("sleep 1000ms end...\n");
目的是查看stop_timer之后是否还有任务在执行(看打印而不是stop_timer返回值,只是因为这样更方便看到效果)
参考资料:
http://www.ibm.com/developerworks/cn/linux/l-cn-timers/index.html