Intel(R) Threading Building Blocks Doxygen Documentation  version 4.2.3
concurrent_vector.h
Go to the documentation of this file.
1 /*
2  Copyright (c) 2005-2018 Intel Corporation
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 
16 
17 
18 
19 */
20 
21 #ifndef __TBB_concurrent_vector_H
22 #define __TBB_concurrent_vector_H
23 
24 #include "tbb_stddef.h"
25 #include "tbb_exception.h"
26 #include "atomic.h"
28 #include "blocked_range.h"
29 #include "tbb_machine.h"
30 #include "tbb_profiling.h"
31 #include <new>
32 #include <cstring> // for memset()
33 #include __TBB_STD_SWAP_HEADER
34 #include <algorithm>
35 #include <iterator>
36 
37 #if _MSC_VER==1500 && !__INTEL_COMPILER
38  // VS2008/VC9 seems to have an issue; limits pull in math.h
39  #pragma warning( push )
40  #pragma warning( disable: 4985 )
41 #endif
42 #include <limits> /* std::numeric_limits */
43 #if _MSC_VER==1500 && !__INTEL_COMPILER
44  #pragma warning( pop )
45 #endif
46 
47 #if __TBB_INITIALIZER_LISTS_PRESENT
48  #include <initializer_list>
49 #endif
50 
51 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
52  // Workaround for overzealous compiler warnings in /Wp64 mode
53  #pragma warning (push)
54 #if defined(_Wp64)
55  #pragma warning (disable: 4267)
56 #endif
57  #pragma warning (disable: 4127) //warning C4127: conditional expression is constant
58 #endif
59 
60 namespace tbb {
61 
62 template<typename T, class A = cache_aligned_allocator<T> >
64 
66 namespace internal {
67 
68  template<typename Container, typename Value>
70 
72  static void *const vector_allocation_error_flag = reinterpret_cast<void*>(size_t(63));
73 
75  template<typename T>
76  void handle_unconstructed_elements(T* array, size_t n_of_elements){
77  std::memset( static_cast<void*>(array), 0, n_of_elements * sizeof( T ) );
78  }
79 
81 
83  protected:
84 
85  // Basic types declarations
86  typedef size_t segment_index_t;
87  typedef size_t size_type;
88 
89  // Using enumerations due to Mac linking problems of static const variables
90  enum {
91  // Size constants
92  default_initial_segments = 1, // 2 initial items
94  pointers_per_short_table = 3, // to fit into 8 words of entire structure
95  pointers_per_long_table = sizeof(segment_index_t) * 8 // one segment per bit
96  };
97 
98  struct segment_not_used {};
99  struct segment_allocated {};
101 
102  class segment_t;
104  void* array;
105  private:
106  //TODO: More elegant way to grant access to selected functions _only_?
107  friend class segment_t;
108  explicit segment_value_t(void* an_array):array(an_array) {}
109  public:
110  friend bool operator==(segment_value_t const& lhs, segment_not_used ) { return lhs.array == 0;}
113  template<typename argument_type>
114  friend bool operator!=(segment_value_t const& lhs, argument_type arg) { return ! (lhs == arg);}
115 
116  template<typename T>
117  T* pointer() const { return static_cast<T*>(const_cast<void*>(array)); }
118  };
119 
121  if(s != segment_allocated()){
122  internal::throw_exception(exception);
123  }
124  }
125 
126  // Segment pointer.
127  class segment_t {
129  public:
130  segment_t(){ store<relaxed>(segment_not_used());}
131  //Copy ctor and assignment operator are defined to ease using of stl algorithms.
132  //These algorithms usually not a synchronization point, so, semantic is
133  //intentionally relaxed here.
135 
136  void swap(segment_t & rhs ){
137  tbb::internal::swap<relaxed>(array, rhs.array);
138  }
139 
141  array.store<relaxed>(rhs.array.load<relaxed>());
142  return *this;
143  }
144 
145  template<memory_semantics M>
146  segment_value_t load() const { return segment_value_t(array.load<M>());}
147 
148  template<memory_semantics M>
150  array.store<M>(0);
151  }
152 
153  template<memory_semantics M>
155  __TBB_ASSERT(load<relaxed>() != segment_allocated(),"transition from \"allocated\" to \"allocation failed\" state looks non-logical");
157  }
158 
159  template<memory_semantics M>
160  void store(void* allocated_segment_pointer) __TBB_NOEXCEPT(true) {
161  __TBB_ASSERT(segment_value_t(allocated_segment_pointer) == segment_allocated(),
162  "other overloads of store should be used for marking segment as not_used or allocation_failed" );
163  array.store<M>(allocated_segment_pointer);
164  }
165 
166 #if TBB_USE_ASSERT
167  ~segment_t() {
168  __TBB_ASSERT(load<relaxed>() != segment_allocated(), "should have been freed by clear" );
169  }
170 #endif /* TBB_USE_ASSERT */
171  };
172  friend void swap(segment_t & , segment_t & ) __TBB_NOEXCEPT(true);
173 
174  // Data fields
175 
177  void* (*vector_allocator_ptr)(concurrent_vector_base_v3 &, size_t);
178 
181 
184 
187 
190 
191  // Methods
192 
194  //Here the semantic is intentionally relaxed.
195  //The reason this is next:
196  //Object that is in middle of construction (i.e. its constructor is not yet finished)
197  //cannot be used concurrently until the construction is finished.
198  //Thus to flag other threads that construction is finished, some synchronization with
199  //acquire-release semantic should be done by the (external) code that uses the vector.
200  //So, no need to do the synchronization inside the vector.
201 
203  my_first_block.store<relaxed>(0); // here is not default_initial_segments
204  my_segment.store<relaxed>(my_storage);
205  }
206 
208 
209  //these helpers methods use the fact that segments are allocated so
210  //that every segment size is a (increasing) power of 2.
211  //with one exception 0 segment has size of 2 as well segment 1;
212  //e.g. size of segment with index of 3 is 2^3=8;
214  return segment_index_t( __TBB_Log2( index|1 ) );
215  }
216 
218  return (segment_index_t(1)<<k & ~segment_index_t(1));
219  }
220 
222  segment_index_t k = segment_index_of( index );
223  index -= segment_base(k);
224  return k;
225  }
226 
228  return segment_index_t(1)<<k; // fake value for k==0
229  }
230 
231 
232  static bool is_first_element_in_segment(size_type element_index){
233  //check if element_index is a power of 2 that is at least 2.
234  //The idea is to detect if the iterator crosses a segment boundary,
235  //and 2 is the minimal index for which it's true
236  __TBB_ASSERT(element_index, "there should be no need to call "
237  "is_first_element_in_segment for 0th element" );
238  return is_power_of_two_at_least( element_index, 2 );
239  }
240 
243 
245  typedef void (__TBB_EXPORTED_FUNC *internal_array_op2)(void* dst, const void* src, size_type n );
246 
251  };
252 
253  void __TBB_EXPORTED_METHOD internal_reserve( size_type n, size_type element_size, size_type max_size );
255  void internal_grow( size_type start, size_type finish, size_type element_size, internal_array_op2 init, const void *src );
256  size_type __TBB_EXPORTED_METHOD internal_grow_by( size_type delta, size_type element_size, internal_array_op2 init, const void *src );
257  void* __TBB_EXPORTED_METHOD internal_push_back( size_type element_size, size_type& index );
259  void* __TBB_EXPORTED_METHOD internal_compact( size_type element_size, void *table, internal_array_op1 destroy, internal_array_op2 copy );
266 
267  void __TBB_EXPORTED_METHOD internal_resize( size_type n, size_type element_size, size_type max_size, const void *src,
268  internal_array_op1 destroy, internal_array_op2 init );
270 
273 private:
275  class helper;
276  friend class helper;
277 
278  template<typename Container, typename Value>
279  friend class vector_iterator;
280 
281  };
282 
284  lhs.swap(rhs);
285  }
286 
288 
290 
292  template<typename Container, typename Value>
293  class vector_iterator
294  {
296  Container* my_vector;
297 
299  size_t my_index;
300 
302 
303  mutable Value* my_item;
304 
305  template<typename C, typename T>
306  friend vector_iterator<C,T> operator+( ptrdiff_t offset, const vector_iterator<C,T>& v );
307 
308  template<typename C, typename T, typename U>
309  friend bool operator==( const vector_iterator<C,T>& i, const vector_iterator<C,U>& j );
310 
311  template<typename C, typename T, typename U>
312  friend bool operator<( const vector_iterator<C,T>& i, const vector_iterator<C,U>& j );
313 
314  template<typename C, typename T, typename U>
315  friend ptrdiff_t operator-( const vector_iterator<C,T>& i, const vector_iterator<C,U>& j );
316 
317  template<typename C, typename U>
319 
320 #if !__TBB_TEMPLATE_FRIENDS_BROKEN
321  template<typename T, class A>
323 #else
324 public:
325 #endif
326 
327  vector_iterator( const Container& vector, size_t index, void *ptr = 0 ) :
328  my_vector(const_cast<Container*>(&vector)),
329  my_index(index),
330  my_item(static_cast<Value*>(ptr))
331  {}
332 
333  public:
335  vector_iterator() : my_vector(NULL), my_index(~size_t(0)), my_item(NULL) {}
336 
338  my_vector(other.my_vector),
339  my_index(other.my_index),
340  my_item(other.my_item)
341  {}
342 
343  vector_iterator operator+( ptrdiff_t offset ) const {
344  return vector_iterator( *my_vector, my_index+offset );
345  }
346  vector_iterator &operator+=( ptrdiff_t offset ) {
347  my_index+=offset;
348  my_item = NULL;
349  return *this;
350  }
351  vector_iterator operator-( ptrdiff_t offset ) const {
352  return vector_iterator( *my_vector, my_index-offset );
353  }
354  vector_iterator &operator-=( ptrdiff_t offset ) {
355  my_index-=offset;
356  my_item = NULL;
357  return *this;
358  }
359  Value& operator*() const {
360  Value* item = my_item;
361  if( !item ) {
362  item = my_item = &my_vector->internal_subscript(my_index);
363  }
364  __TBB_ASSERT( item==&my_vector->internal_subscript(my_index), "corrupt cache" );
365  return *item;
366  }
367  Value& operator[]( ptrdiff_t k ) const {
368  return my_vector->internal_subscript(my_index+k);
369  }
370  Value* operator->() const {return &operator*();}
371 
374  size_t element_index = ++my_index;
375  if( my_item ) {
376  //TODO: consider using of knowledge about "first_block optimization" here as well?
378  //if the iterator crosses a segment boundary, the pointer become invalid
379  //as possibly next segment is in another memory location
380  my_item= NULL;
381  } else {
382  ++my_item;
383  }
384  }
385  return *this;
386  }
387 
390  __TBB_ASSERT( my_index>0, "operator--() applied to iterator already at beginning of concurrent_vector" );
391  size_t element_index = my_index--;
392  if( my_item ) {
394  //if the iterator crosses a segment boundary, the pointer become invalid
395  //as possibly next segment is in another memory location
396  my_item= NULL;
397  } else {
398  --my_item;
399  }
400  }
401  return *this;
402  }
403 
406  vector_iterator result = *this;
407  operator++();
408  return result;
409  }
410 
413  vector_iterator result = *this;
414  operator--();
415  return result;
416  }
417 
418  // STL support
419 
420  typedef ptrdiff_t difference_type;
421  typedef Value value_type;
422  typedef Value* pointer;
423  typedef Value& reference;
424  typedef std::random_access_iterator_tag iterator_category;
425  };
426 
427  template<typename Container, typename T>
429  return vector_iterator<Container,T>( *v.my_vector, v.my_index+offset );
430  }
431 
432  template<typename Container, typename T, typename U>
434  return i.my_index==j.my_index && i.my_vector == j.my_vector;
435  }
436 
437  template<typename Container, typename T, typename U>
439  return !(i==j);
440  }
441 
442  template<typename Container, typename T, typename U>
444  return i.my_index<j.my_index;
445  }
446 
447  template<typename Container, typename T, typename U>
449  return j<i;
450  }
451 
452  template<typename Container, typename T, typename U>
454  return !(i<j);
455  }
456 
457  template<typename Container, typename T, typename U>
459  return !(j<i);
460  }
461 
462  template<typename Container, typename T, typename U>
464  return ptrdiff_t(i.my_index)-ptrdiff_t(j.my_index);
465  }
466 
467  template<typename T, class A>
469  public:
470  typedef typename A::template
471  rebind<T>::other allocator_type;
473 
475 
476  };
477 
478 } // namespace internal
480 
482 
543 template<typename T, class A>
544 class concurrent_vector: protected internal::allocator_base<T, A>,
546 private:
547  template<typename I>
549  public:
550  typedef T value_type;
551  typedef T& reference;
552  typedef const T& const_reference;
553  typedef I iterator;
554  typedef ptrdiff_t difference_type;
555  generic_range_type( I begin_, I end_, size_t grainsize_ = 1) : blocked_range<I>(begin_,end_,grainsize_) {}
556  template<typename U>
559  };
560 
561  template<typename C, typename U>
562  friend class internal::vector_iterator;
563 
564 public:
565  //------------------------------------------------------------------------
566  // STL compatible types
567  //------------------------------------------------------------------------
570 
571  typedef T value_type;
572  typedef ptrdiff_t difference_type;
573  typedef T& reference;
574  typedef const T& const_reference;
575  typedef T *pointer;
576  typedef const T *const_pointer;
577 
578  typedef internal::vector_iterator<concurrent_vector,T> iterator;
579  typedef internal::vector_iterator<concurrent_vector,const T> const_iterator;
580 
581 #if !defined(_MSC_VER) || _CPPLIB_VER>=300
582  // Assume ISO standard definition of std::reverse_iterator
583  typedef std::reverse_iterator<iterator> reverse_iterator;
584  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
585 #else
586  // Use non-standard std::reverse_iterator
587  typedef std::reverse_iterator<iterator,T,T&,T*> reverse_iterator;
588  typedef std::reverse_iterator<const_iterator,T,const T&,const T*> const_reverse_iterator;
589 #endif /* defined(_MSC_VER) && (_MSC_VER<1300) */
590 
591  //------------------------------------------------------------------------
592  // Parallel algorithm support
593  //------------------------------------------------------------------------
594  typedef generic_range_type<iterator> range_type;
595  typedef generic_range_type<const_iterator> const_range_type;
596 
597  //------------------------------------------------------------------------
598  // STL compatible constructors & destructors
599  //------------------------------------------------------------------------
600 
603  : internal::allocator_base<T, A>(a), internal::concurrent_vector_base()
604  {
606  }
607 
608  //Constructors are not required to have synchronization
609  //(for more details see comment in the concurrent_vector_base constructor).
610 #if __TBB_INITIALIZER_LISTS_PRESENT
611  concurrent_vector(std::initializer_list<T> init_list, const allocator_type &a = allocator_type())
613  : internal::allocator_base<T, A>(a), internal::concurrent_vector_base()
614  {
616  __TBB_TRY {
617  internal_assign_iterators(init_list.begin(), init_list.end());
618  } __TBB_CATCH(...) {
619  segment_t *table = my_segment.load<relaxed>();;
621  __TBB_RETHROW();
622  }
623 
624  }
625 #endif //# __TBB_INITIALIZER_LISTS_PRESENT
626 
629  : internal::allocator_base<T, A>(a), internal::concurrent_vector_base()
630  {
632  __TBB_TRY {
633  internal_copy(vector, sizeof(T), &copy_array);
634  } __TBB_CATCH(...) {
635  segment_t *table = my_segment.load<relaxed>();
637  __TBB_RETHROW();
638  }
639  }
640 
641 #if __TBB_CPP11_RVALUE_REF_PRESENT
642  //TODO add __TBB_NOEXCEPT(true) and static_assert(std::has_nothrow_move_constructor<A>::value)
645  : internal::allocator_base<T, A>(std::move(source)), internal::concurrent_vector_base()
646  {
649  }
650 
652  : internal::allocator_base<T, A>(a), internal::concurrent_vector_base()
653  {
655  //C++ standard requires instances of an allocator being compared for equality,
656  //which means that memory allocated by one instance is possible to deallocate with the other one.
657  if (a == source.my_allocator) {
659  } else {
660  __TBB_TRY {
661  internal_copy(source, sizeof(T), &move_array);
662  } __TBB_CATCH(...) {
663  segment_t *table = my_segment.load<relaxed>();
665  __TBB_RETHROW();
666  }
667  }
668  }
669 
670 #endif
671 
673  template<class M>
675  : internal::allocator_base<T, A>(a), internal::concurrent_vector_base()
676  {
678  __TBB_TRY {
679  internal_copy(vector.internal_vector_base(), sizeof(T), &copy_array);
680  } __TBB_CATCH(...) {
681  segment_t *table = my_segment.load<relaxed>();
683  __TBB_RETHROW();
684  }
685  }
686 
689  {
691  __TBB_TRY {
692  internal_resize( n, sizeof(T), max_size(), NULL, &destroy_array, &initialize_array );
693  } __TBB_CATCH(...) {
694  segment_t *table = my_segment.load<relaxed>();
696  __TBB_RETHROW();
697  }
698  }
699 
702  : internal::allocator_base<T, A>(a)
703  {
705  __TBB_TRY {
706  internal_resize( n, sizeof(T), max_size(), static_cast<const void*>(&t), &destroy_array, &initialize_array_by );
707  } __TBB_CATCH(...) {
708  segment_t *table = my_segment.load<relaxed>();
710  __TBB_RETHROW();
711  }
712  }
713 
715  template<class I>
717  : internal::allocator_base<T, A>(a)
718  {
720  __TBB_TRY {
721  internal_assign_range(first, last, static_cast<is_integer_tag<std::numeric_limits<I>::is_integer> *>(0) );
722  } __TBB_CATCH(...) {
723  segment_t *table = my_segment.load<relaxed>();
725  __TBB_RETHROW();
726  }
727  }
728 
731  if( this != &vector )
732  internal_assign(vector, sizeof(T), &destroy_array, &assign_array, &copy_array);
733  return *this;
734  }
735 
736 #if __TBB_CPP11_RVALUE_REF_PRESENT
737  //TODO: add __TBB_NOEXCEPT()
740  __TBB_ASSERT(this != &other, "Move assignment to itself is prohibited ");
742  if(pocma_t::value || this->my_allocator == other.my_allocator) {
743  concurrent_vector trash (std::move(*this));
744  internal_swap(other);
745  if (pocma_t::value) {
746  this->my_allocator = std::move(other.my_allocator);
747  }
748  } else {
750  }
751  return *this;
752  }
753 #endif
754  //TODO: add an template assignment operator? (i.e. with different element type)
755 
757  template<class M>
759  if( static_cast<void*>( this ) != static_cast<const void*>( &vector ) )
760  internal_assign(vector.internal_vector_base(),
761  sizeof(T), &destroy_array, &assign_array, &copy_array);
762  return *this;
763  }
764 
765 #if __TBB_INITIALIZER_LISTS_PRESENT
766  concurrent_vector& operator=( std::initializer_list<T> init_list ) {
769  internal_assign_iterators(init_list.begin(), init_list.end());
770  return *this;
771  }
772 #endif //#if __TBB_INITIALIZER_LISTS_PRESENT
773 
774  //------------------------------------------------------------------------
775  // Concurrent operations
776  //------------------------------------------------------------------------
778 
780  return iterator(*this, delta ? internal_grow_by( delta, sizeof(T), &initialize_array, NULL ) : my_early_size.load());
781  }
782 
784 
786  return iterator(*this, delta ? internal_grow_by( delta, sizeof(T), &initialize_array_by, static_cast<const void*>(&t) ) : my_early_size.load());
787  }
788 
790  template<typename I>
792  typename std::iterator_traits<I>::difference_type delta = std::distance(first, last);
793  __TBB_ASSERT( delta >= 0, NULL);
794 
795  return iterator(*this, delta ? internal_grow_by(delta, sizeof(T), &copy_range<I>, static_cast<const void*>(&first)) : my_early_size.load());
796  }
797 
798 #if __TBB_INITIALIZER_LISTS_PRESENT
799 
800  iterator grow_by( std::initializer_list<T> init_list ) {
801  return grow_by( init_list.begin(), init_list.end() );
802  }
803 #endif //#if __TBB_INITIALIZER_LISTS_PRESENT
804 
806 
811  size_type m=0;
812  if( n ) {
813  m = internal_grow_to_at_least_with_result( n, sizeof(T), &initialize_array, NULL );
814  if( m>n ) m=n;
815  }
816  return iterator(*this, m);
817  };
818 
822  size_type m=0;
823  if( n ) {
825  if( m>n ) m=n;
826  }
827  return iterator(*this, m);
828  };
829 
831 
833  {
834  push_back_helper prolog(*this);
835  new(prolog.internal_push_back_result()) T(item);
836  return prolog.return_iterator_and_dismiss();
837  }
838 
839 #if __TBB_CPP11_RVALUE_REF_PRESENT
840 
842  iterator push_back( T&& item )
843  {
844  push_back_helper prolog(*this);
845  new(prolog.internal_push_back_result()) T(std::move(item));
846  return prolog.return_iterator_and_dismiss();
847  }
848 #if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
849 
851  template<typename... Args>
852  iterator emplace_back( Args&&... args )
853  {
854  push_back_helper prolog(*this);
855  new(prolog.internal_push_back_result()) T(std::forward<Args>(args)...);
856  return prolog.return_iterator_and_dismiss();
857  }
858 #endif //__TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
859 #endif //__TBB_CPP11_RVALUE_REF_PRESENT
860 
864  return internal_subscript(index);
865  }
866 
869  return internal_subscript(index);
870  }
871 
873  reference at( size_type index ) {
875  }
876 
878  const_reference at( size_type index ) const {
880  }
881 
883  range_type range( size_t grainsize = 1 ) {
884  return range_type( begin(), end(), grainsize );
885  }
886 
888  const_range_type range( size_t grainsize = 1 ) const {
889  return const_range_type( begin(), end(), grainsize );
890  }
891 
892  //------------------------------------------------------------------------
893  // Capacity
894  //------------------------------------------------------------------------
896  size_type size() const {
898  return cp < sz ? cp : sz;
899  }
900 
902  bool empty() const {return !my_early_size;}
903 
906 
908 
910  void reserve( size_type n ) {
911  if( n )
912  internal_reserve(n, sizeof(T), max_size());
913  }
914 
916  void resize( size_type n ) {
917  internal_resize( n, sizeof(T), max_size(), NULL, &destroy_array, &initialize_array );
918  }
919 
922  internal_resize( n, sizeof(T), max_size(), static_cast<const void*>(&t), &destroy_array, &initialize_array_by );
923  }
924 
926  void shrink_to_fit();
927 
929  size_type max_size() const {return (~size_type(0))/sizeof(T);}
930 
931  //------------------------------------------------------------------------
932  // STL support
933  //------------------------------------------------------------------------
934 
936  iterator begin() {return iterator(*this,0);}
938  iterator end() {return iterator(*this,size());}
940  const_iterator begin() const {return const_iterator(*this,0);}
942  const_iterator end() const {return const_iterator(*this,size());}
944  const_iterator cbegin() const {return const_iterator(*this,0);}
946  const_iterator cend() const {return const_iterator(*this,size());}
961  __TBB_ASSERT( size()>0, NULL);
962  const segment_value_t& segment_value = my_segment[0].template load<relaxed>();
963  return (segment_value.template pointer<T>())[0];
964  }
967  __TBB_ASSERT( size()>0, NULL);
968  const segment_value_t& segment_value = my_segment[0].template load<relaxed>();
969  return (segment_value.template pointer<const T>())[0];
970  }
973  __TBB_ASSERT( size()>0, NULL);
974  return internal_subscript( size()-1 );
975  }
978  __TBB_ASSERT( size()>0, NULL);
979  return internal_subscript( size()-1 );
980  }
982  allocator_type get_allocator() const { return this->my_allocator; }
983 
985  void assign(size_type n, const_reference t) {
986  clear();
987  internal_resize( n, sizeof(T), max_size(), static_cast<const void*>(&t), &destroy_array, &initialize_array_by );
988  }
989 
991  template<class I>
992  void assign(I first, I last) {
993  clear(); internal_assign_range( first, last, static_cast<is_integer_tag<std::numeric_limits<I>::is_integer> *>(0) );
994  }
995 
996 #if __TBB_INITIALIZER_LISTS_PRESENT
997  void assign(std::initializer_list<T> init_list) {
999  clear(); internal_assign_iterators( init_list.begin(), init_list.end());
1000  }
1001 #endif //# __TBB_INITIALIZER_LISTS_PRESENT
1002 
1004  void swap(concurrent_vector &vector) {
1005  using std::swap;
1006  if( this != &vector ) {
1007  concurrent_vector_base_v3::internal_swap(static_cast<concurrent_vector_base_v3&>(vector));
1008  swap(this->my_allocator, vector.my_allocator);
1009  }
1010  }
1011 
1013 
1014  void clear() {
1016  }
1017 
1020  segment_t *table = my_segment.load<relaxed>();
1022  // base class destructor call should be then
1023  }
1024 
1025  const internal::concurrent_vector_base_v3 &internal_vector_base() const { return *this; }
1026 private:
1028  static void *internal_allocator(internal::concurrent_vector_base_v3 &vb, size_t k) {
1029  return static_cast<concurrent_vector<T, A>&>(vb).my_allocator.allocate(k);
1030  }
1032  void internal_free_segments(segment_t table[], segment_index_t k, segment_index_t first_block);
1033 
1035  T& internal_subscript( size_type index ) const;
1036 
1039 
1042  internal_resize( n, sizeof(T), max_size(), static_cast<const void*>(p), &destroy_array, p? &initialize_array_by : &initialize_array );
1043  }
1044 
1046  template<bool B> class is_integer_tag;
1047 
1049  template<class I>
1050  void internal_assign_range(I first, I last, is_integer_tag<true> *) {
1051  internal_assign_n(static_cast<size_type>(first), &static_cast<T&>(last));
1052  }
1054  template<class I>
1055  void internal_assign_range(I first, I last, is_integer_tag<false> *) {
1057  }
1059  template<class I>
1061 
1062  //these functions are marked __TBB_EXPORTED_FUNC as they are called from within the library
1063 
1065  static void __TBB_EXPORTED_FUNC initialize_array( void* begin, const void*, size_type n );
1066 
1068  static void __TBB_EXPORTED_FUNC initialize_array_by( void* begin, const void* src, size_type n );
1069 
1071  static void __TBB_EXPORTED_FUNC copy_array( void* dst, const void* src, size_type n );
1072 
1073 #if __TBB_MOVE_IF_NOEXCEPT_PRESENT
1074  static void __TBB_EXPORTED_FUNC move_array_if_noexcept( void* dst, const void* src, size_type n );
1076 #endif //__TBB_MOVE_IF_NO_EXCEPT_PRESENT
1077 
1078 #if __TBB_CPP11_RVALUE_REF_PRESENT
1079  static void __TBB_EXPORTED_FUNC move_array( void* dst, const void* src, size_type n );
1081 
1083  static void __TBB_EXPORTED_FUNC move_assign_array( void* dst, const void* src, size_type n );
1084 #endif
1085  template<typename Iterator>
1087  static void __TBB_EXPORTED_FUNC copy_range( void* dst, const void* p_type_erased_iterator, size_type n );
1088 
1090  static void __TBB_EXPORTED_FUNC assign_array( void* dst, const void* src, size_type n );
1091 
1093  static void __TBB_EXPORTED_FUNC destroy_array( void* begin, size_type n );
1094 
1096  class internal_loop_guide : internal::no_copy {
1097  public:
1099  const size_type n;
1101 
1102  static const T* as_const_pointer(const void *ptr) { return static_cast<const T *>(ptr); }
1103  static T* as_pointer(const void *src) { return static_cast<T*>(const_cast<void *>(src)); }
1104 
1105  internal_loop_guide(size_type ntrials, void *ptr)
1106  : array(as_pointer(ptr)), n(ntrials), i(0) {}
1107  void init() { for(; i < n; ++i) new( &array[i] ) T(); }
1108  void init(const void *src) { for(; i < n; ++i) new( &array[i] ) T(*as_const_pointer(src)); }
1109  void copy(const void *src) { for(; i < n; ++i) new( &array[i] ) T(as_const_pointer(src)[i]); }
1110  void assign(const void *src) { for(; i < n; ++i) array[i] = as_const_pointer(src)[i]; }
1111 #if __TBB_CPP11_RVALUE_REF_PRESENT
1112  void move_assign(const void *src) { for(; i < n; ++i) array[i] = std::move(as_pointer(src)[i]); }
1113  void move_construct(const void *src) { for(; i < n; ++i) new( &array[i] ) T( std::move(as_pointer(src)[i]) ); }
1114 #endif
1115 #if __TBB_MOVE_IF_NOEXCEPT_PRESENT
1116  void move_construct_if_noexcept(const void *src) { for(; i < n; ++i) new( &array[i] ) T( std::move_if_noexcept(as_pointer(src)[i]) ); }
1117 #endif //__TBB_MOVE_IF_NOEXCEPT_PRESENT
1118 
1119  //TODO: rename to construct_range
1120  template<class I> void iterate(I &src) { for(; i < n; ++i, ++src) new( &array[i] ) T( *src ); }
1122  if(i < n) {// if an exception was raised, fill the rest of items with zeros
1124  }
1125  }
1126  };
1127 
1128  struct push_back_helper : internal::no_copy{
1129  struct element_construction_guard : internal::no_copy{
1131 
1132  element_construction_guard(pointer an_element) : element (an_element){}
1133  void dismiss(){ element = NULL; }
1135  if (element){
1137  }
1138  }
1139  };
1140 
1144 
1146  v(vector),
1147  g (static_cast<T*>(v.internal_push_back(sizeof(T),k)))
1148  {}
1149 
1152  pointer ptr = g.element;
1153  g.dismiss();
1154  return iterator(v, k, ptr);
1155  }
1156  };
1157 };
1158 
1159 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
1160 // Deduction guide for the constructor from two iterators
1161 template<typename I,
1162  typename T = typename std::iterator_traits<I>::value_type,
1163  typename A = cache_aligned_allocator<T>
1164 > concurrent_vector(I, I, const A& = A())
1165 -> concurrent_vector<T, A>;
1166 
1167 // Deduction guide for the constructor from a vector and allocator
1168 template<typename T, typename A1, typename A2>
1169 concurrent_vector(const concurrent_vector<T, A1> &, const A2 &)
1170 -> concurrent_vector<T, A2>;
1171 
1172 // Deduction guide for the constructor from an initializer_list
1173 template<typename T, typename A = cache_aligned_allocator<T>
1174 > concurrent_vector(std::initializer_list<T>, const A& = A())
1175 -> concurrent_vector<T, A>;
1176 #endif /* __TBB_CPP17_DEDUCTION_GUIDES_PRESENT */
1177 
1178 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
1179 #pragma warning (push)
1180 #pragma warning (disable: 4701) // potentially uninitialized local variable "old"
1181 #endif
1182 template<typename T, class A>
1185  __TBB_TRY {
1186  internal_array_op2 copy_or_move_array =
1187 #if __TBB_MOVE_IF_NOEXCEPT_PRESENT
1188  &move_array_if_noexcept
1189 #else
1190  &copy_array
1191 #endif
1192  ;
1193  if( internal_compact( sizeof(T), &old, &destroy_array, copy_or_move_array ) )
1194  internal_free_segments( old.table, pointers_per_long_table, old.first_block ); // free joined and unnecessary segments
1195  } __TBB_CATCH(...) {
1196  if( old.first_block ) // free segment allocated for compacting. Only for support of exceptions in ctor of user T[ype]
1197  internal_free_segments( old.table, 1, old.first_block );
1198  __TBB_RETHROW();
1199  }
1200 }
1201 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
1202 #pragma warning (pop)
1203 #endif // warning 4701 is back
1204 
1205 template<typename T, class A>
1207  // Free the arrays
1208  while( k > first_block ) {
1209  --k;
1210  segment_value_t segment_value = table[k].load<relaxed>();
1211  table[k].store<relaxed>(segment_not_used());
1212  if( segment_value == segment_allocated() ) // check for correct segment pointer
1213  this->my_allocator.deallocate( (segment_value.pointer<T>()), segment_size(k) );
1214  }
1215  segment_value_t segment_value = table[0].load<relaxed>();
1216  if( segment_value == segment_allocated() ) {
1217  __TBB_ASSERT( first_block > 0, NULL );
1218  while(k > 0) table[--k].store<relaxed>(segment_not_used());
1219  this->my_allocator.deallocate( (segment_value.pointer<T>()), segment_size(first_block) );
1220  }
1221 }
1222 
1223 template<typename T, class A>
1225  //TODO: unify both versions of internal_subscript
1226  __TBB_ASSERT( index < my_early_size, "index out of bounds" );
1227  size_type j = index;
1228  segment_index_t k = segment_base_index_of( j );
1229  __TBB_ASSERT( my_segment.load<acquire>() != my_storage || k < pointers_per_short_table, "index is being allocated" );
1230  //no need in load with acquire (load<acquire>) since thread works in own space or gets
1231  //the information about added elements via some form of external synchronization
1232  //TODO: why not make a load of my_segment relaxed as well ?
1233  //TODO: add an assertion that my_segment[k] is properly aligned to please ITT
1234  segment_value_t segment_value = my_segment[k].template load<relaxed>();
1235  __TBB_ASSERT( segment_value != segment_allocation_failed(), "the instance is broken by bad allocation. Use at() instead" );
1236  __TBB_ASSERT( segment_value != segment_not_used(), "index is being allocated" );
1237  return (( segment_value.pointer<T>()))[j];
1238 }
1239 
1240 template<typename T, class A>
1242  if( index >= my_early_size )
1243  internal::throw_exception(internal::eid_out_of_range); // throw std::out_of_range
1244  size_type j = index;
1245  segment_index_t k = segment_base_index_of( j );
1246  //TODO: refactor this condition into separate helper function, e.g. fits_into_small_table
1247  if( my_segment.load<acquire>() == my_storage && k >= pointers_per_short_table )
1249  // no need in load with acquire (load<acquire>) since thread works in own space or gets
1250  //the information about added elements via some form of external synchronization
1251  //TODO: why not make a load of my_segment relaxed as well ?
1252  //TODO: add an assertion that my_segment[k] is properly aligned to please ITT
1253  segment_value_t segment_value = my_segment[k].template load<relaxed>();
1254  enforce_segment_allocated(segment_value, internal::eid_index_range_error);
1255  return (segment_value.pointer<T>())[j];
1256 }
1257 
1258 template<typename T, class A> template<class I>
1260  __TBB_ASSERT(my_early_size == 0, NULL);
1261  size_type n = std::distance(first, last);
1262  if( !n ) return;
1263  internal_reserve(n, sizeof(T), max_size());
1264  my_early_size = n;
1265  segment_index_t k = 0;
1266  //TODO: unify segment iteration code with concurrent_base_v3::helper
1267  size_type sz = segment_size( my_first_block );
1268  while( sz < n ) {
1269  internal_loop_guide loop(sz, my_segment[k].template load<relaxed>().template pointer<void>());
1270  loop.iterate(first);
1271  n -= sz;
1272  if( !k ) k = my_first_block;
1273  else { ++k; sz <<= 1; }
1274  }
1275  internal_loop_guide loop(n, my_segment[k].template load<relaxed>().template pointer<void>());
1276  loop.iterate(first);
1277 }
1278 
1279 template<typename T, class A>
1281  internal_loop_guide loop(n, begin); loop.init();
1282 }
1283 
1284 template<typename T, class A>
1286  internal_loop_guide loop(n, begin); loop.init(src);
1287 }
1288 
1289 template<typename T, class A>
1290 void concurrent_vector<T, A>::copy_array( void* dst, const void* src, size_type n ) {
1291  internal_loop_guide loop(n, dst); loop.copy(src);
1292 }
1293 
1294 #if __TBB_CPP11_RVALUE_REF_PRESENT
1295 template<typename T, class A>
1296 void concurrent_vector<T, A>::move_array( void* dst, const void* src, size_type n ) {
1297  internal_loop_guide loop(n, dst); loop.move_construct(src);
1298 }
1299 template<typename T, class A>
1300 void concurrent_vector<T, A>::move_assign_array( void* dst, const void* src, size_type n ) {
1301  internal_loop_guide loop(n, dst); loop.move_assign(src);
1302 }
1303 #endif
1304 
1305 #if __TBB_MOVE_IF_NOEXCEPT_PRESENT
1306 template<typename T, class A>
1307 void concurrent_vector<T, A>::move_array_if_noexcept( void* dst, const void* src, size_type n ) {
1308  internal_loop_guide loop(n, dst); loop.move_construct_if_noexcept(src);
1309 }
1310 #endif //__TBB_MOVE_IF_NOEXCEPT_PRESENT
1311 
1312 template<typename T, class A>
1313 template<typename I>
1314 void concurrent_vector<T, A>::copy_range( void* dst, const void* p_type_erased_iterator, size_type n ){
1315  internal_loop_guide loop(n, dst);
1316  loop.iterate( *(static_cast<I*>(const_cast<void*>(p_type_erased_iterator))) );
1317 }
1318 
1319 template<typename T, class A>
1320 void concurrent_vector<T, A>::assign_array( void* dst, const void* src, size_type n ) {
1321  internal_loop_guide loop(n, dst); loop.assign(src);
1322 }
1323 
1324 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
1325  // Workaround for overzealous compiler warning
1326  #pragma warning (push)
1327  #pragma warning (disable: 4189)
1328 #endif
1329 template<typename T, class A>
1331  T* array = static_cast<T*>(begin);
1332  for( size_type j=n; j>0; --j )
1333  array[j-1].~T(); // destructors are supposed to not throw any exceptions
1334 }
1335 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
1336  #pragma warning (pop)
1337 #endif // warning 4189 is back
1338 
1339 // concurrent_vector's template functions
1340 template<typename T, class A1, class A2>
1342  //TODO: call size() only once per vector (in operator==)
1343  // Simply: return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
1344  if(a.size() != b.size()) return false;
1345  typename concurrent_vector<T, A1>::const_iterator i(a.begin());
1346  typename concurrent_vector<T, A2>::const_iterator j(b.begin());
1347  for(; i != a.end(); ++i, ++j)
1348  if( !(*i == *j) ) return false;
1349  return true;
1350 }
1351 
1352 template<typename T, class A1, class A2>
1354 { return !(a == b); }
1355 
1356 template<typename T, class A1, class A2>
1358 { return (std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end())); }
1359 
1360 template<typename T, class A1, class A2>
1362 { return b < a; }
1363 
1364 template<typename T, class A1, class A2>
1366 { return !(b < a); }
1367 
1368 template<typename T, class A1, class A2>
1370 { return !(a < b); }
1371 
1372 template<typename T, class A>
1374 { a.swap( b ); }
1375 
1376 } // namespace tbb
1377 
1378 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
1379  #pragma warning (pop)
1380 #endif // warning 4267,4127 are back
1381 
1382 #endif /* __TBB_concurrent_vector_H */
iterator grow_by(size_type delta, const_reference t)
Grow by "delta" elements using copying constructor.
iterator grow_to_at_least(size_type n, const_reference t)
friend bool operator==(const vector_iterator< C, T > &i, const vector_iterator< C, U > &j)
size_type __TBB_EXPORTED_METHOD internal_grow_by(size_type delta, size_type element_size, internal_array_op2 init, const void *src)
const_iterator cend() const
end const iterator
friend bool operator==(segment_value_t const &lhs, segment_allocated)
intptr_t __TBB_Log2(uintptr_t x)
Definition: tbb_machine.h:864
friend bool operator<(const vector_iterator< C, T > &i, const vector_iterator< C, U > &j)
const_reference operator[](size_type index) const
Get const reference to element at given index.
bool operator!=(const vector_iterator< Container, T > &i, const vector_iterator< Container, U > &j)
T & internal_subscript(size_type index) const
Get reference to element at given index.
A::template rebind< T >::other allocator_type
iterator end()
end iterator
void __TBB_EXPORTED_METHOD internal_reserve(size_type n, size_type element_size, size_type max_size)
bool operator<(const concurrent_vector< T, A1 > &a, const concurrent_vector< T, A2 > &b)
void internal_assign_range(I first, I last, is_integer_tag< false > *)
inline proxy assign by iterators
const_range_type range(size_t grainsize=1) const
Get const range for iterating with parallel algorithms.
iterator push_back(const_reference item)
Push item.
iterator begin()
start iterator
std::reverse_iterator< const_iterator > const_reverse_iterator
vector_iterator()
Default constructor.
iterator grow_by(size_type delta)
Grow by "delta" elements.
size_type max_size() const
Upper bound on argument to reserve.
Specialization for atomic<void*>, for sake of not allowing arithmetic or operator->.
Definition: atomic.h:503
iterator grow_by(std::initializer_list< T > init_list)
allocator_type get_allocator() const
return allocator object
#define __TBB_EXPORTED_FUNC
static void __TBB_EXPORTED_FUNC initialize_array(void *begin, const void *, size_type n)
Construct n instances of T, starting at "begin".
bool operator==(const cache_aligned_allocator< T > &, const cache_aligned_allocator< U > &)
void store(void *allocated_segment_pointer) __TBB_NOEXCEPT(true)
void const char const char int ITT_FORMAT __itt_group_sync s
static size_type segment_size(segment_index_t k)
concurrent_vector(const allocator_type &a=allocator_type())
Construct empty vector.
concurrent_vector & operator=(const concurrent_vector &vector)
Assignment.
atomic< size_type > my_early_size
Requested size of vector.
void *(* vector_allocator_ptr)(concurrent_vector_base_v3 &, size_t)
allocator function pointer
void internal_free_segments(segment_t table[], segment_index_t k, segment_index_t first_block)
Free k segments from table.
concurrent_vector & operator=(concurrent_vector &&other)
Move assignment.
static void __TBB_EXPORTED_FUNC assign_array(void *dst, const void *src, size_type n)
Assign (using operator=) n instances of T, starting at "dst" by assigning according element of src ar...
const_reference back() const
the last item const
Dummy type that distinguishes splitting constructor from copy constructor.
Definition: tbb_stddef.h:399
const_iterator end() const
One past last value in range.
Definition: blocked_range.h:76
void store(value_type value)
Definition: atomic.h:317
Container * my_vector
concurrent_vector over which we are iterating.
void __TBB_EXPORTED_METHOD internal_swap(concurrent_vector_base_v3 &v)
auto last(Container &c) -> decltype(begin(c))
Exception-aware helper class for filling a segment by exception-danger operators of user class.
void resize(size_type n, const_reference t)
Resize the vector, copy t for new elements. Not thread-safe.
void(__TBB_EXPORTED_FUNC * internal_array_op2)(void *dst, const void *src, size_type n)
An operation on n-element destination array and n-element source array.
Concurrent vector container.
void swap(concurrent_vector &vector)
swap two instances
internal::vector_iterator< concurrent_vector, const T > const_iterator
A range over which to iterate.
Definition: blocked_range.h:49
const_reverse_iterator crbegin() const
reverse start const iterator
concurrent_vector(const concurrent_vector &vector, const allocator_type &a=allocator_type())
Copying constructor.
void *__TBB_EXPORTED_METHOD internal_compact(size_type element_size, void *table, internal_array_op1 destroy, internal_array_op2 copy)
void *__TBB_EXPORTED_METHOD internal_push_back(size_type element_size, size_type &index)
const_iterator end() const
end const iterator
#define __TBB_CATCH(e)
Definition: tbb_stddef.h:288
static segment_index_t segment_base(segment_index_t k)
#define __TBB_EXPORTED_METHOD
Definition: tbb_stddef.h:102
bool empty() const
Return false if vector is not empty or has elements under construction at least.
void internal_assign_n(size_type n, const_pointer p)
assign n items by copying t
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:169
auto first(Container &c) -> decltype(begin(c))
concurrent_vector_base_v3 concurrent_vector_base
void const char const char int ITT_FORMAT __itt_group_sync p
bool is_power_of_two_at_least(argument_integer_type arg, power2_integer_type power2)
A function to determine if arg is a power of 2 at least as big as another power of 2.
Definition: tbb_stddef.h:375
Class for determining type of std::allocator<T>::value_type.
Definition: tbb_stddef.h:454
static void * internal_allocator(internal::concurrent_vector_base_v3 &vb, size_t k)
Allocate k items.
static void __TBB_EXPORTED_FUNC copy_range(void *dst, const void *p_type_erased_iterator, size_type n)
Copy-construct n instances of T, starting at "dst" by iterator range of [p_type_erased_iterator,...
friend void swap(segment_t &, segment_t &) __TBB_NOEXCEPT(true)
bool operator<=(const concurrent_vector< T, A1 > &a, const concurrent_vector< T, A2 > &b)
const_iterator cbegin() const
start const iterator
#define __TBB_TRY
Definition: tbb_stddef.h:287
void clear()
Clear container while keeping memory allocated.
size_type capacity() const
Maximum size to which array can grow without allocating more memory. Concurrent allocations are not i...
const internal::concurrent_vector_base_v3 & internal_vector_base() const
void __TBB_EXPORTED_METHOD internal_throw_exception(size_type) const
Obsolete.
bool operator<=(const vector_iterator< Container, T > &i, const vector_iterator< Container, U > &j)
internal_loop_guide(size_type ntrials, void *ptr)
vector_iterator operator-(ptrdiff_t offset) const
atomic< size_type > my_first_block
count of segments in the first block
iterator emplace_back(Args &&... args)
Push item, create item "in place" with provided arguments.
vector_iterator & operator-=(ptrdiff_t offset)
__TBB_EXPORTED_METHOD ~concurrent_vector_base_v3()
static void __TBB_EXPORTED_FUNC copy_array(void *dst, const void *src, size_type n)
Copy-construct n instances of T by copying single element pointed to by src, starting at "dst".
reference front()
the first item
No ordering.
Definition: atomic.h:51
void reserve(size_type n)
Allocate enough space to grow to size n without having to allocate more memory later.
vector_iterator operator--(int)
Post decrement.
void internal_grow(size_type start, size_type finish, size_type element_size, internal_array_op2 init, const void *src)
Base class of concurrent vector implementation.
friend vector_iterator< C, T > operator+(ptrdiff_t offset, const vector_iterator< C, T > &v)
reverse_iterator rend()
reverse end iterator
reference operator[](size_type index)
Get reference to element at given index.
void move(tbb_thread &t1, tbb_thread &t2)
Definition: tbb_thread.h:309
size_type __TBB_EXPORTED_METHOD internal_grow_to_at_least_with_result(size_type new_size, size_type element_size, internal_array_op2 init, const void *src)
static void __TBB_EXPORTED_FUNC initialize_array_by(void *begin, const void *src, size_type n)
Copy-construct n instances of T, starting at "begin".
iterator grow_by(I first, I last)
bool operator>(const vector_iterator< Container, T > &i, const vector_iterator< Container, U > &j)
generic_range_type< iterator > range_type
~concurrent_vector()
Clear and destroy vector.
concurrent_vector(I first, I last, const allocator_type &a=allocator_type())
Construction with copying iteration range and given allocator instance.
generic_range_type(const generic_range_type< U > &r)
bool operator<(const vector_iterator< Container, T > &i, const vector_iterator< Container, U > &j)
Meets requirements of a forward iterator for STL and a Value for a blocked_range.*/.
static segment_index_t segment_base_index_of(segment_index_t &index)
vector_iterator(const vector_iterator< Container, typename Container::value_type > &other)
const_reverse_iterator rend() const
reverse end const iterator
Acquire.
Definition: atomic.h:47
static const T * as_const_pointer(const void *ptr)
Value * my_item
Caches my_vector->internal_subscript(my_index)
void assign(size_type n, const_reference t)
assign n items by copying t item
The graph class.
segment_index_t __TBB_EXPORTED_METHOD internal_clear(internal_array_op1 destroy)
vector_iterator operator+(ptrdiff_t offset) const
void assign(I first, I last)
assign range [first, last)
vector_iterator(const Container &vector, size_t index, void *ptr=0)
bool operator>(const concurrent_vector< T, A1 > &a, const concurrent_vector< T, A2 > &b)
size_type size() const
Return size of vector. It may include elements under construction.
void resize(size_type n)
Resize the vector. Not thread-safe.
static bool is_first_element_in_segment(size_type element_index)
void shrink_to_fit()
Optimize memory usage and fragmentation.
void handle_unconstructed_elements(T *array, size_t n_of_elements)
Exception helper function.
static segment_index_t segment_index_of(size_type index)
#define __TBB_RETHROW()
Definition: tbb_stddef.h:290
static void *const vector_allocation_error_flag
Bad allocation marker.
void __TBB_EXPORTED_METHOD internal_copy(const concurrent_vector_base_v3 &src, size_type element_size, internal_array_op2 copy)
reference back()
the last item
bool operator!=(const cache_aligned_allocator< T > &, const cache_aligned_allocator< U > &)
friend bool operator==(segment_value_t const &lhs, segment_not_used)
vector_iterator & operator+=(ptrdiff_t offset)
Number of slots for segment pointers inside the class.
size_type __TBB_EXPORTED_METHOD internal_capacity() const
friend ptrdiff_t operator-(const vector_iterator< C, T > &i, const vector_iterator< C, U > &j)
friend bool operator==(segment_value_t const &lhs, segment_allocation_failed)
T & internal_subscript_with_exceptions(size_type index) const
Get reference to element at given index with errors checks.
void swap(concurrent_vector< T, A > &a, concurrent_vector< T, A > &b)
push_back_helper(concurrent_vector &vector)
bool operator>=(const vector_iterator< Container, T > &i, const vector_iterator< Container, U > &j)
bool operator==(const vector_iterator< Container, T > &i, const vector_iterator< Container, U > &j)
const_reverse_iterator crend() const
reverse end const iterator
internal::concurrent_vector_base_v3::size_type size_type
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long value
ptrdiff_t operator-(const vector_iterator< Container, T > &i, const vector_iterator< Container, U > &j)
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp begin
void __TBB_EXPORTED_METHOD internal_resize(size_type n, size_type element_size, size_type max_size, const void *src, internal_array_op1 destroy, internal_array_op2 init)
iterator grow_to_at_least(size_type n)
Append minimal sequence of elements such that size()>=n.
void internal_assign_iterators(I first, I last)
assign by iterators
concurrent_vector & operator=(const concurrent_vector< T, M > &vector)
Assignment for vector with different allocator type.
vector_iterator operator++(int)
Post increment.
friend void enforce_segment_allocated(segment_value_t const &s, internal::exception_id exception=eid_bad_last_alloc)
value_type load() const
Definition: atomic.h:306
const_reference at(size_type index) const
Get const reference to element at given index. Throws exceptions on errors.
std::reverse_iterator< iterator > reverse_iterator
friend bool operator!=(segment_value_t const &lhs, argument_type arg)
range_type range(size_t grainsize=1)
Get range for iterating with parallel algorithms.
void internal_assign_range(I first, I last, is_integer_tag< true > *)
assign integer items by copying when arguments are treated as iterators. See C++ Standard 2003 23....
vector_iterator< Container, T > operator+(ptrdiff_t offset, const vector_iterator< Container, T > &v)
const_reverse_iterator rbegin() const
reverse start const iterator
void(__TBB_EXPORTED_FUNC * internal_array_op1)(void *begin, size_type n)
An operation on an n-element array starting at begin.
void swap(atomic< T > &lhs, atomic< T > &rhs)
Definition: atomic.h:539
concurrent_vector(size_type n, const_reference t, const allocator_type &a=allocator_type())
Construction with initial size specified by argument n, initialization by copying of t,...
void __TBB_EXPORTED_METHOD internal_assign(const concurrent_vector_base_v3 &src, size_type element_size, internal_array_op1 destroy, internal_array_op2 assign, internal_array_op2 copy)
concurrent_vector(const concurrent_vector< T, M > &vector, const allocator_type &a=allocator_type())
Copying constructor for vector with different allocator type.
size_t my_index
Index into the vector.
concurrent_vector(concurrent_vector &&source)
Move constructor.
internal::vector_iterator< concurrent_vector, T > iterator
static void __TBB_EXPORTED_FUNC destroy_array(void *begin, size_type n)
Destroy n instances of T, starting at "begin".
void __TBB_EXPORTED_METHOD internal_grow_to_at_least(size_type new_size, size_type element_size, internal_array_op2 init, const void *src)
Deprecated entry point for backwards compatibility to TBB 2.1.
bool operator>=(const concurrent_vector< T, A1 > &a, const concurrent_vector< T, A2 > &b)
iterator push_back(T &&item)
Push item, move-aware.
const_iterator begin() const
start const iterator
internal::allocator_base< T, A >::allocator_type allocator_type
concurrent_vector(size_type n)
Construction with initial size specified by argument n.
generic_range_type(generic_range_type &r, split)
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t new_size
reverse_iterator rbegin()
reverse start iterator
concurrent_vector(concurrent_vector &&source, const allocator_type &a)
atomic< segment_t * > my_segment
Pointer to the segments table.
friend class internal::vector_iterator
std::random_access_iterator_tag iterator_category
vector_iterator & operator--()
Pre decrement.
generic_range_type< const_iterator > const_range_type
#define __TBB_NOEXCEPT(expression)
Definition: tbb_stddef.h:114
const_reference front() const
the first item const
generic_range_type(I begin_, I end_, size_t grainsize_=1)
size_type grainsize() const
The grain size for this range.
Definition: blocked_range.h:86
allocator_base(const allocator_type &a=allocator_type())
const_iterator begin() const
Beginning of range.
Definition: blocked_range.h:73
segment_t my_storage[pointers_per_short_table]
embedded storage of segment pointers
void throw_exception(exception_id eid)
Versionless convenience wrapper for throw_exception_v4()
vector_iterator & operator++()
Pre increment.
void swap(concurrent_hash_map< Key, T, HashCompare, A > &a, concurrent_hash_map< Key, T, HashCompare, A > &b)
static void __TBB_EXPORTED_FUNC move_array(void *dst, const void *src, size_type n)
Move-construct n instances of T, starting at "dst" by copying according element of src array.
reference at(size_type index)
Get reference to element at given index. Throws exceptions on errors.
static void __TBB_EXPORTED_FUNC move_assign_array(void *dst, const void *src, size_type n)
Move-assign (using operator=) n instances of T, starting at "dst" by assigning according element of s...
Value & operator[](ptrdiff_t k) const

Copyright © 2005-2018 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.