ReactivePlusPlus
ReactiveX implementation for C++20
Toggle main menu visibility
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/AlexInLog/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 <new>
17
#include <vector>
18
19
namespace
rpp::details::disposables
20
{
21
class
dynamic_disposables_container
22
{
23
public
:
24
explicit
dynamic_disposables_container() =
default
;
25
26
dynamic_disposables_container(
const
dynamic_disposables_container&) =
delete
;
27
dynamic_disposables_container(dynamic_disposables_container&& other)
noexcept
=
default
;
28
29
dynamic_disposables_container& operator=(
const
dynamic_disposables_container& other) =
delete
;
30
dynamic_disposables_container& operator=(dynamic_disposables_container&& other)
noexcept
=
default
;
31
32
void
push_back(
const
rpp::disposable_wrapper
& d)
33
{
34
m_data.push_back(d);
35
}
36
37
void
push_back(
rpp::disposable_wrapper
&& d)
38
{
39
m_data.push_back(std::move(d));
40
}
41
42
void
remove(
const
rpp::disposable_wrapper
& d)
43
{
44
m_data.erase(std::remove(m_data.begin(), m_data.end(), d), m_data.end());
45
}
46
47
void
dispose()
const
48
{
49
for
(
const
auto
& d : m_data)
50
{
51
d.dispose();
52
}
53
}
54
55
void
clear()
56
{
57
m_data.clear();
58
}
59
60
private
:
61
mutable
std::vector<rpp::disposable_wrapper> m_data{};
62
};
63
64
template
<
size_t
Count>
65
class
static_disposables_container
66
{
67
public
:
68
static_disposables_container() =
default
;
69
static_disposables_container(
const
static_disposables_container&) =
delete
;
70
static_disposables_container& operator=(
const
static_disposables_container& other) =
delete
;
71
72
static_disposables_container& operator=(static_disposables_container&& other)
noexcept
73
{
74
if
(
this
== &other)
75
return
*
this
;
76
77
m_size = other.m_size;
78
for
(
size_t
i = 0; i < m_size; ++i)
79
std::construct_at(get(i), std::move(*other.get(i)));
80
81
other.clear();
82
return
*
this
;
83
}
84
85
static_disposables_container(static_disposables_container&& other)
noexcept
86
{
87
*
this
= std::move(other);
88
}
89
90
~static_disposables_container()
noexcept
91
{
92
clear();
93
}
94
95
void
push_back(
const
rpp::disposable_wrapper
& d)
96
{
97
if
(m_size >= Count)
98
throw
rpp::utils::more_disposables_than_expected
{
"static_disposables_container obtained more disposables than expected"
};
99
std::construct_at(get(m_size++), d);
100
}
101
102
void
push_back(
rpp::disposable_wrapper
&& d)
103
{
104
if
(m_size >= Count)
105
throw
rpp::utils::more_disposables_than_expected
{
"static_disposables_container obtained more disposables than expected"
};
106
std::construct_at(get(m_size++), std::move(d));
107
}
108
109
void
remove(
const
rpp::disposable_wrapper
& d)
110
{
111
for
(
size_t
i = 0; i < m_size;)
112
{
113
if
(*get(i) != d)
114
{
115
++i;
116
continue
;
117
}
118
119
for
(
size_t
j = i + 1; j < m_size; ++j)
120
*get(j - 1) = std::move(*get(j));
121
122
std::destroy_at(get(--m_size));
123
}
124
}
125
126
void
dispose()
const
127
{
128
for
(
size_t
i = 0; i < m_size; ++i)
129
{
130
get(i)->dispose();
131
}
132
}
133
134
void
clear()
135
{
136
for
(
size_t
i = 0; i < m_size; ++i)
137
std::destroy_at(get(i));
138
m_size = 0;
139
}
140
141
private
:
142
const
rpp::disposable_wrapper
* get(
size_t
i)
const
143
{
144
return
std::launder(
reinterpret_cast<
const
rpp::disposable_wrapper
*
>
(&m_data[i *
sizeof
(
rpp::disposable_wrapper
)]));
145
}
146
rpp::disposable_wrapper
* get(
size_t
i)
147
{
148
return
std::launder(
reinterpret_cast<
rpp::disposable_wrapper
*
>
(&m_data[i *
sizeof
(
rpp::disposable_wrapper
)]));
149
}
150
151
private
:
152
alignas
(
rpp::disposable_wrapper
) std::byte m_data[
sizeof
(
rpp::disposable_wrapper
) * Count]{};
153
size_t
m_size{};
154
};
155
156
template
<>
157
class
static_disposables_container<0>
158
{
159
public
:
160
[[noreturn]]
static
void
push_back(
const
rpp::disposable_wrapper
&)
161
{
162
throw
rpp::utils::more_disposables_than_expected
{
"static_disposables_container<0> expected no disposables but received at least one"
};
163
}
164
165
static
void
remove(
const
rpp::disposable_wrapper
&) { }
166
static
void
dispose() { }
167
static
void
clear() { }
168
};
169
}
// namespace rpp::details::disposables
rpp::disposable_wrapper
disposable_wrapper_impl< interface_disposable > disposable_wrapper
Wrapper to keep "simple" disposable. Specialization of rpp::disposable_wrapper_impl.
Definition
fwd.hpp:34
rpp::utils::more_disposables_than_expected
Definition
exceptions.hpp:23
src
rpp
rpp
disposables
details
container.hpp
Generated by
1.17.0