HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
atomic.hpp
1// Copyright Take Vos 2019-2020.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "counters.hpp"
8#include "os_detect.hpp"
9#include <atomic>
10#include <thread>
11#include <chrono>
12
13namespace tt {
14
24template<basic_fixed_string CounterTag, typename T>
25tt_no_inline void
26contended_wait_for_transition(std::atomic<T> const &state, T to, std::memory_order order = std::memory_order_seq_cst)
27{
28 using namespace std::literals::chrono_literals;
29
30 increment_counter<CounterTag>();
31
32 auto backoff = 10ms;
33 while (true) {
34 if (state.load(order) == to) {
35 return;
36 }
37
39 if ((backoff *= 2) > 1s) {
40 backoff = 1s;
41 }
42 }
43}
44
56template<basic_fixed_string CounterTag, typename T>
57void wait_for_transition(std::atomic<T> const &state, T to, std::memory_order order = std::memory_order_seq_cst)
58{
59 if (state.load(order) != to) {
60 [[unlikely]] contended_wait_for_transition<CounterTag>(state, to, order);
61 }
62}
63
72template<basic_fixed_string BlockCounterTag = "", typename T>
73tt_no_inline void contended_transition(std::atomic<T> &state, T from, T to, std::memory_order order = std::memory_order_seq_cst)
74{
75 using namespace std::literals::chrono_literals;
76
77 if constexpr (BlockCounterTag != "") {
78 increment_counter<BlockCounterTag>();
79 }
80
81 auto backoff = 10ms;
82 while (true) {
83 auto expect = from;
84 if (state.compare_exchange_weak(expect, to, order)) {
85 return;
86 }
87
89 if ((backoff *= 2) > 1s) {
90 backoff = 1s;
91 }
92 }
93}
94
104template<basic_fixed_string BlockCounterTag = "", typename T>
105void transition(std::atomic<T> &state, T from, T to, std::memory_order order = std::memory_order_seq_cst)
106{
107 auto expect = from;
108 if (state.compare_exchange_strong(expect, to, order)) {
109 [[likely]] return;
110 } else {
111 return contended_transition<BlockCounterTag>(state, from, to, order);
112 }
113}
114
115} // namespace tt
T compare_exchange_weak(T... args)
T load(T... args)
T sleep_for(T... args)