mdds
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 
19 namespace mdds { namespace mtv { namespace soa {
20 
48 template<typename Traits = mdds::mtv::default_traits>
50 {
51 public:
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 
74 private:
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 
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 
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 
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 
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 
250 public:
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 
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 
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 
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 
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 
1158  void shrink_to_fit();
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 
1182 private:
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 
1490 private:
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: */
static mtv::element_t get_element_type(const T &elem)
Definition: iterator_node.hpp:18
iterator transfer(size_type start_pos, size_type end_pos, multi_type_vector &dest, size_type dest_pos)
iterator set_empty(size_type start_pos, size_type end_pos)
Definition: iterator.hpp:210
multi_type_vector clone() const
static position_type next_position(const position_type &pos)
static position_type advance_position(const position_type &pos, int steps)
iterator release_range(size_type start_pos, size_type end_pos)
Definition: iterator_node.hpp:85
static _Blk::value_type get(const const_position_type &pos)
static size_type logical_position(const const_position_type &pos) noexcept(std::is_fundamental_v< size_type >)
iterator set(size_type pos, const T &value)
Definition: types.hpp:215
Definition: iterator_node.hpp:74
void erase(size_type start_pos, size_type end_pos)
void resize(size_type new_size)
mtv::element_t get_type(size_type pos) const
iterator emplace_back(Args &&...args)
Definition: cref_wrapper.hpp:12
iterator insert_empty(size_type pos, size_type length)
typename mtv_traits::event_func event_func
Definition: main.hpp:72
position_type position(size_type pos)
bool is_empty(size_type pos) const
Definition: types.hpp:134
multi_type_vector() noexcept(nothrow_default_constructible_v)
iterator insert(size_type pos, const T &it_begin, const T &it_end)
void swap(multi_type_vector &other) noexcept(nothrow_swappable_v)
Definition: main.hpp:49