[libcxx-commits] [PATCH] D65339: Implement std::condition_variable via pthread_cond_clockwait() where available

Tom via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Mon Aug 12 16:28:37 PDT 2019


tomcherry added a comment.

I simplified the code a bit more and responded to the comments.  I haven't had a good chance to test this yet, but pushing early for feedback.



================
Comment at: include/__mutex_base:528
+    nanoseconds d = tp.time_since_epoch();
+    if (d > nanoseconds(0x59682F000000E941))
+        d = nanoseconds(0x59682F000000E941);
----------------
EricWF wrote:
> tomcherry wrote:
> > ldionne wrote:
> > > Please pardon my naiveness, but what is that number?
> > It's taken from condition_variable.cpp, added in https://reviews.llvm.org/rGaad745a024a3d0fd573ac9649d4c659e6a713702.  
> > 
> > I tried to keep all of the safety checks around chrono intact.
> Lets give it a name so it makes sense. 
In retrospect, I removed it.  There's no accompanying comments on why it was added originally and there's no obvious reason why it would be needed.


================
Comment at: include/__mutex_base:18
 
+#if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
+#include <time.h>
----------------
EricWF wrote:
> Can't we include `time.h` unconditionally?
I thought it would be better to not include it if not needed, but I'll make it unconditionally included.


================
Comment at: include/__mutex_base:311
 
+    template <class _Duration>
+        _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
----------------
ldionne wrote:
> EricWF wrote:
> > This deduction is wrong. Either you deduce the entire time point, like we were originally, or you use the timepoint and duration specified by the clock.
> > 
> > You don't specify the clock and deduce the other parameters
> > 
> > Also, fewer overloads is better. We want to declare a  _single_ public overload. We can do the magic behind the scenes .
> > This deduction is wrong. Either you deduce the entire time point, like we were originally, or you use the timepoint and duration specified by the clock.
> 
> Why? I was the one to suggest this in the last diff, because we otherwise needed SFINAE and the resulting code was a lot more complex than it needed to be. What's wrong with this implementation?
The latest patchset has it back to the original public interface.


================
Comment at: include/__mutex_base:357
        chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
+#if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
+    void __do_timed_wait(unique_lock<mutex>& __lk,
----------------
EricWF wrote:
> This can likely be the same implementation as  above.
The new patchset does this all with the one public interface.


================
Comment at: include/__mutex_base:474
+    steady_clock::time_point __c_now = steady_clock::now();
+#if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
+    typedef time_point<steady_clock, duration<long double, nano> > __c_tpf;
----------------
EricWF wrote:
> This section seems like it can be generalized to work for both halves of this ifdef.
> Having the same code tested in all cases is always better than preprocessor branches.
> 
> Forgive me if I'm missing something.
I'm not sure it can.  The first branch does the overflow checking with steady_clock and the second does it with system_clock.  If we have steady_clock available, we'll want to use it.  If we don't have steady_clock available, then we must use system_clock, since all non supported clocks end up calling wait_for() with the difference between their now() and the input time.


================
Comment at: include/__mutex_base:475
+#if defined(_LIBCPP_HAS_COND_CLOCKWAIT)
+    typedef time_point<steady_clock, duration<long double, nano> > __c_tpf;
+    typedef time_point<steady_clock, nanoseconds> __c_tpi;
----------------
EricWF wrote:
> `using` instead of `typedef` in new code if you don't mind.
Will do.


================
Comment at: include/__mutex_base:476
+    typedef time_point<steady_clock, duration<long double, nano> > __c_tpf;
+    typedef time_point<steady_clock, nanoseconds> __c_tpi;
+    __c_tpf _Max = __c_tpi::max();
----------------
EricWF wrote:
> This assumes the resolution of the `steady_clock`, no?
Sort of.  It mostly assumes that steady_clock::now() can be converted into nanoseconds safely, which I think is a reasonable assumption to make.  The old code assumed the resolution of system_clock too, so it's not a regression from there.

I'm happy to hear a better solution, because both this code and the original have never sit well with me.  What we really want is a safe_duration_cast, where we get a ceiling effect if there would be overflow.  Since that is not how std::chrono was created, we're left with two options:

1) This function ends up with signed integer overflow if someone passes milliseconds::max() to it and steady/system_clock.  
2) Work-arounds like this


================
Comment at: include/__mutex_base:510
+void
+condition_variable::__do_timed_wait(unique_lock<mutex>& lk,
+     chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp) _NOEXCEPT
----------------
EricWF wrote:
> `__lk`, `__tp`, ` __d`, etc. 
> 
> Everything that isn't a part of the public API needs a reserved name.
Got it, done in next patch.


================
Comment at: include/__mutex_base:523
+    typedef decltype(ts.tv_sec) ts_sec;
+    _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max();
+    if (s.count() < ts_sec_max)
----------------
EricWF wrote:
> `const` works the same in all dialects.
It's constexpr in the original code, but const is sufficient, so I changed it to that.


================
Comment at: include/__mutex_base:527
+        ts.tv_sec = static_cast<ts_sec>(s.count());
+        ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).count());
+    }
----------------
EricWF wrote:
> What does the cast do except silence bugs?
> 
> (Same question above).
The first cast makes sense, we don't know what size time_t is, but we know that if s.count() < ts_sec_max, that we can convert into it.

The second cast isn't needed, removed.


Repository:
  rCXX libc++

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65339/new/

https://reviews.llvm.org/D65339





More information about the libcxx-commits mailing list