Why are sem_init(), sem_getvalue(), sem_destroy() deprecated on Mac OS X — and what replaces them?

前端 未结 1 1297
夕颜
夕颜 2021-02-05 01:05

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 deprecat

相关标签:
1条回答
  • 2021-02-05 01:27

    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:

    • Appendix 9 of the Single UNIX Specification states they are not mandatory interfaces
    • "Most portable code" uses SYSV semaphores
    • Backwards compatibility with POSIX named semaphores, which share the sem_t type is difficult

    As 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.

    0 讨论(0)
提交回复
热议问题