4

残念ながら、cygwin GCC4.5.3pthreadライブラリの実装は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;
}

誰かがこのコードについてより良いアイデアや改善点を持っていますか?

4

1 に答える 1

3

私の提案は、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_);
    }
};
于 2012-06-28T22:55:49.527 に答える