Подтвердить что ты не робот

Почему sem_init(), sem_getvalue(), sem_destroy() устарели на Mac OS X - и что их заменяет?

Когда я скомпилирую программу, используя функцию POSIX sem_init(), я получаю предупреждение о компиляции (ошибка, потому что я обычно использую -Werror), что функция была устаревшей при компиляции в Mac OS X 10.10.1 (Yosemite) с GCC 4.9.1 или версией Clang (Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)) из XCode 6.1.1. Быстрый просмотр /usr/include/sys/semaphore.h показывает, что функция действительно имеет тег __deprecated после его объявления, как и sem_getvalue() и sem_destroy().

Вопросы:

  • Учитывая, что в спецификации POSIX нет намека на устаревание, почему эти три функции выделены как устаревшие в Mac OS X?

  • Учитывая, что они устарели, какова замена, и почему предпочтительна замена?

(сначала я проверил Ask Different, и никаких вопросов не было отмечено c и никаких вопросов, которые задают об устаревших системных вызовах - только программы.)

4b9b3361

Ответ 1

Я столкнулся с этой проблемой сам, пытаясь перенести библиотеку, над которой я работал, в OS X. Я искал какое-то время, не найдя отличный ответ. Когда я нашел ответ, я был немного взволнован: ответ действительно , если Apple внедрила неназванные семафоры POSIX, сколько X Serves вы купили?.

Подводя итог тому, почему они устарели и почему некоторые функции остаются нереализованными:

  • В Приложении 9 Единой спецификации UNIX указано, что они не являются обязательными интерфейсами.
  • "Самый переносимый код" использует семафоры SYSV
  • Обратная совместимость с POSIX семафорами, которые разделяют тип sem_t, сложны

Что касается того, что делать, я пошел с семафорами GCD. Что касается того, почему замена предпочтительнее: это единственный собственный неназванный интерфейс семафора, доступный на ванильной ОС 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
}

Это был минимальный набор функций, о которых я заботился; ваши потребности могут отличаться. Надеюсь, это поможет.