正如标题所说,我正在寻找在C ++中实现多个计时器的最佳方法(而不是c ++ 11)。 我的想法是有一个单一的pthread(posix)来处理定时器。 我需要至少4个定时器,3个周期和1个单发。 最小分辨率应为1秒(最短计时器)和最长分辨率15小时。 所有计时器都应该同时运行。
这些是我想到的不同实现(我不知道它们在线程环境中是最安全的还是最简单的实现):
1)使用itimerspec,sigaction和sigevent结构如下:
static int Tcreate( char *name, timer_t *timerID, int expireMS, int intervalMS )
{
struct sigevent te;
struct itimerspec its;
struct sigaction sa;
int sigNo = SIGRTMIN;
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = app;
sigemptyset(&sa.sa_mask);
if (sigaction(sigNo, &sa, NULL) == -1)
{
perror("sigaction");
}
/* Set and enable alarm */
te.sigev_notify = SIGEV_SIGNAL;
te.sigev_signo = sigNo;
te.sigev_value.sival_ptr = timerID;
timer_create(CLOCK_REALTIME, &te, timerID);
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = intervalMS * 1000000;
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = expireMS * 1000000;
timer_settime(*timerID, 0, &its, NULL);
return 1;
}
2)使用clock()并检查时差,如下所示:
std::clock_t start;
double duration;
start = std::clock();
duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
3)使用这样的计时器:
auto diff = tp - chrono::system_clock::time_point();
cout << "diff:" << chrono::duration_cast<chrono::minutes>(diff).count()
<< " minute(s)" << endl;
Days days = chrono::duration_cast<Days>(diff);
cout << "diff:" << days.count() << " day(s)" << endl;
请将这些视为想法,而不是实际的工作代码。
您对此有何看法?
答案 0 :(得分:0)
由于所有计时器创建显然都是通过单个API(即控制代码可以看到所有计时器),因此您可以完全避免信号或繁忙循环,并保留一个排序的计时器列表(如{{1}按截止日期键入),并使用(例如)pthread_cond_timedwait
等待条件变量。条件变量互斥锁保护定时器列表。
如果您安排一个新的计时器,其截止时间早于当前的&#34;下一个&#34;计时器,您需要唤醒睡眠线程并安排调整后的睡眠(如果不是这个要求,您可以使用普通std::map
或其他)。这一切都发生在与条件变量相关联的互斥锁中。
您不必使用条件变量,但它们似乎是最干净的,因为相关的互斥锁自然用于保护计时器列表。您也可以使用usleep
在一个semaphone上构建它,但是在内部套接字,管道或类似的东西上sem_timedwait
之上构建它,但是你会被单独控制多个 - 对定时器队列的线程访问。
答案 1 :(得分:0)
如果您的计时器线程仅对负责定时器,并且最小分辨率为1秒,并且时间不需要那么精确(即+/- 0.1秒是好的然后,定时器线程的一个简单实现是只睡1秒,检查需要触发的任何定时器,并重复,如下面的伪代码:
repeat:
sleep 1
t = t+1
for timer in timers where timer(t) = true:
fire(timer)
硬件将填充存储定时器的结构 - 可能是定时器将由其他线程设置,可能由多个线程设置,可能尝试同时设置定时器。建议使用一些标准数据结构(如线程安全队列)将消息传递给定时器线程,然后在每个循环中更新定时器集合本身:
repeat:
sleep 1
t = t+1
while new_timer_spec = pop(timer_queue):
add_timer(new_timer_spec)
for timer in timers where timer(t) = true:
fire(timer)
要考虑的另一件事是fire(timer)
的本质 - 这里要做的事情真的取决于使用定时器的线程的需求。也许只是设置一个他们可以读取的变量就足够了,或者这可能会激发线程可以监听的信号。