西格温pthread_mutex_timedlock代理人

cygwin pthread_mutex_timedlock surrogate

本文关键字:mutex 代理人 timedlock pthread      更新时间:2023-10-16

不幸的是,cygwin GCC 4.5.3 pthread库实现不支持POSIX标准函数

int pthread_mutex_timedlock(pthread_mutex_t* mutex, struct timespec* abstime);

有没有人知道如何在互斥包装类中为此方法实现一个好的解决方法?可能将pthread_mutex_trylock()与(基于毫秒的)nanosleep()调用一起使用?我对后一个想法感觉不好,但无论如何,C++实现可能如下所示:

bool MyPosixMutexWrapper::try_lock(const TimeDuration<>& timeout)
{
    if(valid)
    {
        if(timeout == TimeDuration<>::Zero)
        {
             if(pthread_mutex_trylock(&mutexHandle) == 0)
             {
                 return true;
             }
        }
        else
        {
            struct timespec now;
            clock_gettime(CLOCK_REALTIME,&now);
            TimeDuration<> tnow(now);
            tnow += timeout;
            struct timespec until = tnow.getNativeValue();
#if defined(_POSIX_TIMEOUTS)
            if(pthread_mutex_timedlock(&mutexHandle,&until) == 0)
            {
                return true;
            }
#else
            long milliseconds = timeout.milliseconds();
            while(milliseconds > 0)
            {
                 if(pthread_mutex_trylock(&mutexHandle) == 0)
                 {
                     return true;
                 }
                 struct timespec interval;
                 struct timespec remaining;
                 interval.tv_sec = 0;
                 interval.tv_nsec = 1000000;
                 do
                 {
                     remaining.tv_sec = 0;
                     remaining.tv_nsec = 0;
                     if(nanosleep(&interval,&remaining) < 0)
                     {
                         if(errno == EINTR)
                         {
                             interval.tv_sec = remaining.tv_sec;
                             interval.tv_nsec = remaining.tv_nsec;
                         }
                         else
                         {
                             return false;
                         }
                     }
                     clock_gettime(CLOCK_REALTIME,&now);
                     tnow = TimeDuration<>(now);
                     if(tnow >= TimeDuration(until))
                     {
                          return pthread_mutex_trylock(&mutexHandle) == 0;
                     }
                } while(remaining.tv_sec > 0 || remaining.tv_nsec > 0);
                --milliseconds;
            }
#endif
        }
    }
    return pthread_mutex_trylock(&mutexHandle) == 0;
}

有没有人对此代码有更好的想法或改进?

我的建议是使用pthread_cond_timedwait来模仿您的定时锁。这里的诀窍是timed_mutex_永远不会保持很长时间,因为等待timed_cond_释放锁。 timed_mutex_也会在设置或取消设置locked_后立即释放。

struct MutexGuard {
    pthread_mutex_t &mutex_;
    MutexGuard (pthread_mutex_t &m) : mutex_(m) {
        pthread_mutex_lock(&mutex_);
    }
    ~MutexGuard () {
        pthread_mutex_unlock(&mutex_);
    }
};
struct TimedMutex {
    pthread_mutex_t timed_mutex_;
    pthread_cond_t timed_cond_;
    bool locked_;
    TimedMutex ()
        : timed_mutex_(), timed_cond_(), locked_(false) {
        pthread_mutex_init(&timed_mutex_, 0);
        pthread_cond_init(&timed_cond_, 0);
    }
    ~TimedMutex () {
        pthread_cond_destroy(&timed_cond_);
        pthread_mutex_destroy(&timed_mutex_);
    }
    int lock (const struct timespec *t) {
        MutexGuard g(timed_mutex_);
        while (locked_) {
            int r = pthread_cond_timedwait(&timed_cond_, &timed_mutex_, t);
            if (r < 0) return r;
        }
        locked_ = true;
        return 0;
    }
    void lock () {
        MutexGuard g(timed_mutex_);
        while (locked_) {
            pthread_cond_wait(&timed_cond_, &timed_mutex_);
        }
        locked_ = true;
    }
    void unlock () {
        MutexGuard g(timed_mutex_);
        locked_ = false;
        pthread_cond_signal(&timed_cond_);
    }
};