9 #include "../global.hpp"
10 #include "./types_util.hpp"
11 #include "./delayed_delete_vector.hpp"
20 #if defined(MDDS_UNIT_TEST) || defined(MDDS_MULTI_TYPE_VECTOR_DEBUG)
24 namespace mdds {
namespace mtv {
26 using element_t = int;
28 constexpr element_t element_type_empty = -1;
30 constexpr element_t element_type_reserved_start = 0;
31 constexpr element_t element_type_reserved_end = 49;
33 constexpr element_t element_type_user_start = 50;
41 enum class lu_factor_t : int
49 sse2_x64_lu4 = 1 << 8 | 4,
50 sse2_x64_lu8 = 1 << 8 | 8,
51 sse2_x64_lu16 = 1 << 8 | 16,
53 avx2_x64_lu4 = 2 << 8 | 4,
54 avx2_x64_lu8 = 2 << 8 | 8,
76 enum class trace_method_t : int
80 accessor_with_pos_hint = 1 << 8 | 1,
82 mutator_with_pos_hint = 1 << 8 | 2,
92 trace_method_t type = trace_method_t::unspecified;
136 friend element_t get_block_type(
const base_element_block&) noexcept;
140 base_element_block(element_t _t) noexcept : type(_t)
147 template<
typename ValueT>
156 template<
typename BlockT,
typename =
void>
159 using store_type =
typename BlockT::store_type;
161 BlockT* operator()(
const BlockT& blk)
const
163 auto bt = get_block_type(blk);
164 std::ostringstream os;
165 os <<
"cloning of this block type is not implemented (type=" << bt <<
")";
175 template<
typename BlockT>
176 struct clone_block<BlockT, std::enable_if_t<std::is_copy_constructible<BlockT>::value>>
178 using store_type =
typename BlockT::store_type;
180 BlockT* operator()(
const BlockT& src)
const
182 return new BlockT(src);
192 template<
typename BlockT>
193 struct clone_block<BlockT, std::void_t<decltype(clone_value<typename BlockT::value_type>{})>>
195 using store_type =
typename BlockT::store_type;
196 using value_type =
typename BlockT::value_type;
199 BlockT* operator()(
const BlockT& src)
const
201 auto dest_blk = std::make_unique<BlockT>();
202 auto cloned(src.store());
205 std::transform(
typename CV::exec_policy{}, cloned.begin(), cloned.end(), cloned.begin(),
CV{});
207 std::transform(cloned.begin(), cloned.end(), cloned.begin(),
CV{});
209 dest_blk->store().swap(cloned);
210 return dest_blk.release();
214 template<
typename Self, element_t TypeId,
typename ValueT,
template<
typename,
typename>
class StoreT>
218 using store_type = StoreT<ValueT, std::allocator<ValueT>>;
219 static constexpr element_t block_type = TypeId;
231 template<
typename Iter>
236 typedef typename store_type::iterator iterator;
237 typedef typename store_type::reverse_iterator reverse_iterator;
238 typedef typename store_type::const_iterator const_iterator;
239 typedef typename store_type::const_reverse_iterator const_reverse_iterator;
240 typedef ValueT value_type;
242 const store_type& store()
const noexcept
247 store_type& store() noexcept
253 template<
bool Mutable>
254 class base_range_type
256 using elem_block_type = mdds::detail::mutable_t<base_element_block, Mutable>;
257 elem_block_type& m_blk;
260 using iter_type = std::conditional_t<Mutable, iterator, const_iterator>;
262 base_range_type(elem_block_type& blk) : m_blk(blk)
267 return element_block::begin(m_blk);
272 return element_block::end(m_blk);
276 static constexpr
bool nothrow_eq_comparable_v = noexcept(std::declval<store_type>() == std::declval<store_type>());
279 using range_type = base_range_type<true>;
280 using const_range_type = base_range_type<false>;
282 bool operator==(
const Self& r)
const noexcept(nothrow_eq_comparable_v)
284 return m_array == r.m_array;
287 bool operator!=(
const Self& r)
const noexcept(nothrow_eq_comparable_v)
289 return !operator==(r);
292 static const value_type& at(
const base_element_block& block,
typename store_type::size_type pos)
294 return get(block).m_array.at(pos);
299 return get(block).m_array.at(pos);
304 return get(block).m_array.data();
309 return get(block).m_array.size();
314 return get(block).m_array.begin();
319 return get(block).m_array.end();
324 return get(block).m_array.begin();
329 return get(block).m_array.end();
334 return get(block).m_array.begin();
339 return get(block).m_array.end();
344 return get(block).m_array.rbegin();
349 return get(block).m_array.rend();
354 return get(block).m_array.rbegin();
359 return get(block).m_array.rend();
364 return get(block).m_array.rbegin();
369 return get(block).m_array.rend();
374 return const_range_type(block);
379 return range_type(block);
384 #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
387 std::ostringstream os;
388 os <<
"incorrect block type: expected block type=" << TypeId
393 return static_cast<Self&
>(block);
398 #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
401 std::ostringstream os;
402 os <<
"incorrect block type: expected block type=" << TypeId
407 return static_cast<const Self&
>(block);
412 get(blk).m_array[pos] = val;
417 val =
get(blk).m_array[pos];
422 return get(blk).m_array[pos];
425 template<
typename T = ValueT>
428 get(blk).m_array.push_back(std::forward<T>(val));
431 template<
typename... Args>
434 get(blk).m_array.emplace_back(std::forward<Args>(args)...);
439 store_type& blk2 =
get(blk).m_array;
440 blk2.insert(blk2.begin(), val);
443 static Self* create_block(
size_t init_size)
445 return new Self(init_size);
450 delete static_cast<const Self*
>(p);
455 store_type& st =
get(blk).m_array;
460 if (new_size < (detail::get_block_capacity(st) / 2))
461 detail::shrink_to_fit(st);
464 #ifdef MDDS_UNIT_TEST
467 const store_type& blk2 =
get(blk).m_array;
468 for (
const auto& val : blk2)
469 std::cout << val <<
" ";
471 std::cout << std::endl;
480 store_type& blk2 =
get(blk).m_array;
481 blk2.erase(blk2.begin() + pos);
486 store_type& blk2 =
get(blk).m_array;
487 blk2.erase(blk2.begin() + pos, blk2.begin() + pos + size);
492 store_type& d =
get(dest).m_array;
493 const store_type& s =
get(src).m_array;
494 d.insert(d.end(), s.begin(), s.end());
497 static void append_values_from_block(
500 store_type& d =
get(dest).m_array;
501 const store_type& s =
get(src).m_array;
502 std::pair<const_iterator, const_iterator> its = get_iterator_pair(s, begin_pos, len);
503 detail::reserve(d, d.size() + len);
504 d.insert(d.end(), its.first, its.second);
507 static void assign_values_from_block(
510 store_type& d =
get(dest).m_array;
511 const store_type& s =
get(src).m_array;
512 std::pair<const_iterator, const_iterator> its = get_iterator_pair(s, begin_pos, len);
513 d.assign(its.first, its.second);
516 static void prepend_values_from_block(
519 store_type& d =
get(dest).m_array;
520 const store_type& s =
get(src).m_array;
521 std::pair<const_iterator, const_iterator> its = get_iterator_pair(s, begin_pos, len);
522 detail::reserve(d, d.size() + len);
523 d.insert(d.begin(), its.first, its.second);
528 store_type& st1 =
get(blk1).m_array;
529 store_type& st2 =
get(blk2).m_array;
530 assert(pos1 + len <= st1.size());
531 assert(pos2 + len <= st2.size());
533 typename store_type::iterator it1 = st1.begin(), it2 = st2.begin();
534 std::advance(it1, pos1);
535 std::advance(it2, pos2);
537 for (
size_t i = 0; i < len; ++i, ++it1, ++it2)
539 value_type v1 = *it1, v2 = *it2;
547 return get(left) ==
get(right);
550 template<
typename Iter>
551 static void set_values(
base_element_block& block,
size_t pos,
const Iter& it_begin,
const Iter& it_end)
553 store_type& d =
get(block).m_array;
554 typename store_type::iterator it_dest = d.begin();
555 std::advance(it_dest, pos);
556 for (Iter it = it_begin; it != it_end; ++it, ++it_dest)
560 template<
typename Iter>
561 static void append_values(
base_element_block& block,
const Iter& it_begin,
const Iter& it_end)
563 store_type& d =
get(block).m_array;
564 typename store_type::iterator it = d.end();
565 d.insert(it, it_begin, it_end);
568 template<
typename Iter>
569 static void prepend_values(
base_element_block& block,
const Iter& it_begin,
const Iter& it_end)
571 store_type& d =
get(block).m_array;
572 d.insert(d.begin(), it_begin, it_end);
575 template<
typename Iter>
576 static void assign_values(
base_element_block& dest,
const Iter& it_begin,
const Iter& it_end)
578 store_type& d =
get(dest).m_array;
579 d.assign(it_begin, it_end);
582 template<
typename Iter>
583 static void insert_values(
base_element_block& block,
size_t pos,
const Iter& it_begin,
const Iter& it_end)
585 store_type& blk =
get(block).m_array;
586 blk.insert(blk.begin() + pos, it_begin, it_end);
591 const store_type& blk =
get(block).m_array;
592 return detail::get_block_capacity(blk);
597 store_type& blk =
get(block).m_array;
598 detail::reserve(blk, size);
603 store_type& blk =
get(block).m_array;
604 detail::shrink_to_fit(blk);
608 static std::pair<const_iterator, const_iterator> get_iterator_pair(
609 const store_type& array,
size_t begin_pos,
size_t len)
611 assert(begin_pos + len <= array.size());
612 const_iterator it = array.begin();
613 std::advance(it, begin_pos);
614 const_iterator it_end = it;
615 std::advance(it_end, len);
616 return std::pair<const_iterator, const_iterator>(it, it_end);
620 template<
typename Self, element_t TypeId,
typename ValueT,
template<
typename,
typename>
class StoreT>
633 template<
typename Iter>
638 using base_type::get;
643 return new Self(
get(blk));
655 template<
typename Self, element_t TypeId,
typename ValueT,
template<
typename,
typename>
class StoreT>
668 template<
typename Iter>
673 using base_type::get;
705 template<element_t TypeId,
typename ValueT,
template<
typename,
typename>
class StoreT =
delayed_delete_vector>
719 template<
typename Iter>
723 static self_type* create_block_with_value(
size_t init_size,
const ValueT& val)
728 template<
typename Iter>
729 static self_type* create_block_with_values(
const Iter& it_begin,
const Iter& it_end)
744 template<element_t TypeId,
typename ValueT,
template<
typename,
typename>
class StoreT =
delayed_delete_vector>
751 using base_type::get;
752 using base_type::m_array;
753 using base_type::reserve;
754 using base_type::set_value;
762 detail::reserve(m_array, r.m_array.size());
763 for (
const auto& v : r.m_array)
764 m_array.push_back(
new ValueT(*v));
767 template<
typename Iter>
773 std::for_each(m_array.begin(), m_array.end(), std::default_delete<ValueT>());
776 static self_type* create_block_with_value(
size_t init_size, ValueT* val)
780 throw general_error(
"You can't create a managed block with initial value.");
782 std::unique_ptr<self_type> blk = std::make_unique<self_type>(init_size);
784 set_value(*blk, 0, val);
786 return blk.release();
789 template<
typename Iter>
790 static self_type* create_block_with_values(
const Iter& it_begin,
const Iter& it_end)
798 typename managed_element_block::store_type::iterator it = blk.m_array.begin() + pos;
799 typename managed_element_block::store_type::iterator it_end = it + len;
800 std::for_each(it, it_end, std::default_delete<ValueT>());
809 template<element_t TypeId,
typename ValueT,
template<
typename,
typename>
class StoreT =
delayed_delete_vector>
812 noncopyable_managed_element_block<TypeId, ValueT, StoreT>, TypeId, ValueT*, StoreT>
817 using base_type::get;
818 using base_type::m_array;
819 using base_type::set_value;
826 template<
typename Iter>
832 std::for_each(m_array.begin(), m_array.end(), std::default_delete<ValueT>());
835 static self_type* create_block_with_value(
size_t init_size, ValueT* val)
839 throw general_error(
"You can't create a managed block with initial value.");
841 std::unique_ptr<self_type> blk = std::make_unique<self_type>(init_size);
843 set_value(*blk, 0, val);
845 return blk.release();
848 template<
typename Iter>
849 static self_type* create_block_with_values(
const Iter& it_begin,
const Iter& it_end)
857 typename noncopyable_managed_element_block::store_type::iterator it = blk.m_array.begin() + pos;
858 typename noncopyable_managed_element_block::store_type::iterator it_end = it + len;
859 std::for_each(it, it_end, std::default_delete<ValueT>());
864 const auto& array1 =
get(left).m_array;
865 const auto& array2 =
get(right).m_array;
867 if (array1.size() != array2.size())
870 return std::equal(array1.begin(), array1.end(), array2.begin(), [](
const ValueT* p1,
const ValueT* p2) {
878 template<
typename Blk>
881 auto it = Blk::cbegin(data);
882 std::advance(it, offset);
886 template<
typename Blk>
889 return Blk::at(data, offset);
892 template<
typename Blk>
895 typename mdds::mtv::detail::has_std_vector_bool_store<Blk>::type v;
896 return get_block_element_at<Blk>(data, offset, v);
Definition: types.hpp:120
Definition: types.hpp:810
const char * filepath
Definition: types.hpp:111
Definition: types.hpp:148
friend element_t get_block_type(const base_element_block &) noexcept
Definition: types.hpp:696
std::string function_args
Definition: types.hpp:108
Definition: types.hpp:621
Definition: types.hpp:745
int line_number
Definition: types.hpp:114
const void * instance
Definition: types.hpp:99
Definition: types.hpp:215
Definition: types.hpp:706
Definition: types.hpp:157
Definition: global.hpp:59
const char * function_name
Definition: types.hpp:102
Definition: types_util.hpp:142
Definition: cref_wrapper.hpp:12
Definition: types.hpp:656
Definition: delayed_delete_vector.hpp:21
Definition: types.hpp:134