Mac OS X上的POSIX信号量:sem_timedwait替代方案

hha*_*fez 10 unix macos posix semaphore

我正在尝试移植一个使用Semaphores到Mac OS X的项目(从linux)但是在Mac OS X上没有实现一些posix信号量

我在这个港口遇到的那个是 sem_timedwait()

我对信号量知之甚少,但是从手册页sem_wait()似乎接近sem_timedwait并且实现了

从手册页

sem_timedwait() function应锁定函数中
semas所引用的信号量sem_wait().但是,如果在
不等待另一个进程或线程
通过执行sem_post() 函数来解锁信号量的情况下无法锁定信号量,则
在指定的超时到期时应终止此等待

从我对semphores如何工作的有限理解,我可以看到sem_timedwait()更安全,但我仍然应该能够使用sem_wait()

它是否正确?如果不是我还有其他选择......

谢谢

Jar*_*aus 6

超时很可能对算法的运行很重要.因此,使用sem_wait()可能不起作用.

您可以使用sem_trywait(),在所有情况下立即返回.然后,您可以循环,并使用您选择的休眠间隔,每次递减总超时,直到您用完超时或获取信号量.

一个更好的解决方案是重写算法以使用条件变量,然后您可以使用pthread_cond_timedwait()来获得适当的超时.


Bri*_*ian 6

我曾经在 OSX 上使用命名信号量,但现在 sem_timedwait 不可用,并且 sem_init 和朋友已被弃用。我使用 pthread 互斥体和条件实现了信号量,如下所示,这对我有用(OSX 10.13.1)。您可能必须制作一个句柄与结构表,并查找 sem_t 类型,如果它不能在其中保存 ptr (即指针是 64 位而 sem_t 是 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
Run Code Online (Sandbox Code Playgroud)