http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54562

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |ASSIGNED
           Assignee|unassigned at gcc dot gnu.org      |redi at gcc dot gnu.org

--- Comment #4 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Created attachment 30320
  --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=30320&action=edit
proposed patch to use clocks correctly

The <condition_variable> change should be unnecessary, as high_resolution_clock
is a typedef for system_clock in our implementation.

The timed_mutex change is an improvement but not ideal, because the standard
says implementations "should" use a steady clock for try_lock_for() but use the
system_clock for try_lock_until(), and pthread_mutex_timedlock() uses
CLOCK_REALTIME, which corresponds to our system_clock.

I'm going to test this patch (against the current svn trunk, after
gcc.gnu.org/r200180) to fix the timed_mutex issue. The patch attempts to use
the steady clock for relative timeouts, converting to the high_resolution_clock
(aka system_clock) for the pthread call, and re-checks on timeout to handle 
cases where a clock is adjusted during the wait.

N.B. your test technically has undefined behaviour because it attempts to
relock the mutex in the same thread, I'm using this to reproduce the problem
instead:

#include <iostream>
#include <chrono>
#include <mutex>
#include <thread>

typedef std::chrono::high_resolution_clock rt_clock;
typedef std::chrono::time_point<rt_clock> rt_time_point;

std::timed_mutex mutex;

void f()
{
    mutex.try_lock_for(std::chrono::seconds(3));
}

int main()
{
    mutex.lock();
    std::cout << "mutex locked" << std::endl;

    rt_time_point t1 = rt_clock::now();
    std::thread(f).join();
    rt_time_point t2 = rt_clock::now();
    std::cout << "delay: " 
              <<
std::chrono::duration_cast<std::chrono::seconds>(t2-t1).count()
              << std::endl;
    return 0;
}

Reply via email to