Cygwin pthread_mutex_timedlock surrogate

Unfortunately, the implementation of the cygwin GCC 4.5.3 pthread library does not support the standard POSIX function

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

Does anyone have a good idea how to implement a good workaround for this method in the mutex shell class? Can pthread_mutex_trylock() be used with nanosleep() call based on milliseconds? I don't have a good idea of ​​the last idea, but in any case, the C ++ implementation might look like this:

 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; } 

Anyone have a better idea or improvements for this code?

+4
source share
1 answer

My suggestion was to use pthread_cond_timedwait to simulate your temporary lock. The trick here is that timed_mutex_ never held for a very long time, since waiting on timed_cond_ releases the lock. timed_mutex_ also released immediately after locked_ set or not set.

 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_); } }; 
+3
source

All Articles