HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
atomic.hpp
1// Copyright Take Vos 2019, 2021-2022.
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 "../utility/utility.hpp"
8#include "../macros.hpp"
9#include <atomic>
10#include <thread>
11#include <chrono>
12
13hi_export_module(hikogui.concurrency.atomic);
14
15hi_warning_push();
16// C26403: Reset or explicitly delete and owner<T> pointer '...' (r.3).: ...
17// The static analyser is very confused about the get_or_make() function.
18hi_warning_ignore_msvc(26403);
19
20hi_export namespace hi::inline v1 {
21
24template<typename T>
25T fetch_max(std::atomic<T> &lhs, T rhs, std::memory_order order) noexcept
26{
27 auto expected = lhs.load(order);
28 while (expected < rhs) {
29 if (lhs.compare_exchange_weak(expected, rhs, order)) {
30 return expected;
31 }
32 }
33 return expected;
34}
35
38template<typename T>
39T fetch_min(std::atomic<T> &lhs, T rhs, std::memory_order order) noexcept
40{
41 auto expected = lhs.load(order);
42 while (rhs < expected) {
43 if (lhs.compare_exchange_weak(expected, rhs, order)) {
44 return expected;
45 }
46 }
47 return expected;
48}
49
50template<typename T>
52public:
53 using element_type = T;
54 using pointer = element_type *;
55 using reference = element_type &;
56
57 ~atomic_unique_ptr() noexcept
58 {
59 delete _pointer.load(std::memory_order_relaxed);
60 }
61
62 constexpr atomic_unique_ptr() noexcept = default;
63 atomic_unique_ptr(atomic_unique_ptr const &) = delete;
64 atomic_unique_ptr &operator=(atomic_unique_ptr const &) = delete;
65
66 atomic_unique_ptr(atomic_unique_ptr &&other) noexcept : _pointer(other._pointer.exchange(nullptr)) {}
67
68 atomic_unique_ptr &operator=(atomic_unique_ptr &&other) noexcept
69 {
70 hi_return_on_self_assignment(other);
71
72 delete _pointer.exchange(other._pointer.exchange(nullptr));
73 return *this;
74 }
75
76 constexpr atomic_unique_ptr(std::nullptr_t) noexcept : _pointer(nullptr) {}
77
78 atomic_unique_ptr &operator=(std::nullptr_t) noexcept
79 {
80 delete _pointer.exchange(nullptr);
81 return *this;
82 }
83
84 constexpr atomic_unique_ptr(pointer other) noexcept : _pointer(other) {}
85
86 atomic_unique_ptr &operator=(pointer other) noexcept
87 {
88 delete _pointer.exchange(other);
89 return *this;
90 }
91
94 [[nodiscard]] pointer get(std::memory_order order = std::memory_order::seq_cst) const noexcept
95 {
96 return _pointer.load(order);
97 }
98
110 template<typename... Args>
111 [[nodiscard]] reference get_or_make(Args &&...args) noexcept
112 {
113 auto expected = _pointer.load(std::memory_order::acquire);
114 if (expected != nullptr) {
115 return *expected;
116 }
117
118 auto desired = new element_type(std::forward<Args>(args)...);
119 if (not _pointer.compare_exchange_strong(expected, desired, std::memory_order::release, std::memory_order::acquire)) {
120 // Lost construction race.
121 delete desired;
122 return *expected;
123 } else {
124 return *desired;
125 }
126 }
127
128private:
129 std::atomic<pointer> _pointer;
130};
131
132} // namespace hi::inline v1
133
134hi_warning_pop();
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
T fetch_max(std::atomic< T > &lhs, T rhs, std::memory_order order) noexcept
Lock-free fetch-then-max operation on an atomic.
Definition atomic.hpp:25
T fetch_min(std::atomic< T > &lhs, T rhs, std::memory_order order) noexcept
Lock-free fetch-then-min operation on an atomic.
Definition atomic.hpp:39
Definition atomic.hpp:51
reference get_or_make(Args &&...args) noexcept
Get or make an object.
Definition atomic.hpp:111
pointer get(std::memory_order order=std::memory_order::seq_cst) const noexcept
Get the raw pointer.
Definition atomic.hpp:94