mdds
Loading...
Searching...
No Matches
types.hpp
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*************************************************************************
3 *
4 * Copyright (c) 2021 Kohei Yoshida
5 *
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation
8 * files (the "Software"), to deal in the Software without
9 * restriction, including without limitation the rights to use,
10 * copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following
13 * conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 *
27 ************************************************************************/
28
29#ifndef INCLUDED_MDDS_MULTI_TYPE_VECTOR_TYPES_2_HPP
30#define INCLUDED_MDDS_MULTI_TYPE_VECTOR_TYPES_2_HPP
31
32#include "../global.hpp"
33#include "./types_util.hpp"
34
35#include <algorithm>
36#include <cassert>
37#include <memory>
38#include <cstdint>
39#include <vector>
40
41#if defined(MDDS_UNIT_TEST) || defined(MDDS_MULTI_TYPE_VECTOR_DEBUG)
42#include <iostream>
43#include <sstream>
44using std::cerr;
45using std::cout;
46using std::endl;
47#endif
48
49namespace mdds { namespace mtv {
50
51using element_t = int;
52
53constexpr element_t element_type_empty = -1;
54
55constexpr element_t element_type_reserved_start = 0;
56constexpr element_t element_type_reserved_end = 49;
57
58constexpr element_t element_type_user_start = 50;
59
66enum class lu_factor_t : int
67{
68 none = 0,
69 lu4 = 4,
70 lu8 = 8,
71 lu16 = 16,
72 lu32 = 32,
73 sse2_x64 = 1 << 8,
74 sse2_x64_lu4 = 1 << 8 | 4,
75 sse2_x64_lu8 = 1 << 8 | 8,
76 sse2_x64_lu16 = 1 << 8 | 16,
77 avx2_x64 = 2 << 8,
78 avx2_x64_lu4 = 2 << 8 | 4,
79 avx2_x64_lu8 = 2 << 8 | 8,
80};
81
101enum class trace_method_t : int
102{
103 unspecified = 0,
104 accessor = 1,
105 accessor_with_pos_hint = 1 << 8 | 1,
106 mutator = 2,
107 mutator_with_pos_hint = 1 << 8 | 2,
108 constructor = 3,
109 destructor = 4
110};
111
116{
117 trace_method_t type = trace_method_t::unspecified;
118
124 const void* instance = nullptr;
125
127 const char* function_name = nullptr;
128
133 std::string function_args;
134
136 const char* filepath = nullptr;
137
139 int line_number = -1;
140};
141
146{
147public:
148 element_block_error(const std::string& msg) : mdds::general_error(msg)
149 {}
150};
151
153element_t get_block_type(const base_element_block&);
154
160{
161 friend element_t get_block_type(const base_element_block&);
162
163protected:
164 element_t type;
165 base_element_block(element_t _t) : type(_t)
166 {}
167};
168
174template<typename T, typename Allocator = std::allocator<T>>
176{
177 typedef std::vector<T, Allocator> store_type;
178 store_type m_vec;
179 size_t m_front_offset = 0; // number of elements removed from front of array
180public:
181 typedef typename store_type::value_type value_type;
182 typedef typename store_type::size_type size_type;
183 typedef typename store_type::difference_type difference_type;
184 typedef typename store_type::reference reference;
185 typedef typename store_type::const_reference const_reference;
186 typedef typename store_type::pointer pointer;
187 typedef typename store_type::const_pointer const_pointer;
188 typedef typename store_type::iterator iterator;
189 typedef typename store_type::reverse_iterator reverse_iterator;
190 typedef typename store_type::const_iterator const_iterator;
191 typedef typename store_type::const_reverse_iterator const_reverse_iterator;
192
193 delayed_delete_vector() : m_vec()
194 {}
195
196 delayed_delete_vector(size_t n, const T& val) : m_vec(n, val)
197 {}
198
199 delayed_delete_vector(size_t n) : m_vec(n)
200 {}
201
202 template<typename InputIt>
203 delayed_delete_vector(InputIt first, InputIt last) : m_vec(first, last)
204 {}
205
206 iterator begin() noexcept
207 {
208 return m_vec.begin() + m_front_offset;
209 }
210
211 iterator end() noexcept
212 {
213 return m_vec.end();
214 }
215
216 const_iterator begin() const noexcept
217 {
218 return m_vec.begin() + m_front_offset;
219 }
220
221 const_iterator end() const noexcept
222 {
223 return m_vec.end();
224 }
225
226 reverse_iterator rbegin() noexcept
227 {
228 return m_vec.rbegin();
229 }
230
231 const_reverse_iterator rbegin() const noexcept
232 {
233 return m_vec.rbegin();
234 }
235
236 reverse_iterator rend() noexcept
237 {
238 return m_vec.rend() - m_front_offset;
239 }
240
241 const_reverse_iterator rend() const noexcept
242 {
243 return m_vec.rend() - m_front_offset;
244 }
245
246 reference operator[](size_type pos)
247 {
248 return m_vec[pos + m_front_offset];
249 }
250
251 const_reference operator[](size_type pos) const
252 {
253 return m_vec[pos + m_front_offset];
254 }
255
256 reference at(size_type pos)
257 {
258 return m_vec.at(pos + m_front_offset);
259 }
260
261 const_reference at(size_type pos) const
262 {
263 return m_vec.at(pos + m_front_offset);
264 }
265
266 void push_back(const T& value)
267 {
268 m_vec.push_back(value);
269 }
270
271 iterator insert(iterator pos, const T& value)
272 {
273 return m_vec.insert(pos, value);
274 }
275
276 iterator insert(const_iterator pos, T&& value)
277 {
278 return m_vec.insert(pos, std::move(value));
279 }
280
281 template<typename InputIt>
282 void insert(iterator pos, InputIt first, InputIt last)
283 {
284 m_vec.insert(pos, first, last);
285 }
286
287 void resize(size_type count)
288 {
289 clear_removed();
290 m_vec.resize(count);
291 }
292
293 iterator erase(iterator pos)
294 {
295 if (pos == m_vec.begin() + m_front_offset)
296 {
297 ++m_front_offset;
298 return m_vec.begin() + m_front_offset;
299 }
300 else
301 return m_vec.erase(pos);
302 }
303
304 iterator erase(iterator first, iterator last)
305 {
306 return m_vec.erase(first, last);
307 }
308
309 size_type capacity() const noexcept
310 {
311 return m_vec.capacity();
312 }
313
314 void shrink_to_fit()
315 {
316 clear_removed();
317 m_vec.shrink_to_fit();
318 }
319
320 void reserve(size_type new_cap)
321 {
322 clear_removed();
323 m_vec.reserve(new_cap);
324 }
325
326 size_type size() const
327 {
328 return m_vec.size() - m_front_offset;
329 }
330
331 template<typename InputIt>
332 void assign(InputIt first, InputIt last)
333 {
334 clear_removed();
335 m_vec.assign(first, last);
336 }
337
338 T* data()
339 {
340 return m_vec.data() + m_front_offset;
341 }
342
343 const T* data() const
344 {
345 return m_vec.data() + m_front_offset;
346 }
347
348private:
349 void clear_removed()
350 {
351 m_vec.erase(m_vec.begin(), m_vec.begin() + m_front_offset);
352 m_front_offset = 0;
353 }
354};
355
356namespace detail {
357
358template<>
360{
361 using type = std::true_type;
362};
363
364} // namespace detail
365
366template<typename T>
367bool operator==(const delayed_delete_vector<T>& lhs, const delayed_delete_vector<T>& rhs)
368{
369 return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
370}
371
372template<typename Self, element_t TypeId, typename ValueT, template<typename, typename> class StoreT>
374{
375public:
376 using store_type = StoreT<ValueT, std::allocator<ValueT>>;
377 static constexpr element_t block_type = TypeId;
378
379protected:
380 store_type m_array;
381
383 {}
384 element_block(size_t n) : base_element_block(TypeId), m_array(n)
385 {}
386 element_block(size_t n, const ValueT& val) : base_element_block(TypeId), m_array(n, val)
387 {}
388
389 template<typename Iter>
390 element_block(const Iter& it_begin, const Iter& it_end) : base_element_block(TypeId), m_array(it_begin, it_end)
391 {}
392
393public:
394 typedef typename store_type::iterator iterator;
395 typedef typename store_type::reverse_iterator reverse_iterator;
396 typedef typename store_type::const_iterator const_iterator;
397 typedef typename store_type::const_reverse_iterator const_reverse_iterator;
398 typedef ValueT value_type;
399
400private:
401 template<bool Mutable>
402 class base_range_type
403 {
404 using block_type = mdds::detail::mutable_t<base_element_block, Mutable>;
405 block_type& m_blk;
406
407 public:
408 using iter_type = std::conditional_t<Mutable, iterator, const_iterator>;
409
410 base_range_type(block_type& blk) : m_blk(blk)
411 {}
412
413 iter_type begin()
414 {
415 return element_block::begin(m_blk);
416 }
417
418 iter_type end()
419 {
420 return element_block::end(m_blk);
421 }
422 };
423
424public:
425 using range_type = base_range_type<true>;
426 using const_range_type = base_range_type<false>;
427
428 bool operator==(const Self& r) const
429 {
430 return m_array == r.m_array;
431 }
432
433 bool operator!=(const Self& r) const
434 {
435 return !operator==(r);
436 }
437
438 static const value_type& at(const base_element_block& block, typename store_type::size_type pos)
439 {
440 return get(block).m_array.at(pos);
441 }
442
443 static value_type& at(base_element_block& block, typename store_type::size_type pos)
444 {
445 return get(block).m_array.at(pos);
446 }
447
448 static value_type* data(base_element_block& block)
449 {
450 return get(block).m_array.data();
451 }
452
453 static typename store_type::size_type size(const base_element_block& block)
454 {
455 return get(block).m_array.size();
456 }
457
458 static iterator begin(base_element_block& block)
459 {
460 return get(block).m_array.begin();
461 }
462
463 static iterator end(base_element_block& block)
464 {
465 return get(block).m_array.end();
466 }
467
468 static const_iterator begin(const base_element_block& block)
469 {
470 return get(block).m_array.begin();
471 }
472
473 static const_iterator end(const base_element_block& block)
474 {
475 return get(block).m_array.end();
476 }
477
478 static const_iterator cbegin(const base_element_block& block)
479 {
480 return get(block).m_array.begin();
481 }
482
483 static const_iterator cend(const base_element_block& block)
484 {
485 return get(block).m_array.end();
486 }
487
488 static reverse_iterator rbegin(base_element_block& block)
489 {
490 return get(block).m_array.rbegin();
491 }
492
493 static reverse_iterator rend(base_element_block& block)
494 {
495 return get(block).m_array.rend();
496 }
497
498 static const_reverse_iterator rbegin(const base_element_block& block)
499 {
500 return get(block).m_array.rbegin();
501 }
502
503 static const_reverse_iterator rend(const base_element_block& block)
504 {
505 return get(block).m_array.rend();
506 }
507
508 static const_reverse_iterator crbegin(const base_element_block& block)
509 {
510 return get(block).m_array.rbegin();
511 }
512
513 static const_reverse_iterator crend(const base_element_block& block)
514 {
515 return get(block).m_array.rend();
516 }
517
518 static const_range_type range(const base_element_block& block)
519 {
520 return const_range_type(block);
521 }
522
523 static range_type range(base_element_block& block)
524 {
525 return range_type(block);
526 }
527
528 static Self& get(base_element_block& block)
529 {
530#ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
531 if (get_block_type(block) != TypeId)
532 {
533 std::ostringstream os;
534 os << "incorrect block type: expected block type=" << TypeId
535 << ", passed block type=" << get_block_type(block);
536 throw general_error(os.str());
537 }
538#endif
539 return static_cast<Self&>(block);
540 }
541
542 static const Self& get(const base_element_block& block)
543 {
544#ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
545 if (get_block_type(block) != TypeId)
546 {
547 std::ostringstream os;
548 os << "incorrect block type: expected block type=" << TypeId
549 << ", passed block type=" << get_block_type(block);
550 throw general_error(os.str());
551 }
552#endif
553 return static_cast<const Self&>(block);
554 }
555
556 static void set_value(base_element_block& blk, size_t pos, const ValueT& val)
557 {
558 get(blk).m_array[pos] = val;
559 }
560
561 static void get_value(const base_element_block& blk, size_t pos, ValueT& val)
562 {
563 val = get(blk).m_array[pos];
564 }
565
566 static value_type get_value(const base_element_block& blk, size_t pos)
567 {
568 return get(blk).m_array[pos];
569 }
570
571 static void append_value(base_element_block& blk, const ValueT& val)
572 {
573 get(blk).m_array.push_back(val);
574 }
575
576 static void prepend_value(base_element_block& blk, const ValueT& val)
577 {
578 store_type& blk2 = get(blk).m_array;
579 blk2.insert(blk2.begin(), val);
580 }
581
582 static Self* create_block(size_t init_size)
583 {
584 return new Self(init_size);
585 }
586
587 static void delete_block(const base_element_block* p)
588 {
589 delete static_cast<const Self*>(p);
590 }
591
592 static void resize_block(base_element_block& blk, size_t new_size)
593 {
594 store_type& st = get(blk).m_array;
595 st.resize(new_size);
596
597 // Test if the vector's capacity is larger than twice its current
598 // size, and if so, shrink its capacity to free up some memory.
599 if (new_size < (detail::get_block_capacity(st) / 2))
600 detail::shrink_to_fit(st);
601 }
602
603#ifdef MDDS_UNIT_TEST
604 static void print_block(const base_element_block& blk)
605 {
606 const store_type& blk2 = get(blk).m_array;
607 for (const auto& val : blk2)
608 std::cout << val << " ";
609
610 std::cout << std::endl;
611 }
612#else
613 static void print_block(const base_element_block&)
614 {}
615#endif
616
617 static void erase_value(base_element_block& blk, size_t pos)
618 {
619 store_type& blk2 = get(blk).m_array;
620 blk2.erase(blk2.begin() + pos);
621 }
622
623 static void erase_values(base_element_block& blk, size_t pos, size_t size)
624 {
625 store_type& blk2 = get(blk).m_array;
626 blk2.erase(blk2.begin() + pos, blk2.begin() + pos + size);
627 }
628
629 static void append_block(base_element_block& dest, const base_element_block& src)
630 {
631 store_type& d = get(dest).m_array;
632 const store_type& s = get(src).m_array;
633 d.insert(d.end(), s.begin(), s.end());
634 }
635
636 static void append_values_from_block(
637 base_element_block& dest, const base_element_block& src, size_t begin_pos, size_t len)
638 {
639 store_type& d = get(dest).m_array;
640 const store_type& s = get(src).m_array;
641 std::pair<const_iterator, const_iterator> its = get_iterator_pair(s, begin_pos, len);
642 detail::reserve(d, d.size() + len);
643 d.insert(d.end(), its.first, its.second);
644 }
645
646 static void assign_values_from_block(
647 base_element_block& dest, const base_element_block& src, size_t begin_pos, size_t len)
648 {
649 store_type& d = get(dest).m_array;
650 const store_type& s = get(src).m_array;
651 std::pair<const_iterator, const_iterator> its = get_iterator_pair(s, begin_pos, len);
652 d.assign(its.first, its.second);
653 }
654
655 static void prepend_values_from_block(
656 base_element_block& dest, const base_element_block& src, size_t begin_pos, size_t len)
657 {
658 store_type& d = get(dest).m_array;
659 const store_type& s = get(src).m_array;
660 std::pair<const_iterator, const_iterator> its = get_iterator_pair(s, begin_pos, len);
661 detail::reserve(d, d.size() + len);
662 d.insert(d.begin(), its.first, its.second);
663 }
664
665 static void swap_values(base_element_block& blk1, base_element_block& blk2, size_t pos1, size_t pos2, size_t len)
666 {
667 store_type& st1 = get(blk1).m_array;
668 store_type& st2 = get(blk2).m_array;
669 assert(pos1 + len <= st1.size());
670 assert(pos2 + len <= st2.size());
671
672 typename store_type::iterator it1 = st1.begin(), it2 = st2.begin();
673 std::advance(it1, pos1);
674 std::advance(it2, pos2);
675
676 for (size_t i = 0; i < len; ++i, ++it1, ++it2)
677 {
678 value_type v1 = *it1, v2 = *it2;
679 *it1 = v2;
680 *it2 = v1;
681 }
682 }
683
684 static bool equal_block(const base_element_block& left, const base_element_block& right)
685 {
686 return get(left) == get(right);
687 }
688
689 template<typename Iter>
690 static void set_values(base_element_block& block, size_t pos, const Iter& it_begin, const Iter& it_end)
691 {
692 store_type& d = get(block).m_array;
693 typename store_type::iterator it_dest = d.begin();
694 std::advance(it_dest, pos);
695 for (Iter it = it_begin; it != it_end; ++it, ++it_dest)
696 *it_dest = *it;
697 }
698
699 template<typename Iter>
700 static void append_values(base_element_block& block, const Iter& it_begin, const Iter& it_end)
701 {
702 store_type& d = get(block).m_array;
703 typename store_type::iterator it = d.end();
704 d.insert(it, it_begin, it_end);
705 }
706
707 template<typename Iter>
708 static void prepend_values(base_element_block& block, const Iter& it_begin, const Iter& it_end)
709 {
710 store_type& d = get(block).m_array;
711 d.insert(d.begin(), it_begin, it_end);
712 }
713
714 template<typename Iter>
715 static void assign_values(base_element_block& dest, const Iter& it_begin, const Iter& it_end)
716 {
717 store_type& d = get(dest).m_array;
718 d.assign(it_begin, it_end);
719 }
720
721 template<typename Iter>
722 static void insert_values(base_element_block& block, size_t pos, const Iter& it_begin, const Iter& it_end)
723 {
724 store_type& blk = get(block).m_array;
725 blk.insert(blk.begin() + pos, it_begin, it_end);
726 }
727
728 static size_t capacity(const base_element_block& block)
729 {
730 const store_type& blk = get(block).m_array;
731 return detail::get_block_capacity(blk);
732 }
733
734 static void reserve(base_element_block& block, std::size_t size)
735 {
736 store_type& blk = get(block).m_array;
737 detail::reserve(blk, size);
738 }
739
740 static void shrink_to_fit(base_element_block& block)
741 {
742 store_type& blk = get(block).m_array;
743 detail::shrink_to_fit(blk);
744 }
745
746private:
747 static std::pair<const_iterator, const_iterator> get_iterator_pair(
748 const store_type& array, size_t begin_pos, size_t len)
749 {
750 assert(begin_pos + len <= array.size());
751 const_iterator it = array.begin();
752 std::advance(it, begin_pos);
753 const_iterator it_end = it;
754 std::advance(it_end, len);
755 return std::pair<const_iterator, const_iterator>(it, it_end);
756 }
757};
758
759template<typename Self, element_t TypeId, typename ValueT, template<typename, typename> class StoreT>
760class copyable_element_block : public element_block<Self, TypeId, ValueT, StoreT>
761{
763
764protected:
766 {}
767 copyable_element_block(size_t n) : base_type(n)
768 {}
769 copyable_element_block(size_t n, const ValueT& val) : base_type(n, val)
770 {}
771
772 template<typename Iter>
773 copyable_element_block(const Iter& it_begin, const Iter& it_end) : base_type(it_begin, it_end)
774 {}
775
776public:
777 using base_type::get;
778
779 static Self* clone_block(const base_element_block& blk)
780 {
781 // Use copy constructor to copy the data.
782 return new Self(get(blk));
783 }
784};
785
786template<typename Self, element_t TypeId, typename ValueT, template<typename, typename> class StoreT>
787class noncopyable_element_block : public element_block<Self, TypeId, ValueT, StoreT>
788{
790
791protected:
793 {}
795 {}
796 noncopyable_element_block(size_t n, const ValueT& val) : base_type(n, val)
797 {}
798
799 template<typename Iter>
800 noncopyable_element_block(const Iter& it_begin, const Iter& it_end) : base_type(it_begin, it_end)
801 {}
802
803public:
805 noncopyable_element_block& operator=(const noncopyable_element_block&) = delete;
806
807 static Self* clone_block(const base_element_block&)
808 {
809 throw element_block_error("attempted to clone a noncopyable element block.");
810 }
811};
812
820inline element_t get_block_type(const base_element_block& blk)
821{
822 return blk.type;
823}
824
829template<element_t TypeId, typename ValueT, template<typename, typename> class StoreT = delayed_delete_vector>
831 : public copyable_element_block<default_element_block<TypeId, ValueT, StoreT>, TypeId, ValueT, StoreT>
832{
835
837 {}
838 default_element_block(size_t n) : base_type(n)
839 {}
840 default_element_block(size_t n, const ValueT& val) : base_type(n, val)
841 {}
842
843 template<typename Iter>
844 default_element_block(const Iter& it_begin, const Iter& it_end) : base_type(it_begin, it_end)
845 {}
846
847 static self_type* create_block_with_value(size_t init_size, const ValueT& val)
848 {
849 return new self_type(init_size, val);
850 }
851
852 template<typename Iter>
853 static self_type* create_block_with_values(const Iter& it_begin, const Iter& it_end)
854 {
855 return new self_type(it_begin, it_end);
856 }
857
858 static void overwrite_values(base_element_block&, size_t, size_t)
859 {
860 // Do nothing.
861 }
862};
863
868template<element_t TypeId, typename ValueT, template<typename, typename> class StoreT = delayed_delete_vector>
870 : public copyable_element_block<managed_element_block<TypeId, ValueT, StoreT>, TypeId, ValueT*, StoreT>
871{
874
875 using base_type::get;
876 using base_type::m_array;
877 using base_type::reserve;
878 using base_type::set_value;
879
881 {}
882 managed_element_block(size_t n) : base_type(n)
883 {}
885 {
886 detail::reserve(m_array, r.m_array.size());
887 for (const auto& v : r.m_array)
888 m_array.push_back(new ValueT(*v));
889 }
890
891 template<typename Iter>
892 managed_element_block(const Iter& it_begin, const Iter& it_end) : base_type(it_begin, it_end)
893 {}
894
896 {
897 std::for_each(m_array.begin(), m_array.end(), std::default_delete<ValueT>());
898 }
899
900 static self_type* create_block_with_value(size_t init_size, ValueT* val)
901 {
902 // Managed blocks don't support initialization with value.
903 if (init_size > 1)
904 throw general_error("You can't create a managed block with initial value.");
905
906 std::unique_ptr<self_type> blk = std::make_unique<self_type>(init_size);
907 if (init_size == 1)
908 set_value(*blk, 0, val);
909
910 return blk.release();
911 }
912
913 template<typename Iter>
914 static self_type* create_block_with_values(const Iter& it_begin, const Iter& it_end)
915 {
916 return new self_type(it_begin, it_end);
917 }
918
919 static void overwrite_values(base_element_block& block, size_t pos, size_t len)
920 {
921 managed_element_block& blk = get(block);
922 typename managed_element_block::store_type::iterator it = blk.m_array.begin() + pos;
923 typename managed_element_block::store_type::iterator it_end = it + len;
924 std::for_each(it, it_end, std::default_delete<ValueT>());
925 }
926};
927
928template<element_t TypeId, typename ValueT, template<typename, typename> class StoreT = delayed_delete_vector>
931 noncopyable_managed_element_block<TypeId, ValueT, StoreT>, TypeId, ValueT*, StoreT>
932{
935
936 using base_type::get;
937 using base_type::m_array;
938 using base_type::set_value;
939
941 {}
943 {}
944
945 template<typename Iter>
946 noncopyable_managed_element_block(const Iter& it_begin, const Iter& it_end) : base_type(it_begin, it_end)
947 {}
948
950 {
951 std::for_each(m_array.begin(), m_array.end(), std::default_delete<ValueT>());
952 }
953
954 static self_type* create_block_with_value(size_t init_size, ValueT* val)
955 {
956 // Managed blocks don't support initialization with value.
957 if (init_size > 1)
958 throw general_error("You can't create a managed block with initial value.");
959
960 std::unique_ptr<self_type> blk = std::make_unique<self_type>(init_size);
961 if (init_size == 1)
962 set_value(*blk, 0, val);
963
964 return blk.release();
965 }
966
967 template<typename Iter>
968 static self_type* create_block_with_values(const Iter& it_begin, const Iter& it_end)
969 {
970 return new self_type(it_begin, it_end);
971 }
972
973 static void overwrite_values(base_element_block& block, size_t pos, size_t len)
974 {
975 noncopyable_managed_element_block& blk = get(block);
976 typename noncopyable_managed_element_block::store_type::iterator it = blk.m_array.begin() + pos;
977 typename noncopyable_managed_element_block::store_type::iterator it_end = it + len;
978 std::for_each(it, it_end, std::default_delete<ValueT>());
979 }
980};
981
982namespace detail {
983
984template<typename Blk>
985bool get_block_element_at(const mdds::mtv::base_element_block& data, size_t offset, std::true_type)
986{
987 auto it = Blk::cbegin(data);
988 std::advance(it, offset);
989 return *it;
990}
991
992template<typename Blk>
993typename Blk::value_type get_block_element_at(const mdds::mtv::base_element_block& data, size_t offset, std::false_type)
994{
995 return Blk::at(data, offset);
996}
997
998template<typename Blk>
999typename Blk::value_type get_block_element_at(const mdds::mtv::base_element_block& data, size_t offset)
1000{
1001 typename mdds::mtv::detail::has_std_vector_bool_store<Blk>::type v;
1002 return get_block_element_at<Blk>(data, offset, v);
1003}
1004
1005} // namespace detail
1006
1007}} // namespace mdds::mtv
1008
1009#endif
1010
1011/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Definition global.hpp:84
Definition types.hpp:160
friend element_t get_block_type(const base_element_block &)
Definition types.hpp:820
Definition types.hpp:761
Definition types.hpp:176
Definition types.hpp:146
Definition types.hpp:374
Definition types.hpp:788
Definition types.hpp:832
Definition types_util.hpp:147
Definition types.hpp:871
Definition types.hpp:116
std::string function_args
Definition types.hpp:133
const char * function_name
Definition types.hpp:127
int line_number
Definition types.hpp:139
const void * instance
Definition types.hpp:124
const char * filepath
Definition types.hpp:136