mdds
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>
44 using std::cerr;
45 using std::cout;
46 using std::endl;
47 #endif
48 
49 namespace mdds { namespace mtv {
50 
51 using element_t = int;
52 
53 constexpr element_t element_type_empty = -1;
54 
55 constexpr element_t element_type_reserved_start = 0;
56 constexpr element_t element_type_reserved_end = 49;
57 
58 constexpr element_t element_type_user_start = 50;
59 
66 enum 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 
101 enum 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 {
147 public:
148  element_block_error(const std::string& msg) : mdds::general_error(msg)
149  {}
150 };
151 
152 class base_element_block;
153 element_t get_block_type(const base_element_block&);
154 
160 {
161  friend element_t get_block_type(const base_element_block&);
162 
163 protected:
164  element_t type;
165  base_element_block(element_t _t) : type(_t)
166  {}
167 };
168 
174 template<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
180 public:
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 
348 private:
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 
356 namespace detail {
357 
358 template<>
360 {
361  using type = std::true_type;
362 };
363 
364 } // namespace detail
365 
366 template<typename T>
367 bool 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 
372 template<typename Self, element_t TypeId, typename ValueT, template<typename, typename> class StoreT>
374 {
375 public:
376  using store_type = StoreT<ValueT, std::allocator<ValueT>>;
377  static constexpr element_t block_type = TypeId;
378 
379 protected:
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 
393 public:
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 
400 private:
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 
424 public:
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 
746 private:
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 
759 template<typename Self, element_t TypeId, typename ValueT, template<typename, typename> class StoreT>
760 class copyable_element_block : public element_block<Self, TypeId, ValueT, StoreT>
761 {
763 
764 protected:
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 
776 public:
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 
786 template<typename Self, element_t TypeId, typename ValueT, template<typename, typename> class StoreT>
787 class noncopyable_element_block : public element_block<Self, TypeId, ValueT, StoreT>
788 {
790 
791 protected:
793  {}
794  noncopyable_element_block(size_t n) : base_type(n)
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 
803 public:
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 
820 inline element_t get_block_type(const base_element_block& blk)
821 {
822  return blk.type;
823 }
824 
829 template<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 
868 template<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 
928 template<element_t TypeId, typename ValueT, template<typename, typename> class StoreT = delayed_delete_vector>
930  : public noncopyable_element_block<
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 
982 namespace detail {
983 
984 template<typename Blk>
985 bool 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 
992 template<typename Blk>
993 typename 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 
998 template<typename Blk>
999 typename 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: types.hpp:145
Definition: types_util.hpp:146
const char * filepath
Definition: types.hpp:136
std::string function_args
Definition: types.hpp:133
Definition: types.hpp:760
Definition: types.hpp:115
Definition: types.hpp:869
int line_number
Definition: types.hpp:139
const void * instance
Definition: types.hpp:124
Definition: types.hpp:373
Definition: types.hpp:830
Definition: global.hpp:83
friend element_t get_block_type(const base_element_block &)
Definition: types.hpp:820
const char * function_name
Definition: types.hpp:127
Definition: flat_segment_tree.hpp:46
Definition: types.hpp:787
Definition: types.hpp:175
Definition: types.hpp:159