Search code examples
c++pthreads-win32

pthread_mutex not waiting on timeout


I have the following code:

bool Mutex::timed_lock(unsigned long milliseconds)
{
    if (!milliseconds)
    {
        return lock();
    }

    struct timespec ts;
    ts.tv_sec = milliseconds / 1000;
    ts.tv_nsec = (milliseconds - (ts.tv_sec * 1000)) * 1000000;

    //printf("%lld, %ld\n\n", ts.tv_sec, ts.tv_nsec);


    int res = pthread_mutex_timedlock(&info->mutex, &ts);
    info->ref_count += res != ETIMEDOUT && res != EDEADLK && !res ? 1 : 0;
    return res != ETIMEDOUT && res != EDEADLK && !res;
}

then I tried testing it like so:

Mutex lock;

std::thread([&]{
    std::cout<<"LOCKED: "<<std::boolalpha<<lock.lock()<<"\n";
    Sleep(5000);
}).detach();
Sleep(1000);

std::cout<<"DONE: "<<std::boolalpha<<lock.timed_lock(6600)<<"\n";

The result is that it prints "LOCKED: true \n DONE: false" and ETIMEDOUT is the error. It's supposed to block for the duration of 6600 ms if it cannot lock it.

Any ideas what I'm doing wrong? I'm only reinventing the wheel instead of using the C++11 std::mutex because this Mutex I need to share for IPC synchronisation/events (similar to WinAPI's CreateEvent).


Solution

  • The timeout to pthread_mutex_timedlock() is an absolute timeout, not a relative timeout. So you need to figure out the current time and calculate the future absolute time:

    struct timespec ts;
    struct timespec now;
    gettimeofday(&now, NULL);
    ts->tv_sec = now.tv_sec + milliseconds/1000;
    ts->tv_nsec = (now.tv_usec * 1000) + ((milliseconds%1000) * 1000000);
    if (ts.tv_nsec >= 1000000000) {
         ts.tv_sec++;
         ts.tv_nsec -= 1000000000;
    }