HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
atomic.hpp
1// Copyright 2019 Pokitec
2// All rights reserved.
3
4#pragma once
5
6#include "TTauri/Foundation/counters.hpp"
7#include "TTauri/Foundation/string_tag.hpp"
8#include "TTauri/Foundation/os_detect.hpp"
9#include <atomic>
10#include <thread>
11#include <chrono>
12
13namespace tt {
14
23template<typename CounterTag, typename T>
24tt_no_inline void contended_wait_for_transition(std::atomic<T> const &state, T to, std::memory_order order=std::memory_order_seq_cst)
25{
26 using namespace std::literals::chrono_literals;
27
28 increment_counter<CounterTag>();
29
30 auto backoff = 10ms;
31 while (true) {
32 if (state.load(order) == to) {
33 return;
34 }
35
37 if ((backoff *= 2) > 1s) {
38 backoff = 1s;
39 }
40 }
41}
42
52template<typename CounterTag, typename T>
53tt_force_inline void wait_for_transition(std::atomic<T> const &state, T to, std::memory_order order=std::memory_order_seq_cst)
54{
55 if (tt_unlikely(state.load(order) != to)) {
56 contended_wait_for_transition<CounterTag>(state, to, order);
57 }
58}
59
68template<string_tag BlockCounterTag=0,typename T>
69tt_no_inline void contended_transition(std::atomic<T> &state, T from, T to, std::memory_order order=std::memory_order_seq_cst)
70{
71 using namespace std::literals::chrono_literals;
72
73 if constexpr (BlockCounterTag != 0) {
74 increment_counter<BlockCounterTag>();
75 }
76
77 auto backoff = 10ms;
78 while (true) {
79 auto expect = from;
80 if (state.compare_exchange_weak(expect, to, order)) {
81 return;
82 }
83
85 if ((backoff *= 2) > 1s) {
86 backoff = 1s;
87 }
88 }
89}
90
100template<string_tag BlockCounterTag=0,typename T>
101tt_force_inline void transition(std::atomic<T> &state, T from, T to, std::memory_order order=std::memory_order_seq_cst)
102{
103 auto expect = from;
104 if (tt_likely(state.compare_exchange_strong(expect, to, order))) {
105 return;
106 } else {
107 return contended_transition<BlockCounterTag>(state, from, to, order);
108 }
109}
110
111
112}
113
T compare_exchange_weak(T... args)
T load(T... args)
T sleep_for(T... args)