POSIX Semaphores on Mac OS X: sem_timedwait alternative POSIX Semaphores on Mac OS X: sem_timedwait alternative unix unix

POSIX Semaphores on Mac OS X: sem_timedwait alternative


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.


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:

/**                       s e m _ t i m e d w a i t**  Function:*     Implements a version of sem_timedwait().**  Description:*     Not all systems implement sem_timedwait(), which is a version of*     sem_wait() with a timeout. Mac OS X is one example, at least up to*     and including version 10.6 (Leopard). If such a function is needed,*     this code provides a reasonable implementation, which I think is*     compatible with the standard version, although possibly less*     efficient. It works by creating a thread that interrupts a normal*     sem_wait() call after the specified timeout.** ...**  Limitations:**     The mechanism used involves sending a SIGUSR2 signal to the thread*     calling sem_timedwait(). The handler for this signal is set to a null*     routine which does nothing, and with any flags for the signal *     (eg SA_RESTART) cleared. Note that this effective disabling of the*     SIGUSR2 signal is a side-effect of using this routine, and means it*     may not be a completely transparent plug-in replacement for a*     'normal' sig_timedwait() call. Since OS X does not declare the*     sem_timedwait() call in its standard include files, the relevant *     declaration (shown above in the man pages extract) will probably have*     to be added to any code that uses this.* * ...* *  Copyright (c) Australian Astronomical Observatory.*  Commercial use requires permission.*  This code comes with absolutely no warranty of any kind.*/


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?)

#ifdef __APPLE__typedef struct{    pthread_mutex_t count_lock;    pthread_cond_t  count_bump;    unsigned count;}bosal_sem_t;int sem_init(sem_t *psem, int flags, unsigned count){    bosal_sem_t *pnewsem;    int result;    pnewsem = (bosal_sem_t *)malloc(sizeof(bosal_sem_t));    if (! pnewsem)    {        return -1;    }    result = pthread_mutex_init(&pnewsem->count_lock, NULL);    if (result)    {        free(pnewsem);        return result;    }    result = pthread_cond_init(&pnewsem->count_bump, NULL);    if (result)    {        pthread_mutex_destroy(&pnewsem->count_lock);        free(pnewsem);        return result;    }    pnewsem->count = count;    *psem = (sem_t)pnewsem;    return 0;}int sem_destroy(sem_t *psem){    bosal_sem_t *poldsem;    if (! psem)    {        return EINVAL;    }    poldsem = (bosal_sem_t *)*psem;    pthread_mutex_destroy(&poldsem->count_lock);    pthread_cond_destroy(&poldsem->count_bump);    free(poldsem);    return 0;}int sem_post(sem_t *psem){     bosal_sem_t *pxsem;    int result, xresult;    if (! psem)    {        return EINVAL;    }    pxsem = (bosal_sem_t *)*psem;    result = pthread_mutex_lock(&pxsem->count_lock);    if (result)    {        return result;    }    pxsem->count = pxsem->count + 1;    xresult = pthread_cond_signal(&pxsem->count_bump);    result = pthread_mutex_unlock(&pxsem->count_lock);    if (result)    {        return result;    }    if (xresult)    {        errno = xresult;        return -1;    }}int sem_trywait(sem_t *psem){    bosal_sem_t *pxsem;    int result, xresult;    if (! psem)    {        return EINVAL;    }    pxsem = (bosal_sem_t *)*psem;    result = pthread_mutex_lock(&pxsem->count_lock);    if (result)    {        return result;    }    xresult = 0;    if (pxsem->count > 0)    {        pxsem->count--;    }    else    {        xresult = EAGAIN;    }    result = pthread_mutex_unlock(&pxsem->count_lock);    if (result)    {        return result;    }    if (xresult)    {        errno = xresult;        return -1;    }    return 0;}int sem_wait(sem_t *psem){    bosal_sem_t *pxsem;    int result, xresult;    if (! psem)    {        return EINVAL;    }    pxsem = (bosal_sem_t *)*psem;    result = pthread_mutex_lock(&pxsem->count_lock);    if (result)    {        return result;    }    xresult = 0;    if (pxsem->count == 0)    {        xresult = pthread_cond_wait(&pxsem->count_bump, &pxsem->count_lock);    }    if (! xresult)    {        if (pxsem->count > 0)        {            pxsem->count--;        }    }    result = pthread_mutex_unlock(&pxsem->count_lock);    if (result)    {        return result;    }    if (xresult)    {        errno = xresult;        return -1;    }    return 0;}int sem_timedwait(sem_t *psem, const struct timespec *abstim){    bosal_sem_t *pxsem;    int result, xresult;    if (! psem)    {        return EINVAL;    }    pxsem = (bosal_sem_t *)*psem;    result = pthread_mutex_lock(&pxsem->count_lock);    if (result)    {        return result;    }    xresult = 0;    if (pxsem->count == 0)    {        xresult = pthread_cond_timedwait(&pxsem->count_bump, &pxsem->count_lock, abstim);    }    if (! xresult)    {        if (pxsem->count > 0)        {            pxsem->count--;        }    }    result = pthread_mutex_unlock(&pxsem->count_lock);    if (result)    {        return result;    }    if (xresult)    {        errno = xresult;        return -1;    }    return 0;}#endif