sem_init()
函数编译程序时,收到编译警告(错误,因为我通常使用 -Werror
),表明在 Mac OS X 10.10.1 (Yosemite) 上编译时该函数已被弃用使用 GCC 4.9.1 或 XCode 6.1.1 中的 Clang (Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
) 版本。快速查看 /usr/include/sys/semaphore.h
显示该函数在声明后确实有一个 __deprecated
标记,就像
sem_getvalue()
和
sem_destroy()
。
问题:
鉴于 POSIX 规范中没有任何弃用的暗示,为什么这三个函数在 Mac OS X 上被单独列为弃用?
既然它们已被弃用,那么替代品是什么,为什么首选替代品?
当我尝试将我正在开发的库移植到 OS X 时,我自己也遇到了这个问题。我搜索了一段时间,但没有找到很好的答案。当我找到答案时,我有点不安:答案实际上是 “如果 Apple 实现 POSIX 未命名信号量,你会购买多少个 X Serves?”.
总结一下它们被弃用的原因以及为什么某些功能仍未实现的原因:
sem_t
类型的 POSIX 命名信号量向后兼容很困难至于该怎么做,我选择了 GCD 信号量。至于为什么首选替代品:它是 vanilla OS X 上唯一可用的原生未命名信号量接口。显然,GCD 帮助他们销售了更多的 X Serves。我担心没有更好的答案。
但是,希望一些代码会有所帮助。所有这一切的结果是您实际上必须实现自己的便携式信号量接口:
#ifdef __APPLE__
#include <dispatch/dispatch.h>
#else
#include <semaphore.h>
#endif
struct rk_sema {
#ifdef __APPLE__
dispatch_semaphore_t sem;
#else
sem_t sem;
#endif
};
static inline void
rk_sema_init(struct rk_sema *s, uint32_t value)
{
#ifdef __APPLE__
dispatch_semaphore_t *sem = &s->sem;
*sem = dispatch_semaphore_create(value);
#else
sem_init(&s->sem, 0, value);
#endif
}
static inline void
rk_sema_wait(struct rk_sema *s)
{
#ifdef __APPLE__
dispatch_semaphore_wait(s->sem, DISPATCH_TIME_FOREVER);
#else
int r;
do {
r = sem_wait(&s->sem);
} while (r == -1 && errno == EINTR);
#endif
}
static inline void
rk_sema_post(struct rk_sema *s)
{
#ifdef __APPLE__
dispatch_semaphore_signal(s->sem);
#else
sem_post(&s->sem);
#endif
}
这是我关心的最小功能集;您的需求可能会有所不同。希望这有帮助。
只是为了在这里添加一些颜色, OS X 上的 sem_init 声称编译器报告“已弃用”,但实现实际上只是设置 errno 并返回
-1
。
真的很丢脸。如果您想在 Mac 上使用简单的信号量,您别无选择,只能对代码进行扩展。