When I compile a program using the POSIX sem_init()
function, I get a compilation warning (error because I normally use -Werror
) that the function has been deprecated when I compile on Mac OS X 10.10.1 (Yosemite) with GCC 4.9.1 or the version of Clang (Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
) from XCode 6.1.1. A quick look at /usr/include/sys/semaphore.h
shows that the function does indeed have a __deprecated
tag after its declaration, as do
sem_getvalue()
and
sem_destroy()
.
Questions:
Given that there is no hint of deprecation in the POSIX specification, why are these three functions singled out as deprecated on Mac OS X?
Given that they are deprecated, what is the replacement, and why is the replacement preferred?
(I did check Ask Different first; there are no questions tagged c and no questions that ask about deprecated system calls — only programs.)
I ran into this problem myself when trying to port a library I was working on to OS X. I searched for a while without finding a great answer. When I did find the answer, I was a bit perturbed: the answer is effectively "if Apple implemented POSIX unnamed semaphores, how many X Serves would you buy?".
To summarize the points of why they are deprecated and why some of the functionality remains unimplemented:
sem_t
type is difficultAs for what to do instead, I went with GCD semaphores. As to why the replacement is preferred: it's the only native unnamed semaphore interface available on vanilla OS X. Apparently GCD helped them sell more X Serves. I fear there's not a better answer.
However, hopefully some code will be helpful. The upshot of all of this is that you effectively have to implement your own portable semaphore interface:
#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
}
This was the minimal set of functionality I cared about; your needs may vary. Hopefully this is helpful.