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 "architecture.hpp"
8#include <atomic>
9#include <thread>
10#include <chrono>
11
12namespace tt {
13
16template<typename T>
17T fetch_max(std::atomic<T> &lhs, T rhs, std::memory_order order) noexcept
18{
19 auto expected = lhs.load(order);
20 while (expected < rhs) {
21 if (lhs.compare_exchange_weak(expected, rhs, order)) {
22 return expected;
23 }
24 }
25 return expected;
26}
27
30template<typename T>
31T fetch_min(std::atomic<T> &lhs, T rhs, std::memory_order order) noexcept
32{
33 auto expected = lhs.load(order);
34 while (rhs < expected) {
35 if (lhs.compare_exchange_weak(expected, rhs, order)) {
36 return expected;
37 }
38 }
39 return expected;
40}
41
42template<typename T>
44public:
45 using element_type = T;
46 using pointer = element_type *;
47 using reference = element_type &;
48
49 ~atomic_unique_ptr() noexcept
50 {
51 delete _pointer.load(std::memory_order_relaxed);
52 }
53
54 constexpr atomic_unique_ptr() noexcept = default;
55 atomic_unique_ptr(atomic_unique_ptr const &) = delete;
56 atomic_unique_ptr &operator=(atomic_unique_ptr const &) = delete;
57
58 atomic_unique_ptr(atomic_unique_ptr &&other) noexcept : _pointer(other._pointer.exchange(nullptr)) {}
59
60 atomic_unique_ptr &operator=(atomic_unique_ptr &&other) noexcept {
61 tt_return_on_self_assignment(other);
62
63 delete _pointer.exchange(other._pointer.exchange(nullptr));
64 return *this;
65 }
66
67 constexpr atomic_unique_ptr(std::nullptr_t) noexcept : _pointer(nullptr) {}
68
69 atomic_unique_ptr &operator=(std::nullptr_t) noexcept
70 {
71 delete _pointer.exchange(nullptr);
72 return *this;
73 }
74
75 constexpr atomic_unique_ptr(pointer other) noexcept : _pointer(other) {}
76
77 atomic_unique_ptr &operator=(pointer other) noexcept
78 {
79 delete _pointer.exchange(other);
80 return *this;
81 }
82
85 [[nodiscard]] pointer get(std::memory_order order = std::memory_order::seq_cst) const noexcept
86 {
87 return _pointer.load(order);
88 }
89
101 template<typename... Args>
102 [[nodiscard]] reference get_or_make(Args &&... args) noexcept
103 {
104 auto expected = _pointer.load(std::memory_order::acquire);
105 if (expected != nullptr) {
106 return *expected;
107 }
108
109 auto desired = new element_type(std::forward<Args>(args)...);
110 if (not _pointer.compare_exchange_strong(expected, desired, std::memory_order::release, std::memory_order::acquire)) {
111 // Lost construction race.
112 delete desired;
113 return *expected;
114 } else {
115 return *desired;
116 }
117 }
118
119private:
120 std::atomic<pointer> _pointer;
121};
122
123} // namespace tt
Definition atomic.hpp:43
reference get_or_make(Args &&... args) noexcept
Get or make an object.
Definition atomic.hpp:102
pointer get(std::memory_order order=std::memory_order::seq_cst) const noexcept
Get the raw pointer.
Definition atomic.hpp:85
Definition concepts.hpp:34
Definition concepts.hpp:37
T compare_exchange_strong(T... args)
T exchange(T... args)
T load(T... args)