xref: /freebsd-src/contrib/llvm-project/libcxx/include/__thread/this_thread.h (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1*06c3fb27SDimitry Andric // -*- C++ -*-
2*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
3*06c3fb27SDimitry Andric //
4*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*06c3fb27SDimitry Andric //
8*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
9*06c3fb27SDimitry Andric 
10*06c3fb27SDimitry Andric #ifndef _LIBCPP___THREAD_THIS_THREAD_H
11*06c3fb27SDimitry Andric #define _LIBCPP___THREAD_THIS_THREAD_H
12*06c3fb27SDimitry Andric 
13*06c3fb27SDimitry Andric #include <__chrono/steady_clock.h>
14*06c3fb27SDimitry Andric #include <__chrono/time_point.h>
15*06c3fb27SDimitry Andric #include <__condition_variable/condition_variable.h>
16*06c3fb27SDimitry Andric #include <__config>
17*06c3fb27SDimitry Andric #include <__mutex/mutex.h>
18*06c3fb27SDimitry Andric #include <__mutex/unique_lock.h>
19*06c3fb27SDimitry Andric #include <__threading_support>
20*06c3fb27SDimitry Andric 
21*06c3fb27SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22*06c3fb27SDimitry Andric #  pragma GCC system_header
23*06c3fb27SDimitry Andric #endif
24*06c3fb27SDimitry Andric 
25*06c3fb27SDimitry Andric _LIBCPP_PUSH_MACROS
26*06c3fb27SDimitry Andric #include <__undef_macros>
27*06c3fb27SDimitry Andric 
28*06c3fb27SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
29*06c3fb27SDimitry Andric 
30*06c3fb27SDimitry Andric namespace this_thread
31*06c3fb27SDimitry Andric {
32*06c3fb27SDimitry Andric 
33*06c3fb27SDimitry Andric _LIBCPP_EXPORTED_FROM_ABI void sleep_for(const chrono::nanoseconds& __ns);
34*06c3fb27SDimitry Andric 
35*06c3fb27SDimitry Andric template <class _Rep, class _Period>
36*06c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI void
37*06c3fb27SDimitry Andric sleep_for(const chrono::duration<_Rep, _Period>& __d)
38*06c3fb27SDimitry Andric {
39*06c3fb27SDimitry Andric     if (__d > chrono::duration<_Rep, _Period>::zero())
40*06c3fb27SDimitry Andric     {
41*06c3fb27SDimitry Andric         // The standard guarantees a 64bit signed integer resolution for nanoseconds,
42*06c3fb27SDimitry Andric         // so use INT64_MAX / 1e9 as cut-off point. Use a constant to avoid <climits>
43*06c3fb27SDimitry Andric         // and issues with long double folding on PowerPC with GCC.
44*06c3fb27SDimitry Andric         _LIBCPP_CONSTEXPR chrono::duration<long double> __max =
45*06c3fb27SDimitry Andric             chrono::duration<long double>(9223372036.0L);
46*06c3fb27SDimitry Andric         chrono::nanoseconds __ns;
47*06c3fb27SDimitry Andric         if (__d < __max)
48*06c3fb27SDimitry Andric         {
49*06c3fb27SDimitry Andric             __ns = chrono::duration_cast<chrono::nanoseconds>(__d);
50*06c3fb27SDimitry Andric             if (__ns < __d)
51*06c3fb27SDimitry Andric                 ++__ns;
52*06c3fb27SDimitry Andric         }
53*06c3fb27SDimitry Andric         else
54*06c3fb27SDimitry Andric             __ns = chrono::nanoseconds::max();
55*06c3fb27SDimitry Andric         this_thread::sleep_for(__ns);
56*06c3fb27SDimitry Andric     }
57*06c3fb27SDimitry Andric }
58*06c3fb27SDimitry Andric 
59*06c3fb27SDimitry Andric template <class _Clock, class _Duration>
60*06c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI void
61*06c3fb27SDimitry Andric sleep_until(const chrono::time_point<_Clock, _Duration>& __t)
62*06c3fb27SDimitry Andric {
63*06c3fb27SDimitry Andric     mutex __mut;
64*06c3fb27SDimitry Andric     condition_variable __cv;
65*06c3fb27SDimitry Andric     unique_lock<mutex> __lk(__mut);
66*06c3fb27SDimitry Andric     while (_Clock::now() < __t)
67*06c3fb27SDimitry Andric         __cv.wait_until(__lk, __t);
68*06c3fb27SDimitry Andric }
69*06c3fb27SDimitry Andric 
70*06c3fb27SDimitry Andric template <class _Duration>
71*06c3fb27SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY
72*06c3fb27SDimitry Andric void
73*06c3fb27SDimitry Andric sleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t)
74*06c3fb27SDimitry Andric {
75*06c3fb27SDimitry Andric     this_thread::sleep_for(__t - chrono::steady_clock::now());
76*06c3fb27SDimitry Andric }
77*06c3fb27SDimitry Andric 
78*06c3fb27SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY
79*06c3fb27SDimitry Andric void yield() _NOEXCEPT {__libcpp_thread_yield();}
80*06c3fb27SDimitry Andric 
81*06c3fb27SDimitry Andric } // namespace this_thread
82*06c3fb27SDimitry Andric 
83*06c3fb27SDimitry Andric _LIBCPP_END_NAMESPACE_STD
84*06c3fb27SDimitry Andric 
85*06c3fb27SDimitry Andric _LIBCPP_POP_MACROS
86*06c3fb27SDimitry Andric 
87*06c3fb27SDimitry Andric #endif // _LIBCPP___THREAD_THIS_THREAD_H
88