192832e48SLouis Dionne // -*- C++ -*- 292832e48SLouis Dionne //===----------------------------------------------------------------------===// 392832e48SLouis Dionne // 492832e48SLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 592832e48SLouis Dionne // See https://llvm.org/LICENSE.txt for license information. 692832e48SLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 792832e48SLouis Dionne // 892832e48SLouis Dionne //===----------------------------------------------------------------------===// 9480cd780SLouis Dionne 1092832e48SLouis Dionne #ifndef _LIBCPP___THREAD_POLL_WITH_BACKOFF_H 1192832e48SLouis Dionne #define _LIBCPP___THREAD_POLL_WITH_BACKOFF_H 1292832e48SLouis Dionne 13489637e6SNikolas Klauser #include <__chrono/duration.h> 14489637e6SNikolas Klauser #include <__chrono/high_resolution_clock.h> 1592832e48SLouis Dionne #include <__config> 1692832e48SLouis Dionne 1792832e48SLouis Dionne #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 1892832e48SLouis Dionne # pragma GCC system_header 1992832e48SLouis Dionne #endif 2092832e48SLouis Dionne 2192832e48SLouis Dionne _LIBCPP_BEGIN_NAMESPACE_STD 2292832e48SLouis Dionne 2392832e48SLouis Dionne static _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64; 2492832e48SLouis Dionne 2592832e48SLouis Dionne // Polls a thread for a condition given by a predicate, and backs off based on a backoff policy 2692832e48SLouis Dionne // before polling again. 2792832e48SLouis Dionne // 28*55454061SLouis Dionne // - __poll is the "test function" that should return true if polling succeeded, and false if it failed. 2992832e48SLouis Dionne // 30*55454061SLouis Dionne // - __backoff is the "backoff policy", which is called with the duration since we started polling. It should 3192832e48SLouis Dionne // return false in order to resume polling, and true if polling should stop entirely for some reason. 3292832e48SLouis Dionne // In general, backoff policies sleep for some time before returning control to the polling loop. 3392832e48SLouis Dionne // 3492832e48SLouis Dionne // - __max_elapsed is the maximum duration to try polling for. If the maximum duration is exceeded, 3592832e48SLouis Dionne // the polling loop will return false to report a timeout. 36*55454061SLouis Dionne template <class _Poll, class _Backoff> 379783f28cSLouis Dionne _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool __libcpp_thread_poll_with_backoff( 38*55454061SLouis Dionne _Poll&& __poll, _Backoff&& __backoff, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero()) { 3992832e48SLouis Dionne auto const __start = chrono::high_resolution_clock::now(); 4092832e48SLouis Dionne for (int __count = 0;;) { 41*55454061SLouis Dionne if (__poll()) 42*55454061SLouis Dionne return true; // __poll completion means success 4392832e48SLouis Dionne if (__count < __libcpp_polling_count) { 4492832e48SLouis Dionne __count += 1; 4592832e48SLouis Dionne continue; 4692832e48SLouis Dionne } 4792832e48SLouis Dionne chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start; 4892832e48SLouis Dionne if (__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed) 4992832e48SLouis Dionne return false; // timeout failure 50*55454061SLouis Dionne if (__backoff(__elapsed)) 51*55454061SLouis Dionne return false; // __backoff completion means failure 5292832e48SLouis Dionne } 5392832e48SLouis Dionne } 5492832e48SLouis Dionne 5592832e48SLouis Dionne // A trivial backoff policy that always immediately returns the control to 5692832e48SLouis Dionne // the polling loop. 5792832e48SLouis Dionne // 5892832e48SLouis Dionne // This is not very well-behaved since it will cause the polling loop to spin, 5992832e48SLouis Dionne // so this should most likely only be used on single-threaded systems where there 6092832e48SLouis Dionne // are no other threads to compete with. 6192832e48SLouis Dionne struct __spinning_backoff_policy { operator__spinning_backoff_policy629783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool operator()(chrono::nanoseconds const&) const { return false; } 6392832e48SLouis Dionne }; 6492832e48SLouis Dionne 6592832e48SLouis Dionne _LIBCPP_END_NAMESPACE_STD 6692832e48SLouis Dionne 6792832e48SLouis Dionne #endif // _LIBCPP___THREAD_POLL_WITH_BACKOFF_H 68