Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 如何使用pthreads在*nix系统上实现异步计时器_Multithreading_Unix_Pthreads - Fatal编程技术网

Multithreading 如何使用pthreads在*nix系统上实现异步计时器

Multithreading 如何使用pthreads在*nix系统上实现异步计时器,multithreading,unix,pthreads,Multithreading,Unix,Pthreads,我有两个问题: Q1我可以在单线程应用程序中实现异步计时器吗?也就是说,我想要这样的功能 .... Timer mytimer(5,timeOutHandler) .... //this thread is doing some other task ... and after 5 seconds, the timeOutHandler function is invoked. 就我所知,单线程应用程序无法做到这一点。如果我错了,请纠正我。我不知道是否可以使用select作为解复用器,

我有两个问题:

Q1我可以在单线程应用程序中实现异步计时器吗?也就是说,我想要这样的功能

....
Timer mytimer(5,timeOutHandler)


.... //this thread is doing some other task


...
and after 5 seconds, the timeOutHandler function is invoked.
就我所知,单线程应用程序无法做到这一点。如果我错了,请纠正我。我不知道是否可以使用select作为解复用器,但即使可以使用select,事件循环也需要一个线程?不是吗

我还想知道是否可以使用select实现timernot timeout。 Select仅等待一组文件描述符,但我希望有一个计时器列表,按其过期超时的升序排列,并希望Select告诉我第一个计时器何时过期,依此类推。因此,问题可以归结为异步计时器是否可以使用select/poll或其他事件解复用器实现

问题2现在让我们来看我的第二个问题。这是我的主要问题。 现在我使用一个专用线程来检查超时,也就是说,我有一个最小的timersexpiry时间堆,这个线程一直休眠到第一个计时器过期,然后调用回调。 i、 e代码看起来像这样

锁定互斥锁 检查第一个计时器的时间 condition timed wait等待该时间,如果其他线程插入了到期时间小于第一个计时器condition wait的计时器,则唤醒该线程以解锁锁。 在条件等待结束后,我们拥有锁。因此,解锁它,从堆中移除计时器并调用回调函数。 转到1 我想要这种异步计时器的时间复杂度。据我所见

插入是lgn 到期日为lgn 取消 :这就是让我头晕的原因。问题是,我有一个最小的计时器堆,根据它们的时间,当我插入计时器时,我会得到一个唯一的id。因此,当我需要取消计时器时,我需要提供此计时器id,在堆中搜索此计时器id将在最坏的情况下发生

我错了吗

可以在Olg n中取消吗


请注意一些多线程问题。一旦我得到一些回复,我会详细解释我上一句话的意思。

如果你是windows应用程序,你可以在将来的某个时候触发WM_定时器消息发送给你,即使你的应用程序是单线程的,它也会起作用。但是,计时的准确性不会太高

如果你的应用程序像游戏一样在一个恒定的循环中运行,以60Hz的频率渲染,你只需在循环的每一次中检查是否需要调用触发的事件


如果你希望你的应用程序基本上被中断,你的函数被调用,然后执行返回到原来的位置,那么你可能会运气不佳。

如果你使用的是C,System.Timers.Timer会做你想做的事情。指定计时器到期时调用的事件处理程序方法,该方法可以位于从中调用计时器的类中。请注意,当计时器调用事件处理程序时,它将在一个单独的线程上执行,如果您正在更新用户界面,或使用其SynchronizationObject属性在UI线程上运行它,则需要考虑到这一点。

使用单个线程实现计时器肯定是可能的,而且通常更可取,如果我们可以假设线程将花费大部分时间在select中阻塞

您可以使用signal和SIGALRM来实现POSIX下的功能,但我建议您不要使用Unix信号,因为Unix信号是丑陋的黑客,当signal回调函数运行时,您在它内部安全地做的事情很少,因为它与您的应用程序线程异步运行

您关于使用select的超时来实现计时器功能的想法是很好的——这是一种非常常见的技术,而且效果很好。基本上,您保留了一个按时间戳排序的挂起/即将发生的事件列表,在调用select之前,您从列表中的第一个时间戳中减去当前时间,并将该时间增量作为超时值传递给select。注意:如果时间增量为负数,则传入零作为超时值!选择返回时,将当前时间与列表中第一项的时间进行比较;如果当前时间大于或等于事件时间,请处理计时器事件,从列表开头弹出第一项,然后重复


至于效率,big-O时间将完全取决于用于存储有序计时器列表的数据结构。如果使用优先级队列或类似的有序树类型结构,则所有操作都可以使用Olog N次。您甚至可以更进一步,将事件列表存储在事件ID上的哈希表和按时间戳排序的链表中,这可以为所有操作提供O1次。不过,Olog N可能已经足够有效了,除非您计划一次挂起大量事件。

您在哪个平台上写这篇文章?例如,Windows有一些API调用,允许我们使用单线程应用程序
man pthread_cond_timedwait

man pthread_cond_signal

我有一个计时器。或者你正在尝试编写自己的操作系统?大家好,我在*nix系统上工作,即任何兼容posix的linux、solaris和其他Unice系统。我正在使用pthreads。您在这里介绍的第二个选项实际上是可能的,只是实现起来非常痛苦: