join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
backoff.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_CORE_BACKOFF_HPP
26#define JOIN_CORE_BACKOFF_HPP
27
28// libjoin.
29#include <join/clock.hpp>
30
31// C++.
32#include <thread>
33#include <chrono>
34
35// C.
36#if defined(__x86_64__) || defined(__i386__)
37#include <immintrin.h>
38#endif
39#include <cstddef>
40
41namespace join
42{
46 class Backoff
47 {
48 public:
55 explicit Backoff (std::chrono::nanoseconds spin = std::chrono::microseconds (10),
56 std::chrono::nanoseconds yield = std::chrono::microseconds (100),
57 std::chrono::nanoseconds sleep = std::chrono::microseconds (50)) noexcept
58 : _spin (spin)
59 , _yield (yield)
60 , _sleep (sleep)
61 {
62 }
63
67 void operator() () noexcept
68 {
69 if (_start == Rdtsc::TimePoint ())
70 {
71 _start = Rdtsc::now ();
72 }
73
74 if (_spinning)
75 {
76 if (Rdtsc::now () - _start < _spin)
77 {
78#if defined(__x86_64__) || defined(__i386__)
79 _mm_pause ();
80#elif defined(__aarch64__) || defined(__arm__)
81 __asm__ __volatile__ ("isb" ::: "memory");
82#endif
83 return;
84 }
85
86 _spinning = false;
87 }
88
89 const auto elapsed = Rdtsc::now () - _start;
90
91 if ((_sleep == std::chrono::nanoseconds::zero ()) || (elapsed - _spin < _yield))
92 {
93 std::this_thread::yield ();
94 }
95 else
96 {
97 std::this_thread::sleep_for (_sleep);
98 }
99 }
100
104 void reset () noexcept
105 {
106 _start = Rdtsc::TimePoint ();
107 _spinning = true;
108 }
109
114 bool spinExhausted () const noexcept
115 {
116 return (_start != Rdtsc::TimePoint ()) && (Rdtsc::now () - _start >= _spin);
117 }
118
119 private:
121 std::chrono::nanoseconds _spin;
122
124 std::chrono::nanoseconds _yield;
125
127 std::chrono::nanoseconds _sleep;
128
131
133 bool _spinning = true;
134 };
135}
136
137#endif
adaptive backoff for busy-wait loops, requires Rdtsc::calibrate ().
Definition backoff.hpp:47
void reset() noexcept
reset backoff to initial state.
Definition backoff.hpp:104
Backoff(std::chrono::nanoseconds spin=std::chrono::microseconds(10), std::chrono::nanoseconds yield=std::chrono::microseconds(100), std::chrono::nanoseconds sleep=std::chrono::microseconds(50)) noexcept
construct a backoff strategy.
Definition backoff.hpp:55
void operator()() noexcept
execute one backoff iteration.
Definition backoff.hpp:67
bool spinExhausted() const noexcept
check if initial spin phase is over.
Definition backoff.hpp:114
std::chrono::time_point< NanoClock > TimePoint
Definition clock.hpp:187
static TimePoint now() noexcept
read the current time, requires calibrate ().
Definition clock.hpp:266
Definition acceptor.hpp:32