ReactivePlusPlus
ReactiveX implementation for C++20
Loading...
Searching...
No Matches
container.hpp
1// ReactivePlusPlus library
2//
3// Copyright Aleksey Loginov 2023 - present.
4// Distributed under the Boost Software License, Version 1.0.
5// (See accompanying file LICENSE_1_0.txt or copy at
6// https://www.boost.org/LICENSE_1_0.txt)
7//
8// Project home: https://github.com/victimsnino/ReactivePlusPlus
9
10#pragma once
11
12#include <rpp/disposables/disposable_wrapper.hpp>
13#include <rpp/utils/exceptions.hpp>
14
15#include <algorithm>
16#include <vector>
17
18namespace rpp::details::disposables
19{
21 {
22 public:
23 explicit dynamic_disposables_container() = default;
24
27
28 dynamic_disposables_container& operator=(const dynamic_disposables_container& other) = delete;
29 dynamic_disposables_container& operator=(dynamic_disposables_container&& other) noexcept = default;
30
31 void push_back(const rpp::disposable_wrapper& d)
32 {
33 m_data.push_back(d);
34 }
35
36 void push_back(rpp::disposable_wrapper&& d)
37 {
38 m_data.push_back(std::move(d));
39 }
40
41 void remove(const rpp::disposable_wrapper& d)
42 {
43 m_data.erase(std::remove(m_data.begin(), m_data.end(), d), m_data.end());
44 }
45
46 void dispose() const
47 {
48 for (const auto& d : m_data)
49 {
50 d.dispose();
51 }
52 }
53
54 void clear()
55 {
56 m_data.clear();
57 }
58
59 private:
60 mutable std::vector<rpp::disposable_wrapper> m_data{};
61 };
62
63 template<size_t Count>
65 {
66 public:
69 static_disposables_container& operator=(const static_disposables_container& other) = delete;
70
72 {
73 if (this == &other)
74 return *this;
75
76 m_size = other.m_size;
77 for (size_t i = 0; i < m_size; ++i)
78 std::construct_at(get(i), std::move(*other.get(i)));
79
80 other.clear();
81 return *this;
82 }
83
84 static_disposables_container(static_disposables_container&& other) noexcept
85 {
86 *this = std::move(other);
87 }
88
89 ~static_disposables_container() noexcept
90 {
91 clear();
92 }
93
94 void push_back(const rpp::disposable_wrapper& d)
95 {
96 if (m_size >= Count)
97 throw rpp::utils::more_disposables_than_expected{"static_disposables_container obtained more disposables than expected"};
98 std::construct_at(get(m_size++), d);
99 }
100
101 void push_back(rpp::disposable_wrapper&& d)
102 {
103 if (m_size >= Count)
104 throw rpp::utils::more_disposables_than_expected{"static_disposables_container obtained more disposables than expected"};
105 std::construct_at(get(m_size++), std::move(d));
106 }
107
108 void remove(const rpp::disposable_wrapper& d)
109 {
110 for (size_t i = 0; i < m_size;)
111 {
112 if (*get(i) != d)
113 {
114 ++i;
115 continue;
116 }
117
118 for (size_t j = i + 1; j < m_size; ++j)
119 *get(j - 1) = std::move(*get(j));
120
121 std::destroy_at(get(--m_size));
122 }
123 }
124
125 void dispose() const
126 {
127 for (size_t i = 0; i < m_size; ++i)
128 {
129 get(i)->dispose();
130 }
131 }
132
133 void clear()
134 {
135 for (size_t i = 0; i < m_size; ++i)
136 std::destroy_at(get(i));
137 m_size = 0;
138 }
139
140 private:
141 const rpp::disposable_wrapper* get(size_t i) const
142 {
143 return std::launder(reinterpret_cast<const rpp::disposable_wrapper*>(&m_data[i * sizeof(rpp::disposable_wrapper)]));
144 }
145 rpp::disposable_wrapper* get(size_t i)
146 {
147 return std::launder(reinterpret_cast<rpp::disposable_wrapper*>(&m_data[i * sizeof(rpp::disposable_wrapper)]));
148 }
149
150 private:
151 alignas(rpp::disposable_wrapper) std::byte m_data[sizeof(rpp::disposable_wrapper) * Count]{};
152 size_t m_size{};
153 };
154
155 template<>
157 {
158 public:
159 [[noreturn]] static void push_back(const rpp::disposable_wrapper&)
160 {
161 throw rpp::utils::more_disposables_than_expected{"static_disposables_container<0> expected no disposables but received at least one"};
162 }
163
164 static void remove(const rpp::disposable_wrapper&) {}
165 static void dispose() {}
166 static void clear() {}
167 };
168} // namespace rpp::details::disposables
Container with fixed std::array as underlying storage.
Definition fwd.hpp:65
disposable_wrapper_impl< interface_disposable > disposable_wrapper
Wrapper to keep "simple" disposable. Specialization of rpp::disposable_wrapper_impl.
Definition fwd.hpp:34
Definition exceptions.hpp:23