mdds
Loading...
Searching...
No Matches
soa/main.hpp
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3// SPDX-FileCopyrightText: 2021 - 2025 Kohei Yoshida
4//
5// SPDX-License-Identifier: MIT
6
7#pragma once
8
9#include "../../global.hpp"
10#include "../types.hpp"
11#include "../util.hpp"
12#include "./block_util.hpp"
13#include "./iterator.hpp"
14
15#ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
16#include <iostream>
17#endif
18
19namespace mdds { namespace mtv { namespace soa {
20
48template<typename Traits = mdds::mtv::default_traits>
49class multi_type_vector
50{
51public:
52 using size_type = std::size_t;
53 using block_funcs = typename Traits::block_funcs;
54
72 using event_func = typename Traits::event_func;
73
74private:
75 struct block_slot_type
76 {
77 size_type position = 0;
78 size_type size = 0;
80
81 block_slot_type() noexcept(std::is_fundamental_v<size_type>)
82 {}
83 block_slot_type(size_type _position, size_type _size) noexcept(std::is_fundamental_v<size_type>)
84 : position(_position), size(_size)
85 {}
86 };
87
88 struct blocks_type
89 {
90 std::vector<size_type> positions;
91 std::vector<size_type> sizes;
92 std::vector<base_element_block*> element_blocks;
93
94 static constexpr bool nothrow_default_constructible_v =
95 std::is_nothrow_default_constructible_v<std::vector<size_type>> &&
96 std::is_nothrow_default_constructible_v<std::vector<base_element_block*>>;
97
98 static constexpr bool nothrow_move_constructible_v =
99 std::is_nothrow_move_constructible_v<std::vector<size_type>> &&
100 std::is_nothrow_move_constructible_v<std::vector<base_element_block*>>;
101
102 static constexpr bool nothrow_value_swappable_v =
103 noexcept(std::swap(std::declval<size_type&>(), std::declval<size_type&>())) &&
104 noexcept(std::swap(std::declval<base_element_block*&>(), std::declval<base_element_block*&>()));
105
106 static constexpr bool nothrow_swappable_v = std::is_nothrow_swappable_v<std::vector<size_type>> &&
107 std::is_nothrow_swappable_v<std::vector<base_element_block*>>;
108
109 blocks_type() noexcept(nothrow_default_constructible_v);
110 blocks_type(mtv::detail::clone_construction_type, const blocks_type& other);
111 blocks_type(const blocks_type& other);
112 blocks_type(blocks_type&& other) noexcept(nothrow_move_constructible_v);
113
114 void pop_back()
115 {
116 positions.pop_back();
117 sizes.pop_back();
118 element_blocks.pop_back();
119 }
120
121 void push_back(size_type pos, size_type size, base_element_block* data)
122 {
123 positions.push_back(pos);
124 sizes.push_back(size);
125 element_blocks.push_back(data);
126 }
127
128 void push_back(const block_slot_type& slot)
129 {
130 positions.push_back(slot.position);
131 sizes.push_back(slot.size);
132 element_blocks.push_back(slot.element_block);
133 }
134
135 void erase(size_type index);
136 void erase(size_type index, size_type size);
137 void insert(size_type index, size_type size);
138 void insert(size_type index, size_type pos, size_type size, base_element_block* data);
139 void insert(size_type index, const blocks_type& new_blocks);
140
147 void calc_block_position(size_type index);
148
149 size_type calc_next_block_position(size_type index);
150
151 void swap(size_type index1, size_type index2) noexcept(nothrow_value_swappable_v);
152
153 void swap(blocks_type& other) noexcept(nothrow_swappable_v);
154
155 void reserve(size_type n);
156
157 bool equals(const blocks_type& other) const;
158
159 void clear();
160
161 void check_integrity() const;
162 };
163
164 struct blocks_to_transfer
165 {
166 blocks_type blocks;
167 size_type insert_index = 0;
168 };
169
170 struct iterator_trait
171 {
172 using parent = multi_type_vector;
173 using positions_type = std::vector<size_type>;
174 using sizes_type = std::vector<size_type>;
175 using element_blocks_type = std::vector<base_element_block*>;
176
177 using positions_iterator_type = typename positions_type::iterator;
178 using sizes_iterator_type = typename sizes_type::iterator;
179 using element_blocks_iterator_type = typename element_blocks_type::iterator;
180
181 using private_data_update = mdds::detail::mtv::private_data_forward_update<multi_type_vector, size_type>;
182 };
183
184 struct const_iterator_trait
185 {
186 using parent = multi_type_vector;
187 using positions_type = std::vector<size_type>;
188 using sizes_type = std::vector<size_type>;
189 using element_blocks_type = std::vector<base_element_block*>;
190
191 using positions_iterator_type = typename positions_type::const_iterator;
192 using sizes_iterator_type = typename sizes_type::const_iterator;
193 using element_blocks_iterator_type = typename element_blocks_type::const_iterator;
194
195 using private_data_update = mdds::detail::mtv::private_data_forward_update<multi_type_vector, size_type>;
196 };
197
198 struct reverse_iterator_trait
199 {
200 using parent = multi_type_vector;
201 using positions_type = std::vector<size_type>;
202 using sizes_type = std::vector<size_type>;
203 using element_blocks_type = std::vector<base_element_block*>;
204
205 using positions_iterator_type = typename positions_type::reverse_iterator;
206 using sizes_iterator_type = typename sizes_type::reverse_iterator;
207 using element_blocks_iterator_type = typename element_blocks_type::reverse_iterator;
208
209 using private_data_update = mdds::detail::mtv::private_data_no_update<multi_type_vector, size_type>;
210 };
211
212 struct const_reverse_iterator_trait
213 {
214 using parent = multi_type_vector;
215 using positions_type = std::vector<size_type>;
216 using sizes_type = std::vector<size_type>;
217 using element_blocks_type = std::vector<base_element_block*>;
218
219 using positions_iterator_type = typename positions_type::const_reverse_iterator;
220 using sizes_iterator_type = typename sizes_type::const_reverse_iterator;
221 using element_blocks_iterator_type = typename element_blocks_type::const_reverse_iterator;
222
223 using private_data_update = mdds::detail::mtv::private_data_no_update<multi_type_vector, size_type>;
224 };
225
226 struct element_block_deleter
227 {
228 void operator()(const base_element_block* p)
229 {
230 block_funcs::delete_block(p);
231 }
232 };
233
234 static constexpr bool nothrow_default_constructible_v = std::is_nothrow_default_constructible_v<event_func> &&
235 std::is_nothrow_default_constructible_v<blocks_type> &&
236 std::is_nothrow_default_constructible_v<size_type>;
237
238 static constexpr bool nothrow_move_constructible_v = std::is_nothrow_move_constructible_v<event_func> &&
239 std::is_nothrow_move_constructible_v<blocks_type> &&
240 std::is_nothrow_move_constructible_v<size_type>;
241
242 static constexpr bool nothrow_swappable_v = std::is_nothrow_swappable_v<event_func> &&
243 std::is_nothrow_swappable_v<size_type> &&
244 std::is_nothrow_swappable_v<blocks_type>;
245
246 static constexpr bool nothrow_move_assignable_v = nothrow_move_constructible_v && nothrow_swappable_v;
247
248 multi_type_vector(mtv::detail::clone_construction_type, const multi_type_vector& other);
249
250public:
251 using iterator = detail::iterator_base<iterator_trait>;
252 using const_iterator = detail::const_iterator_base<const_iterator_trait, iterator>;
253
254 using reverse_iterator = detail::iterator_base<reverse_iterator_trait>;
255 using const_reverse_iterator = detail::const_iterator_base<const_reverse_iterator_trait, reverse_iterator>;
256
257 using position_type = std::pair<iterator, size_type>;
258 using const_position_type = std::pair<const_iterator, size_type>;
259
276
285 static position_type next_position(const position_type& pos);
286
296 static position_type advance_position(const position_type& pos, int steps);
297
306 static const_position_type next_position(const const_position_type& pos);
307
317 static const_position_type advance_position(const const_position_type& pos, int steps);
318
327 static size_type logical_position(const const_position_type& pos) noexcept(std::is_fundamental_v<size_type>);
328
337 template<typename _Blk>
338 static typename _Blk::value_type get(const const_position_type& pos);
339
340 event_func& event_handler();
341 const event_func& event_handler() const;
342
346 multi_type_vector() noexcept(nothrow_default_constructible_v);
347
354 multi_type_vector(const event_func& hdl);
355
362 multi_type_vector(event_func&& hdl);
363
371 multi_type_vector(size_type init_size);
372
382 template<typename T>
383 multi_type_vector(size_type init_size, const T& value);
384
398 template<typename T>
399 multi_type_vector(size_type init_size, const T& it_begin, const T& it_end);
400
406 multi_type_vector(const multi_type_vector& other);
407
413 multi_type_vector(multi_type_vector&& other) noexcept(nothrow_move_constructible_v);
414
418 ~multi_type_vector();
419
433 multi_type_vector clone() const;
434
451 position_type position(size_type pos);
452
472 position_type position(const iterator& pos_hint, size_type pos);
473
487 const_position_type position(size_type pos) const;
488
505 const_position_type position(const const_iterator& pos_hint, size_type pos) const;
506
531 iterator transfer(size_type start_pos, size_type end_pos, multi_type_vector& dest, size_type dest_pos);
532
560 iterator transfer(
561 const iterator& pos_hint, size_type start_pos, size_type end_pos, multi_type_vector& dest, size_type dest_pos);
562
579 template<typename T>
580 iterator set(size_type pos, const T& value);
581
614 template<typename T>
615 iterator set(const iterator& pos_hint, size_type pos, const T& value);
616
638 template<typename T>
639 iterator set(size_type pos, const T& it_begin, const T& it_end);
640
678 template<typename T>
679 iterator set(const iterator& pos_hint, size_type pos, const T& it_begin, const T& it_end);
680
697 template<typename T>
698 iterator push_back(T&& value);
699
707 iterator push_back_empty();
708
726 template<typename T, typename... Args>
727 iterator emplace_back(Args&&... args);
728
750 template<typename T>
751 iterator insert(size_type pos, const T& it_begin, const T& it_end);
752
790 template<typename T>
791 iterator insert(const iterator& pos_hint, size_type pos, const T& it_begin, const T& it_end);
792
800 mtv::element_t get_type(size_type pos) const;
801
813 bool is_empty(size_type pos) const;
814
828 iterator set_empty(size_type start_pos, size_type end_pos);
829
859 iterator set_empty(const iterator& pos_hint, size_type start_pos, size_type end_pos);
860
876 void erase(size_type start_pos, size_type end_pos);
877
896 iterator insert_empty(size_type pos, size_type length);
897
932 iterator insert_empty(const iterator& pos_hint, size_type pos, size_type length);
933
938 void clear();
939
945 size_type size() const;
946
964 size_type block_size() const;
965
971 bool empty() const;
972
983 template<typename T>
984 void get(size_type pos, T& value) const;
985
997 template<typename T>
998 T get(size_type pos) const;
999
1014 template<typename T>
1015 T release(size_type pos);
1016
1033 template<typename T>
1034 iterator release(size_type pos, T& value);
1035
1055 template<typename T>
1056 iterator release(const iterator& pos_hint, size_type pos, T& value);
1057
1066 void release();
1067
1083 iterator release_range(size_type start_pos, size_type end_pos);
1084
1109 iterator release_range(const iterator& pos_hint, size_type start_pos, size_type end_pos);
1110
1111 iterator begin();
1112 iterator end();
1113
1114 const_iterator begin() const;
1115 const_iterator end() const;
1116
1117 const_iterator cbegin() const;
1118 const_iterator cend() const;
1119
1120 reverse_iterator rbegin();
1121 reverse_iterator rend();
1122
1123 const_reverse_iterator rbegin() const;
1124 const_reverse_iterator rend() const;
1125
1126 const_reverse_iterator crbegin() const;
1127 const_reverse_iterator crend() const;
1128
1136 void resize(size_type new_size);
1137
1143 void swap(multi_type_vector& other) noexcept(nothrow_swappable_v);
1144
1153 void swap(size_type start_pos, size_type end_pos, multi_type_vector& other, size_type other_pos);
1154
1159
1160 bool operator==(const multi_type_vector& other) const;
1161 bool operator!=(const multi_type_vector& other) const;
1162
1163 multi_type_vector& operator=(const multi_type_vector& other);
1164 multi_type_vector& operator=(multi_type_vector&& other) noexcept(nothrow_move_assignable_v);
1165
1173 template<typename T>
1174 static mtv::element_t get_element_type(const T& elem);
1175
1176#ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
1177 void dump_blocks(std::ostream& os) const;
1178
1179 void check_block_integrity() const;
1180#endif
1181
1182private:
1183 void delete_element_block(size_type block_index);
1184
1185 void delete_element_blocks(size_type start, size_type end);
1186
1187 template<typename T>
1188 void get_impl(size_type pos, T& value) const;
1189
1190 template<typename T>
1191 bool set_cells_precheck(size_type row, const T& it_begin, const T& it_end, size_type& end_pos);
1192
1193 template<typename T>
1194 iterator set_impl(size_type pos, size_type block_index, const T& value);
1195
1196 template<typename T>
1197 iterator release_impl(size_type pos, size_type block_index, T& value);
1198
1199 void swap_impl(
1200 multi_type_vector& other, size_type start_pos, size_type end_pos, size_type other_pos, size_type block_index1,
1201 size_type block_index2, size_type dblock_index1, size_type dblock_index2);
1202
1203 void swap_single_block(
1204 multi_type_vector& other, size_type start_pos, size_type end_pos, size_type other_pos, size_type block_index,
1205 size_type other_block_index);
1206
1207 void swap_single_to_multi_blocks(
1208 multi_type_vector& other, size_type start_pos, size_type end_pos, size_type other_pos, size_type block_index,
1209 size_type dst_block_index1, size_type dst_block_index2);
1210
1211 void swap_multi_to_multi_blocks(
1212 multi_type_vector& other, size_type start_pos, size_type end_pos, size_type other_pos, size_type block_index1,
1213 size_type block_index2, size_type dblock_index1, size_type dblock_index2);
1214
1215 template<typename T>
1216 iterator insert_cells_impl(size_type row, size_type block_index, const T& it_begin, const T& it_end);
1217
1218 void resize_impl(size_type new_size);
1219
1224 iterator transfer_multi_blocks(
1225 size_type start_pos, size_type end_pos, size_type block_index1, size_type block_index2, multi_type_vector& dest,
1226 size_type dest_pos);
1227
1236 iterator set_empty_impl(size_type start_pos, size_type end_pos, size_type block_index1, bool overwrite);
1237
1238 iterator set_empty_in_single_block(size_type start_row, size_type end_row, size_type block_index, bool overwrite);
1239
1249 iterator set_empty_in_multi_blocks(
1250 size_type start_row, size_type end_row, size_type block_index1, size_type block_index2, bool overwrite);
1251
1252 void erase_impl(size_type start_pos, size_type end_pos);
1253 void erase_in_single_block(size_type start_pos, size_type end_pos, size_type block_index);
1254
1260 iterator insert_empty_impl(size_type pos, size_type block_index, size_type length);
1261
1262 void insert_blocks_at(size_type position, size_type insert_pos, blocks_type& new_blocks);
1263
1264 void prepare_blocks_to_transfer(
1265 blocks_to_transfer& bucket, size_type block_index1, size_type offset1, size_type block_index2,
1266 size_type offset2);
1267
1268 iterator set_whole_block_empty(size_type block_index, bool overwrite);
1269
1270 template<typename T>
1271 iterator push_back_impl(T&& value);
1272
1273 template<typename T, typename... Args>
1274 iterator emplace_back_impl(Args&&... args);
1275
1276 template<typename T>
1277 iterator set_cells_impl(
1278 size_type row, size_type end_row, size_type block_index1, const T& it_begin, const T& it_end);
1279
1280 template<typename T>
1281 iterator set_cells_to_single_block(
1282 size_type start_row, size_type end_row, size_type block_index, const T& it_begin, const T& it_end);
1283
1284 template<typename T>
1285 iterator set_cells_to_multi_blocks(
1286 size_type start_row, size_type end_row, size_type block_index1, size_type block_index2, const T& it_begin,
1287 const T& it_end);
1288
1289 template<typename T>
1290 iterator set_cells_to_multi_blocks_block1_non_equal(
1291 size_type start_row, size_type end_row, size_type block_index1, size_type block_index2, const T& it_begin,
1292 const T& it_end);
1293
1294 template<typename T>
1295 iterator set_cells_to_multi_blocks_block1_non_empty(
1296 size_type start_row, size_type end_row, size_type block_index1, size_type block_index2, const T& it_begin,
1297 const T& it_end);
1298
1299 template<typename T>
1300 iterator set_cell_to_empty_block(size_type block_index, size_type pos_in_block, const T& cell);
1301
1302 template<typename T>
1303 iterator set_cell_to_non_empty_block_of_size_one(size_type block_index, const T& cell);
1304
1314 size_type get_block_position(size_type row, size_type start_block_index = 0) const;
1315
1320 size_type get_block_position(const typename value_type::private_data& pos_data, size_type row) const;
1321
1322 template<typename T>
1323 void create_new_block_with_new_cell(size_type block_index, T&& cell);
1324
1325 template<typename T, typename... Args>
1326 void create_new_block_with_emplace_back(size_type block_index, const T& t, Args&&... args);
1327
1328 template<typename T>
1329 void append_cell_to_block(size_type block_index, const T& cell);
1330
1338 template<typename T>
1339 bool append_to_prev_block(
1340 size_type block_index, element_t cat, size_type length, const T& it_begin, const T& it_end);
1341
1342 template<typename T>
1343 void insert_cells_to_middle(size_type row, size_type block_index, const T& it_begin, const T& it_end);
1344
1345 template<typename T>
1346 iterator set_cell_to_middle_of_block(size_type block_index, size_type pos_in_block, const T& cell);
1347
1353 template<typename T>
1354 void set_cell_to_top_of_data_block(size_type block_index, const T& cell);
1355
1356 template<typename T>
1357 void set_cell_to_bottom_of_data_block(size_type block_index, const T& cell);
1358
1359 iterator transfer_impl(
1360 size_type start_pos, size_type end_pos, size_type block_index1, multi_type_vector& dest, size_type dest_pos);
1361
1365 iterator transfer_single_block(
1366 size_type start_pos, size_type end_pos, size_type block_index1, multi_type_vector& dest, size_type dest_pos);
1367
1376 size_type merge_with_adjacent_blocks(size_type block_index);
1377
1385 bool merge_with_next_block(size_type block_index);
1386
1400 size_type set_new_block_to_middle(
1401 size_type block_index, size_type offset, size_type new_block_size, bool overwrite);
1402
1412 bool is_previous_block_of_type(size_type block_index, element_t cat) const;
1413
1423 bool is_next_block_of_type(size_type block_index, element_t cat) const;
1424
1446 base_element_block* exchange_elements(
1447 const base_element_block& src_data, size_type src_offset, size_type dst_index, size_type dst_offset,
1448 size_type len);
1449
1450 void exchange_elements(
1451 const base_element_block& src_blk, size_type src_offset, size_type dst_index1, size_type dst_offset1,
1452 size_type dst_index2, size_type dst_offset2, size_type len, blocks_type& new_blocks);
1453
1454 bool append_empty(size_type len);
1455
1456 inline iterator get_iterator(size_type block_index)
1457 {
1458 auto iter_pos = m_block_store.positions.begin();
1459 std::advance(iter_pos, block_index);
1460 auto iter_size = m_block_store.sizes.begin();
1461 std::advance(iter_size, block_index);
1462 auto iter_elem = m_block_store.element_blocks.begin();
1463 std::advance(iter_elem, block_index);
1464
1465 return iterator(
1466 {iter_pos, iter_size, iter_elem},
1467 {m_block_store.positions.end(), m_block_store.sizes.end(), m_block_store.element_blocks.end()}, this,
1468 block_index);
1469 }
1470
1471 inline const_iterator get_const_iterator(size_type block_index) const
1472 {
1473 auto iter_pos = m_block_store.positions.cbegin();
1474 std::advance(iter_pos, block_index);
1475 auto iter_size = m_block_store.sizes.cbegin();
1476 std::advance(iter_size, block_index);
1477 auto iter_elem = m_block_store.element_blocks.cbegin();
1478 std::advance(iter_elem, block_index);
1479
1480 return const_iterator(
1481 {iter_pos, iter_size, iter_elem},
1482 {m_block_store.positions.cend(), m_block_store.sizes.cend(), m_block_store.element_blocks.cend()}, this,
1483 block_index);
1484 }
1485
1486#ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
1487 void debug_check_full(std::string_view location);
1488#endif
1489
1490private:
1491 using adjust_block_positions_func = detail::adjust_block_positions<blocks_type, Traits::loop_unrolling>;
1492
1493 event_func m_hdl_event;
1494 blocks_type m_block_store;
1495 size_type m_cur_size;
1496
1497#ifdef MDDS_MULTI_TYPE_VECTOR_TRACE
1498 mutable int m_trace_call_depth = 0;
1499#endif
1500};
1501
1502}}} // namespace mdds::mtv::soa
1503
1504#include "main_def.inl"
1505
1506/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Definition types.hpp:135
Definition types.hpp:216
iterator set(size_type pos, const T &value)
iterator release_range(size_type start_pos, size_type end_pos)
static const_position_type advance_position(const const_position_type &pos, int steps)
static position_type advance_position(const position_type &pos, int steps)
iterator insert_empty(size_type pos, size_type length)
static const_position_type next_position(const const_position_type &pos)
position_type position(size_type pos)
iterator insert(size_type pos, const T &it_begin, const T &it_end)
static _Blk::value_type get(const const_position_type &pos)
typename Traits::event_func event_func
Definition soa/main.hpp:72
iterator transfer(size_type start_pos, size_type end_pos, multi_type_vector &dest, size_type dest_pos)
void erase(size_type start_pos, size_type end_pos)
void swap(multi_type_vector &other) noexcept(nothrow_swappable_v)
iterator emplace_back(Args &&... args)
mdds::detail::mtv::iterator_value_node< multi_type_vector, size_type > value_type
Definition soa/main.hpp:275
static position_type next_position(const position_type &pos)
mtv::element_t get_type(size_type pos) const
static mtv::element_t get_element_type(const T &elem)
static size_type logical_position(const const_position_type &pos) noexcept(std::is_fundamental_v< size_type >)
iterator set_empty(size_type start_pos, size_type end_pos)
multi_type_vector() noexcept(nothrow_default_constructible_v)
Definition iterator_node.hpp:19