我正在尝试将一个使用信号量的项目(从 Linux)移植到 Mac OS X,但是某些 posix 信号量在 Mac OS X 上并未实现
我在此端口中遇到的一个是 sem_timedwait()
我对信号量了解不多,但从手册页 sem_wait()
似乎接近 sem_timedwait
并且它是
从手册页
实现的
sem_timedwait()
函数应
锁定
引用的信号量
sem
与 sem_wait()
函数中一样。
但是,如果信号量不能
锁定,无需等待另一个
进程或线程解锁
通过执行 sem_post() 来获取信号量
函数,这个等待应该是ter-
当指定的超时时间时终止
过期
,我可以看到 sem_timedwait() 更安全,但我仍然应该能够使用 sem_wait()
这是正确的吗? 如果没有,我还有什么其他选择...
谢谢
I am trying to port a project (from linux) that uses Semaphores to Mac OS X however some of the posix semaphores are not implemented on Mac OS X
The one that I hit in this port is sem_timedwait()
I don't know much about semaphores but from the man pages sem_wait()
seems to be close to sem_timedwait
and it is implemented
From the man pages
sem_timedwait()
function shall
lock the semaphore referenced by
sem
as in the sem_wait()
function.
However, if the semaphore cannot be
locked without waiting for another
process or thread to unlock the
semaphore by performing a sem_post()
function, this wait shall be ter-
minated when the specified timeout
expires
From my limited understanding of how semphores work I can see that sem_timedwait()
is safer, but I still should be able to use sem_wait()
Is this correct? If not what other alternatives do I have...
Thanks
发布评论
评论(10)
超时可能对算法的运行很重要。 因此,仅使用 sem_wait() 可能不起作用。
您可以使用 sem_trywait(),它在所有情况下都会立即返回。 然后,您可以循环并使用您选择的睡眠间隔,每次减少总超时,直到超时或获取信号量。
更好的解决方案是重写算法以使用条件变量,然后您可以使用 pthread_cond_timedwait() 来获取适当的超时。
It's likely that the timeout is important to the operation of the algorithm. Therefore just using
sem_wait()
might not work.You could use
sem_trywait()
, which returns right away in all cases. You can then loop, and use a sleep interval that you choose, each time decrementing the total timeout until you either run out of timeout or the semaphore is acquired.A much better solution is to rewrite the algorithm to use a condition variable, and then you can use
pthread_cond_timedwait()
to get the appropriate timeout.我曾经在 OSX 上使用命名信号量,但现在 sem_timedwait 不可用,并且 sem_init 和朋友已被弃用。 我使用 pthread 互斥体和条件实现了信号量,如下所示,这对我有用(OSX 10.13.1)。 您可能必须创建一个句柄与结构表,并查找 sem_t 类型,如果它不能在其中保存 ptr (即指针是 64 位而 sem_t 是 32?)
I used to use named semaphores on OSX, but now sem_timedwait isn't available and sem_init and friends are deprecated. I implemented semaphores using pthread mutex and conditions as follows which work for me (OSX 10.13.1). You might have to make a handle vs struct table and look up the sem_t type if it can't hold a ptr in it (i.e. pointers are 64bits and sem_t is 32?)
另一种选择可能是使用 sem_timedwait.c
由澳大利亚天文台软件组的 Keith Shortridge 实施。
从源文件:
Yet another alternative may be to use the sem_timedwait.c
implementation by Keith Shortridge of the Australian Astronomical Observatory's software group.
From the source file:
您是否考虑过使用 apache 可移植运行时? 它预装在每个 Mac OS X Box 和许多 Linux 发行版上,并且带有一个围绕线程并发的平台中立包装器,甚至可以在 MS Windows 上运行:
http://apr.apache.org/docs/apr/1.3/group__apr__thread__cond.html
Have you considered using the apache portable runtime? It's preinstalled on every Mac OS X Box and many Linux distros and it comes with a platform neutral wrapper around thread concurrency, that works even on MS Windows:
http://apr.apache.org/docs/apr/1.3/group__apr__thread__cond.html
一种选择是使用低级信号量 mach API:
顺便说一句,它在 libuv 中使用。
参考:
One option is to use low-level semaphore mach API:
It is used in libuv BTW.
Reference:
我认为最简单的解决方案是使用 sem_wait() 结合调用 Alarm() 来唤醒中止等待。 例如:
一个问题是警报需要几秒钟的时间作为输入,因此在您的情况下定时等待可能太长。
——阿吉利斯
I think the simplest solution is to use sem_wait() in combination with a call to alarm() to wake up abort the wait. For example:
One issue is that alarm takes seconds as input so the timed wait might be too long in your case.
-- aghiles
如果计时器到期后尚未被应该调用 sem_post() 的主线程调用,您是否可以尝试通过在另一个调用 sem_post() 的线程中启动计时器来模拟 sem_timedwait() 调用的功能?
Could you try to mimic the functionality of the sem_timedwait() call by starting a timer in another thread that calls sem_post() after the timer expires if it hasn't been called by the primary thread that is supposed to call sem_post()?
如果您可以仅使用 MP API:
如果超出指定超时且没有发出信号,则
MPWaitOnSemaphore
与kMPTimeoutErr
一起存在。If you can just use MP API:
MPWaitOnSemaphore
exists withkMPTimeoutErr
if specified timeout is exceeded without signaling.我原本计划使用以下函数作为替代,但后来我发现 sem_getvalue() 也已被弃用并且在 OSX 上不起作用。 您可以在 MIT 或 LGPL 许可证(您的选择)下自由使用以下稍微未经测试的代码。
SIGALRM 比 SIGUSR2 更有意义,因为这里显然使用了另一个示例(我没有费心去看它)。 SIGALRM 主要保留用于alarm() 调用,当您想要亚秒分辨率时,这些调用实际上毫无用处。
此代码首先尝试使用 sem_trywait() 获取信号量。 如果立即成功,那么它就会退出。 否则,它启动一个线程,该线程是通过 pthread_cond_timedwait() 实现计时器的地方。 MxSignaled 布尔值用于确定超时状态。
您可能还会发现此相关函数对于调用上述 sem_timedwait() 实现很有用(同样,MIT 或 LGPL,您的选择):
帮助使用最接近 Clock_gettime() 可以提供的内容填充 timespec 结构。 有各种评论表明重复调用 host_get_clock_service() 的成本很高。 但启动一个线程也很昂贵。
真正的解决办法是 Apple 实现整个 POSIX 规范,而不仅仅是强制性部分。 仅实现 POSIX 的强制性部分,然后声称符合 POSIX 要求,只会给每个人带来一个半损坏的操作系统和大量类似上述的解决方法,这些解决方法可能具有不太理想的性能。
综上所述,我放弃了 Mac OSX 和 Linux 上的本机信号量(Sys V 和 POSIX)。 它们以多种相当不幸的方式被破坏。 其他人也应该放弃他们。 (我不会放弃这些操作系统上的信号量,只是放弃本机实现。)无论如何,现在每个人都有一个 sem_timedwait() 实现,没有商业限制,其他人可以随心所欲地复制意大利面。
I was planning on using the following function as a replacement but then I discovered that sem_getvalue() was also deprecated and non-functional on OSX. You are free to use the following slightly untested code under a MIT or LGPL license (your choice).
SIGALRM makes more sense than SIGUSR2 as another example here apparently uses (I didn't bother looking at it). SIGALRM is mostly reserved for alarm() calls, which are virtually useless when you want sub-second resolution.
This code first attempts to acquire the semaphore with sem_trywait(). If that immediately succeeds, then it bails out. Otherwise, it starts a thread which is where the timer is implemented via pthread_cond_timedwait(). The MxSignaled boolean is used to determine the timeout state.
You may also find this relevant function useful for calling the above sem_timedwait() implementation (again, MIT or LGPL, your choice):
Helps populate a timespec structure with the closest thing to what clock_gettime() can provide. There are various comments out there that calling host_get_clock_service() repeatedly is expensive. But starting up a thread is also expensive.
The real fix is for Apple to implement the entire POSIX specification, not just the mandatory parts. Implementing only the mandatory bits of POSIX and then claiming POSIX compliance just leaves everyone with a half-broken OS and tons of workarounds like the above that may have less-than-ideal performance.
The above all said, I am giving up on native semaphores (both Sys V and POSIX) on both Mac OSX and Linux. They are broken in quite a few rather unfortunate ways. Everyone else should give up on them too. (I'm not giving up on semaphores on those OSes, just the native implementations.) At any rate, now everyone has a sem_timedwait() implementation without commercial restrictions that others can copy-pasta to their heart's content.
在 MacOS 上,我建议基于
SIGALRM
进行以下实现,以毫秒为单位给出超时
:on MacOS, I suggest the following implementation based on
SIGALRM
for atimeout
given in milliseconds: