C++ cygwin pthread_mutex_timedlock代理

C++ cygwin pthread_mutex_timedlock代理,c++,cygwin,posix,mutex,C++,Cygwin,Posix,Mutex,不幸的是,cygwin GCC 4.5.3 pthread库实现不支持POSIX标准函数 int pthread_mutex_timedlock(pthread_mutex_t* mutex, struct timespec* abstime); 有人知道如何在互斥体包装器类中实现此方法的良好解决方案吗?可能正在使用pthread\u mutex\u trylock()和(基于毫秒的)nanosleep()调用? 我对后者的想法没有什么感觉,但是无论如何C++的实现都可以是这样的: bool

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

int pthread_mutex_timedlock(pthread_mutex_t* mutex, struct timespec* abstime);
有人知道如何在互斥体包装器类中实现此方法的良好解决方案吗?可能正在使用
pthread\u mutex\u 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;
}
bool MyPosixMutexWrapper::try_lock(const TimeDuration&timeout)
{
如果(有效)
{
如果(超时==持续时间::零)
{
if(pthread\u mutex\u trylock(&mutexHandle)==0)
{
返回true;
}
}
其他的
{
现在构造timespec;
clock\u gettime(clock\u REALTIME和now);
持续时间tnow(现在);
tnow+=超时;
struct timespec till=tnow.getNativeValue();
#如果已定义(_POSIX_超时)
if(pthread\u mutex\u timedlock(&mutexHandle,&until)==0)
{
返回true;
}
#否则
长毫秒=超时。毫秒();
而(毫秒>0)
{
if(pthread\u mutex\u trylock(&mutexHandle)==0)
{
返回true;
}
结构时间间隔;
剩余的结构timespec;
间隔.tv_秒=0;
interval.tv_nsec=1000000;
做
{
剩余的.tv_秒=0;
剩余的.tv_nsec=0;
如果(纳秒睡眠(&间隔,&剩余)<0)
{
如果(errno==EINTR)
{
间隔.tv_秒=剩余的.tv_秒;
interval.tv\u nsec=剩余的.tv\u nsec;
}
其他的
{
返回false;
}
}
clock\u gettime(clock\u REALTIME和now);
tnow=持续时间(现在);
如果(tnow>=持续时间(直到))
{
返回pthread\u mutex\u trylock(&mutexHandle)==0;
}
}而(剩余.tv_sec>0 | |剩余.tv_nsec>0);
--毫秒;
}
#恩迪夫
}
}
返回pthread\u mutex\u trylock(&mutexHandle)==0;
}

有人对这段代码有更好的想法或改进吗?

我的建议是使用
pthread\u cond\u timedwait
来模拟您的定时锁。这里的诀窍是,
timed\u mutex\uuu
不会保持很长时间,因为等待
timed\u cond\uu
会释放锁<设置或取消设置
locked
后,也会立即释放code>timed\u mutex

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_);
    }
};
struct MutexGuard{
pthread_mutex_t&mutex;
MutexGuard(pthread\u mutex\u t&m):mutex(m){
pthread_mutex_lock(&mutex);
}
~MutexGuard(){
pthread_mutex_unlock(&mutex);
}
};
结构TimedMutex{
pthread_mutex_t timed_mutex;
pthread_cond_u t timed_cond_;
布尔锁定;
TimedMutex()
:timed_mutex_(){
pthread_mutex_init(&timed_mutex_0);
pthread_cond_init(&timed_cond_,0);
}
~TimedMutex(){
pthread_cond_destroy(&timed_cond_);
pthread_mutex_destroy(&timed_mutex_);
}
int锁(const struct timespec*t){
MutexGuard g(定时互斥);
while(锁定){
int r=pthread_cond_timedwait(&timed_cond_uu,&timed_mutex_uu,t);
如果(r<0)返回r;
}
锁定=真;
返回0;
}
无效锁(){
MutexGuard g(定时互斥);
while(锁定){
pthread_cond_wait(&timed_cond_,&timed_mutex);
}
锁定=真;
}
无效解锁(){
MutexGuard g(定时互斥);
锁定=错误;
pthread_cond_信号(&timed_cond_);
}
};

您可以使用Windows互斥体而不是pthread互斥体,并使用带有适当超时的
WaitForSingleObject
。但是Windows互斥锁非常繁重,在所有情况下都需要系统调用,甚至是无争用的锁定,因此除了必须编写所有新代码来处理它们之外,您还可能会受到性能的影响。@AdamRosenfield:我更喜欢某种“POSIX兼容”的实现,
\u POSIX\u超时
指示
pthread\u mutex\u timedlock()
函数是否可用。我不想在这段代码中使用windows本机解决方案。正如我已经担心的那样,建议的实现在Cygwin环境中不能很好地工作。尽管我改进了检查超时的代码…Thx,但您的答案看起来很有希望。出于好奇:这就是cx11标准为互斥和timedmutex提供单独类型的原因吗?因为后者的实施可能需要额外的资源?@g-makulik:恐怕我不知道C++11委员会决定背后的理由。但是,我想它既允许程序员从库中包含一组较小的代码来完成工作,也允许库编写器提供提供提供功能的最严格的实现。我不明白为什么在这里使用两个不同的互斥体,直截了当的解决方案是使用一个互斥和一个条件变量构建自己的定时互斥类型。另外,这个解决方案在竞争时可能会非常慢。@PaulGroke:我今天早上才意识到这一点,并且刚刚在研究它。谢谢你的洞察力。Regards@user315052:啊,该死,我刚刚发布了一个带有“bool”版本的答案-似乎我太慢了:)