在C++线程内实现多个计时器的最安全方法
Safest way to implement multiple timers inside a thread in C++
正如标题所说,我正在寻找在C++(不是c ++ 11(中实现多个计时器的最佳方法。 我的想法是有一个线程(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;
请将这些视为想法,而不是实际的工作代码。
你对此有何看法?
如果您的计时器线程只负责计时器,并且最小分辨率为 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)
的性质 - 这里要做什么实际上取决于使用计时器的线程的需求。 也许只需设置一个他们可以读取的变量就足够了,或者这可以触发线程可以侦听的信号。
由于您所有的计时器创建显然都通过单个 API(即,控制代码可以看到所有计时器(,因此您可以完全避免信号或繁忙循环,并保留一个排序的计时器列表(如按截止日期键入的std::map
(,只需使用 (例如(pthread_cond_timedwait
等待条件变量。条件变量互斥锁保护计时器列表。
如果您安排了截止时间早于当前"下一个"计时器的新计时器,则需要唤醒睡眠线程并安排调整后的睡眠(如果不是因为此要求,您可以使用普通usleep
或其他方式(。这一切都发生在与条件变量关联的互斥锁中。
您不必使用条件变量,但它们似乎是最干净的,因为关联的互斥锁自然用于保护计时器列表。您可能也可以在带有sem_timedwait
的 semaphone 之上构建它,但在内部插座、管道或类似的东西上构建select
,但随后您将单独控制对计时器队列的多线程访问。
- Linux的Cpp上的计时器
- 提升 ASIO 无法识别计时器对象
- 提升 asio 并发计时器取消问题与链
- 使用单体计时器的pthread_cond_timedwait有时会比预期晚超时
- 窗口中的微秒计时器
- 计时器是否从另一个线程启动?
- 如何在 c++ 中创建计时器
- C++回调计时器实现
- 在计时器或主线程外部的命令上销毁/替换线程
- 如何制作每秒从 30 乘 1 倒计时的计时器?
- 保留计时器集合(对象与指针)的最佳方法
- 在网络套接字计时器滴答后增加asio短读错误
- 是否可以仅使用标准 c++/c++11 实现不带"sleep"的计时器?
- 在没有NtSetTimerResolution的Windows上提高计时器分辨率(高分辨率)
- 计时器坏了或者其他什么的
- 功能计时器阻止主功能继续
- IO服务重新启动后,Boost最后期限计时器持续触发
- 在C++线程内实现多个计时器的最安全方法
- 在计时器执行过程中使用 c++ KillTimer() 是否安全?
- 从其处理程序或处理程序 dtor 销毁 boost::asio 计时器是否安全?