HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
stable_set.hpp
1// Copyright Take Vos 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/module.hpp"
8#include "concurrency/module.hpp"
9#include <mutex>
10#include <memory>
11#include <atomic>
12#include <map>
13#include <unordered_map>
14#include <functional>
15
16namespace hi::inline v1 {
17
28template<typename Key>
30public:
31 using value_type = Key;
32 using size_type = size_t;
33 using map_type = std::conditional_t<
37 using key_type = Key;
38 using difference_type = ptrdiff_t;
39 using reference = value_type const&;
40 using const_reference = value_type const&;
41 using pointer = value_type const *;
42 using const_pointer = value_type const *;
43
44 ~stable_set() = default;
45 constexpr stable_set() noexcept = default;
46 stable_set(stable_set const&) = delete;
47 stable_set(stable_set&&) = delete;
48 stable_set& operator=(stable_set const&) = delete;
49 stable_set& operator=(stable_set&&) = delete;
50
51 [[nodiscard]] size_t size() const noexcept
52 {
53 hilet lock = std::scoped_lock(_mutex);
54 return _vector.size();
55 }
56
57 [[nodiscard]] bool empty() const noexcept
58 {
59 return size() == 0;
60 }
61
62 operator bool() const noexcept
63 {
64 return not empty();
65 }
66
73 [[nodiscard]] const_reference operator[](size_t index) const noexcept
74 {
75 hilet lock = std::scoped_lock(_mutex);
76 hi_assert_bounds(index, _vector);
77 return *_vector[index];
78 }
79
89 template<typename Arg>
90 [[nodiscard]] size_t insert(Arg&& arg) noexcept requires(std::is_same_v<std::decay_t<Arg>, value_type>)
91 {
92 hilet lock = std::scoped_lock(_mutex);
93
94 hilet[it, is_inserted] = _map.emplace(std::forward<Arg>(arg), _vector.size());
95 if (is_inserted) {
96 _vector.push_back(std::addressof(it->first));
97 }
98 return it->second;
99 }
100
110 template<typename... Args>
111 [[nodiscard]] size_t emplace(Args&&...args) noexcept
112 {
113 hilet lock = std::scoped_lock(_mutex);
114
115 hilet[it, is_inserted] = _map.emplace(value_type{std::forward<Args>(args)...}, _vector.size());
116 if (is_inserted) {
117 _vector.push_back(std::addressof(it->first));
118 }
119 return it->second;
120 }
121
122private:
123 // clang-format sucks.
124 using vector_type = std::vector<const_pointer>;
125
126 vector_type _vector;
127 map_type _map;
128 mutable unfair_mutex _mutex;
129};
130} // namespace hi::inline v1
#define hi_assert_bounds(x,...)
Assert if a value is within bounds.
Definition assert.hpp:225
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:13
This is a set of object with stable indices.
Definition stable_set.hpp:29
size_t insert(Arg &&arg) noexcept
Insert an object into the stable-set.
Definition stable_set.hpp:90
size_t emplace(Args &&...args) noexcept
Emplace an object into the stable-set.
Definition stable_set.hpp:111
const_reference operator[](size_t index) const noexcept
Get a const reference to an object located at an index in the set.
Definition stable_set.hpp:73
Definition concepts.hpp:36
Definition concepts.hpp:39
T addressof(T... args)