[Bug libstdc++/53841] New: [C++11] condition_variable::wait_until() fails with high resolution clocks

redi at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Tue Jul 3 15:59:00 GMT 2012


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

             Bug #: 53841
           Summary: [C++11] condition_variable::wait_until() fails with
                    high resolution clocks
    Classification: Unclassified
           Product: gcc
           Version: 4.8.0
            Status: UNCONFIRMED
          Keywords: rejects-valid
          Severity: normal
          Priority: P3
         Component: libstdc++
        AssignedTo: unassigned@gcc.gnu.org
        ReportedBy: redi@gcc.gnu.org


GCC's condition_variable::wait_until knows how to convert from unknown clocks
to system_clock, although it has a problem:

    // DR 887 - Sync unknown clock to known clock.
    const typename _Clock::time_point __c_entry = _Clock::now();
    const __clock_t::time_point __s_entry = __clock_t::now();
    const chrono::nanoseconds __delta = __atime - __c_entry;

That last line fails to compile if _Clock is higher resolution than
system_clock (i.e. has a smaller period or uses a floating point
representation).

Here's a clock that corresponds to system_clock but uses
duration<double,ratio<1>> as its duration type:

#include <chrono>
#include <mutex>
#include <condition_variable>

namespace ch = std::chrono;

struct FPClock : ch::system_clock
{
    typedef double rep;
    typedef std::ratio<1> period;
    typedef ch::duration<rep, period> duration;
    typedef ch::time_point<FPClock> time_point;

    static time_point now()
    { return time_point(duration(system_clock::now().time_since_epoch())); }
};

void f()
{
    std::mutex mx;
    std::unique_lock<std::mutex> l(mx);
    std::condition_variable cv;
    cv.wait_until(l, FPClock::now());
}

This fails to compile.

It could be fixed with duration_cast:

    const chrono::nanoseconds __delta
      = chrono::duration_cast<chrono::nanoseconds>(__atime - __c_entry);

but that loses precision and truncates the value, e.g. FPClock::duration(9e-10)
is converted to nanoseconds(0), but nanoseconds(1) would be better.

I think it needs to use a version of duration_cast that rounds up to the next
value representable as chrono::nanoseconds.



More information about the Gcc-bugs mailing list