00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef __TBB_concurrent_vector_H
00022 #define __TBB_concurrent_vector_H
00023
00024 #include "tbb_stddef.h"
00025 #include "tbb_exception.h"
00026 #include "atomic.h"
00027 #include "cache_aligned_allocator.h"
00028 #include "blocked_range.h"
00029 #include "tbb_machine.h"
00030 #include "tbb_profiling.h"
00031 #include <new>
00032
00033 #if !TBB_USE_EXCEPTIONS && _MSC_VER
00034
00035 #pragma warning (push)
00036 #pragma warning (disable: 4530)
00037 #endif
00038
00039 #include <algorithm>
00040 #include <iterator>
00041
00042 #if !TBB_USE_EXCEPTIONS && _MSC_VER
00043 #pragma warning (pop)
00044 #endif
00045
00046 #if _MSC_VER==1500 && !__INTEL_COMPILER
00047
00048 #pragma warning( push )
00049 #pragma warning( disable: 4985 )
00050 #endif
00051 #include <limits>
00052 #if _MSC_VER==1500 && !__INTEL_COMPILER
00053 #pragma warning( pop )
00054 #endif
00055
00056 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_Wp64)
00057
00058 #pragma warning (push)
00059 #pragma warning (disable: 4267)
00060 #endif
00061
00062 namespace tbb {
00063
00064 template<typename T, class A = cache_aligned_allocator<T> >
00065 class concurrent_vector;
00066
00068 namespace internal {
00069
00071 static void *const vector_allocation_error_flag = reinterpret_cast<void*>(size_t(63));
00072
00074
00075 class concurrent_vector_base_v3 {
00076 protected:
00077
00078
00079 typedef size_t segment_index_t;
00080 typedef size_t size_type;
00081
00082
00083 enum {
00084
00085 default_initial_segments = 1,
00087 pointers_per_short_table = 3,
00088 pointers_per_long_table = sizeof(segment_index_t) * 8
00089 };
00090
00091
00092 struct segment_t {
00093 void* array;
00094 #if TBB_USE_ASSERT
00095 ~segment_t() {
00096 __TBB_ASSERT( array <= internal::vector_allocation_error_flag, "should have been freed by clear" );
00097 }
00098 #endif
00099 };
00100
00101
00102
00104 void* (*vector_allocator_ptr)(concurrent_vector_base_v3 &, size_t);
00105
00107 atomic<size_type> my_first_block;
00108
00110 atomic<size_type> my_early_size;
00111
00113 atomic<segment_t*> my_segment;
00114
00116 segment_t my_storage[pointers_per_short_table];
00117
00118
00119
00120 concurrent_vector_base_v3() {
00121 my_early_size = 0;
00122 my_first_block = 0;
00123 for( segment_index_t i = 0; i < pointers_per_short_table; i++)
00124 my_storage[i].array = NULL;
00125 my_segment = my_storage;
00126 }
00127 __TBB_EXPORTED_METHOD ~concurrent_vector_base_v3();
00128
00129 static segment_index_t segment_index_of( size_type index ) {
00130 return segment_index_t( __TBB_Log2( index|1 ) );
00131 }
00132
00133 static segment_index_t segment_base( segment_index_t k ) {
00134 return (segment_index_t(1)<<k & ~segment_index_t(1));
00135 }
00136
00137 static inline segment_index_t segment_base_index_of( segment_index_t &index ) {
00138 segment_index_t k = segment_index_of( index );
00139 index -= segment_base(k);
00140 return k;
00141 }
00142
00143 static size_type segment_size( segment_index_t k ) {
00144 return segment_index_t(1)<<k;
00145 }
00146
00148 typedef void (__TBB_EXPORTED_FUNC *internal_array_op1)(void* begin, size_type n );
00149
00151 typedef void (__TBB_EXPORTED_FUNC *internal_array_op2)(void* dst, const void* src, size_type n );
00152
00154 struct internal_segments_table {
00155 segment_index_t first_block;
00156 void* table[pointers_per_long_table];
00157 };
00158
00159 void __TBB_EXPORTED_METHOD internal_reserve( size_type n, size_type element_size, size_type max_size );
00160 size_type __TBB_EXPORTED_METHOD internal_capacity() const;
00161 void internal_grow( size_type start, size_type finish, size_type element_size, internal_array_op2 init, const void *src );
00162 size_type __TBB_EXPORTED_METHOD internal_grow_by( size_type delta, size_type element_size, internal_array_op2 init, const void *src );
00163 void* __TBB_EXPORTED_METHOD internal_push_back( size_type element_size, size_type& index );
00164 segment_index_t __TBB_EXPORTED_METHOD internal_clear( internal_array_op1 destroy );
00165 void* __TBB_EXPORTED_METHOD internal_compact( size_type element_size, void *table, internal_array_op1 destroy, internal_array_op2 copy );
00166 void __TBB_EXPORTED_METHOD internal_copy( const concurrent_vector_base_v3& src, size_type element_size, internal_array_op2 copy );
00167 void __TBB_EXPORTED_METHOD internal_assign( const concurrent_vector_base_v3& src, size_type element_size,
00168 internal_array_op1 destroy, internal_array_op2 assign, internal_array_op2 copy );
00170 void __TBB_EXPORTED_METHOD internal_throw_exception(size_type) const;
00171 void __TBB_EXPORTED_METHOD internal_swap(concurrent_vector_base_v3& v);
00172
00173 void __TBB_EXPORTED_METHOD internal_resize( size_type n, size_type element_size, size_type max_size, const void *src,
00174 internal_array_op1 destroy, internal_array_op2 init );
00175 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 );
00176
00178 void __TBB_EXPORTED_METHOD internal_grow_to_at_least( size_type new_size, size_type element_size, internal_array_op2 init, const void *src );
00179 private:
00181 class helper;
00182 friend class helper;
00183 };
00184
00185 typedef concurrent_vector_base_v3 concurrent_vector_base;
00186
00188
00190 template<typename Container, typename Value>
00191 class vector_iterator
00192 {
00194 Container* my_vector;
00195
00197 size_t my_index;
00198
00200
00201 mutable Value* my_item;
00202
00203 template<typename C, typename T>
00204 friend vector_iterator<C,T> operator+( ptrdiff_t offset, const vector_iterator<C,T>& v );
00205
00206 template<typename C, typename T, typename U>
00207 friend bool operator==( const vector_iterator<C,T>& i, const vector_iterator<C,U>& j );
00208
00209 template<typename C, typename T, typename U>
00210 friend bool operator<( const vector_iterator<C,T>& i, const vector_iterator<C,U>& j );
00211
00212 template<typename C, typename T, typename U>
00213 friend ptrdiff_t operator-( const vector_iterator<C,T>& i, const vector_iterator<C,U>& j );
00214
00215 template<typename C, typename U>
00216 friend class internal::vector_iterator;
00217
00218 #if !defined(_MSC_VER) || defined(__INTEL_COMPILER)
00219 template<typename T, class A>
00220 friend class tbb::concurrent_vector;
00221 #else
00222 public:
00223 #endif
00224
00225 vector_iterator( const Container& vector, size_t index, void *ptr = 0 ) :
00226 my_vector(const_cast<Container*>(&vector)),
00227 my_index(index),
00228 my_item(static_cast<Value*>(ptr))
00229 {}
00230
00231 public:
00233 vector_iterator() : my_vector(NULL), my_index(~size_t(0)), my_item(NULL) {}
00234
00235 vector_iterator( const vector_iterator<Container,typename Container::value_type>& other ) :
00236 my_vector(other.my_vector),
00237 my_index(other.my_index),
00238 my_item(other.my_item)
00239 {}
00240
00241 vector_iterator operator+( ptrdiff_t offset ) const {
00242 return vector_iterator( *my_vector, my_index+offset );
00243 }
00244 vector_iterator &operator+=( ptrdiff_t offset ) {
00245 my_index+=offset;
00246 my_item = NULL;
00247 return *this;
00248 }
00249 vector_iterator operator-( ptrdiff_t offset ) const {
00250 return vector_iterator( *my_vector, my_index-offset );
00251 }
00252 vector_iterator &operator-=( ptrdiff_t offset ) {
00253 my_index-=offset;
00254 my_item = NULL;
00255 return *this;
00256 }
00257 Value& operator*() const {
00258 Value* item = my_item;
00259 if( !item ) {
00260 item = my_item = &my_vector->internal_subscript(my_index);
00261 }
00262 __TBB_ASSERT( item==&my_vector->internal_subscript(my_index), "corrupt cache" );
00263 return *item;
00264 }
00265 Value& operator[]( ptrdiff_t k ) const {
00266 return my_vector->internal_subscript(my_index+k);
00267 }
00268 Value* operator->() const {return &operator*();}
00269
00271 vector_iterator& operator++() {
00272 size_t k = ++my_index;
00273 if( my_item ) {
00274
00275 if( (k& (k-2))==0 ) {
00276
00277 my_item= NULL;
00278 } else {
00279 ++my_item;
00280 }
00281 }
00282 return *this;
00283 }
00284
00286 vector_iterator& operator--() {
00287 __TBB_ASSERT( my_index>0, "operator--() applied to iterator already at beginning of concurrent_vector" );
00288 size_t k = my_index--;
00289 if( my_item ) {
00290
00291 if( (k& (k-2))==0 ) {
00292
00293 my_item= NULL;
00294 } else {
00295 --my_item;
00296 }
00297 }
00298 return *this;
00299 }
00300
00302 vector_iterator operator++(int) {
00303 vector_iterator result = *this;
00304 operator++();
00305 return result;
00306 }
00307
00309 vector_iterator operator--(int) {
00310 vector_iterator result = *this;
00311 operator--();
00312 return result;
00313 }
00314
00315
00316
00317 typedef ptrdiff_t difference_type;
00318 typedef Value value_type;
00319 typedef Value* pointer;
00320 typedef Value& reference;
00321 typedef std::random_access_iterator_tag iterator_category;
00322 };
00323
00324 template<typename Container, typename T>
00325 vector_iterator<Container,T> operator+( ptrdiff_t offset, const vector_iterator<Container,T>& v ) {
00326 return vector_iterator<Container,T>( *v.my_vector, v.my_index+offset );
00327 }
00328
00329 template<typename Container, typename T, typename U>
00330 bool operator==( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
00331 return i.my_index==j.my_index && i.my_vector == j.my_vector;
00332 }
00333
00334 template<typename Container, typename T, typename U>
00335 bool operator!=( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
00336 return !(i==j);
00337 }
00338
00339 template<typename Container, typename T, typename U>
00340 bool operator<( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
00341 return i.my_index<j.my_index;
00342 }
00343
00344 template<typename Container, typename T, typename U>
00345 bool operator>( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
00346 return j<i;
00347 }
00348
00349 template<typename Container, typename T, typename U>
00350 bool operator>=( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
00351 return !(i<j);
00352 }
00353
00354 template<typename Container, typename T, typename U>
00355 bool operator<=( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
00356 return !(j<i);
00357 }
00358
00359 template<typename Container, typename T, typename U>
00360 ptrdiff_t operator-( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
00361 return ptrdiff_t(i.my_index)-ptrdiff_t(j.my_index);
00362 }
00363
00364 template<typename T, class A>
00365 class allocator_base {
00366 public:
00367 typedef typename A::template
00368 rebind<T>::other allocator_type;
00369 allocator_type my_allocator;
00370
00371 allocator_base(const allocator_type &a = allocator_type() ) : my_allocator(a) {}
00372 };
00373
00374 }
00376
00378
00439 template<typename T, class A>
00440 class concurrent_vector: protected internal::allocator_base<T, A>,
00441 private internal::concurrent_vector_base {
00442 private:
00443 template<typename I>
00444 class generic_range_type: public blocked_range<I> {
00445 public:
00446 typedef T value_type;
00447 typedef T& reference;
00448 typedef const T& const_reference;
00449 typedef I iterator;
00450 typedef ptrdiff_t difference_type;
00451 generic_range_type( I begin_, I end_, size_t grainsize_ = 1) : blocked_range<I>(begin_,end_,grainsize_) {}
00452 template<typename U>
00453 generic_range_type( const generic_range_type<U>& r) : blocked_range<I>(r.begin(),r.end(),r.grainsize()) {}
00454 generic_range_type( generic_range_type& r, split ) : blocked_range<I>(r,split()) {}
00455 };
00456
00457 template<typename C, typename U>
00458 friend class internal::vector_iterator;
00459 public:
00460
00461
00462
00463 typedef internal::concurrent_vector_base_v3::size_type size_type;
00464 typedef typename internal::allocator_base<T, A>::allocator_type allocator_type;
00465
00466 typedef T value_type;
00467 typedef ptrdiff_t difference_type;
00468 typedef T& reference;
00469 typedef const T& const_reference;
00470 typedef T *pointer;
00471 typedef const T *const_pointer;
00472
00473 typedef internal::vector_iterator<concurrent_vector,T> iterator;
00474 typedef internal::vector_iterator<concurrent_vector,const T> const_iterator;
00475
00476 #if !defined(_MSC_VER) || _CPPLIB_VER>=300
00477
00478 typedef std::reverse_iterator<iterator> reverse_iterator;
00479 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00480 #else
00481
00482 typedef std::reverse_iterator<iterator,T,T&,T*> reverse_iterator;
00483 typedef std::reverse_iterator<const_iterator,T,const T&,const T*> const_reverse_iterator;
00484 #endif
00485
00486
00487
00488
00489 typedef generic_range_type<iterator> range_type;
00490 typedef generic_range_type<const_iterator> const_range_type;
00491
00492
00493
00494
00495
00497 explicit concurrent_vector(const allocator_type &a = allocator_type())
00498 : internal::allocator_base<T, A>(a), internal::concurrent_vector_base()
00499 {
00500 vector_allocator_ptr = &internal_allocator;
00501 }
00502
00504 concurrent_vector( const concurrent_vector& vector, const allocator_type& a = allocator_type() )
00505 : internal::allocator_base<T, A>(a), internal::concurrent_vector_base()
00506 {
00507 vector_allocator_ptr = &internal_allocator;
00508 __TBB_TRY {
00509 internal_copy(vector, sizeof(T), ©_array);
00510 } __TBB_CATCH(...) {
00511 segment_t *table = my_segment;
00512 internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block );
00513 __TBB_RETHROW();
00514 }
00515 }
00516
00518 template<class M>
00519 concurrent_vector( const concurrent_vector<T, M>& vector, const allocator_type& a = allocator_type() )
00520 : internal::allocator_base<T, A>(a), internal::concurrent_vector_base()
00521 {
00522 vector_allocator_ptr = &internal_allocator;
00523 __TBB_TRY {
00524 internal_copy(vector.internal_vector_base(), sizeof(T), ©_array);
00525 } __TBB_CATCH(...) {
00526 segment_t *table = my_segment;
00527 internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block );
00528 __TBB_RETHROW();
00529 }
00530 }
00531
00533 explicit concurrent_vector(size_type n)
00534 {
00535 vector_allocator_ptr = &internal_allocator;
00536 __TBB_TRY {
00537 internal_resize( n, sizeof(T), max_size(), NULL, &destroy_array, &initialize_array );
00538 } __TBB_CATCH(...) {
00539 segment_t *table = my_segment;
00540 internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block );
00541 __TBB_RETHROW();
00542 }
00543 }
00544
00546 concurrent_vector(size_type n, const_reference t, const allocator_type& a = allocator_type())
00547 : internal::allocator_base<T, A>(a)
00548 {
00549 vector_allocator_ptr = &internal_allocator;
00550 __TBB_TRY {
00551 internal_resize( n, sizeof(T), max_size(), static_cast<const void*>(&t), &destroy_array, &initialize_array_by );
00552 } __TBB_CATCH(...) {
00553 segment_t *table = my_segment;
00554 internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block );
00555 __TBB_RETHROW();
00556 }
00557 }
00558
00560 template<class I>
00561 concurrent_vector(I first, I last, const allocator_type &a = allocator_type())
00562 : internal::allocator_base<T, A>(a)
00563 {
00564 vector_allocator_ptr = &internal_allocator;
00565 __TBB_TRY {
00566 internal_assign_range(first, last, static_cast<is_integer_tag<std::numeric_limits<I>::is_integer> *>(0) );
00567 } __TBB_CATCH(...) {
00568 segment_t *table = my_segment;
00569 internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block );
00570 __TBB_RETHROW();
00571 }
00572 }
00573
00575 concurrent_vector& operator=( const concurrent_vector& vector ) {
00576 if( this != &vector )
00577 internal_assign(vector, sizeof(T), &destroy_array, &assign_array, ©_array);
00578 return *this;
00579 }
00580
00582 template<class M>
00583 concurrent_vector& operator=( const concurrent_vector<T, M>& vector ) {
00584 if( static_cast<void*>( this ) != static_cast<const void*>( &vector ) )
00585 internal_assign(vector.internal_vector_base(),
00586 sizeof(T), &destroy_array, &assign_array, ©_array);
00587 return *this;
00588 }
00589
00590
00591
00592
00594 #if TBB_DEPRECATED
00595
00596 size_type grow_by( size_type delta ) {
00597 return delta ? internal_grow_by( delta, sizeof(T), &initialize_array, NULL ) : my_early_size;
00598 }
00599 #else
00600
00601 iterator grow_by( size_type delta ) {
00602 return iterator(*this, delta ? internal_grow_by( delta, sizeof(T), &initialize_array, NULL ) : my_early_size);
00603 }
00604 #endif
00605
00607 #if TBB_DEPRECATED
00608
00609 size_type grow_by( size_type delta, const_reference t ) {
00610 return delta ? internal_grow_by( delta, sizeof(T), &initialize_array_by, static_cast<const void*>(&t) ) : my_early_size;
00611 }
00612 #else
00613
00614 iterator grow_by( size_type delta, const_reference t ) {
00615 return iterator(*this, delta ? internal_grow_by( delta, sizeof(T), &initialize_array_by, static_cast<const void*>(&t) ) : my_early_size);
00616 }
00617 #endif
00618
00620 #if TBB_DEPRECATED
00621
00623 void grow_to_at_least( size_type n ) {
00624 if( n ) internal_grow_to_at_least_with_result( n, sizeof(T), &initialize_array, NULL );
00625 };
00626 #else
00627
00631 iterator grow_to_at_least( size_type n ) {
00632 size_type m=0;
00633 if( n ) {
00634 m = internal_grow_to_at_least_with_result( n, sizeof(T), &initialize_array, NULL );
00635 if( m>n ) m=n;
00636 }
00637 return iterator(*this, m);
00638 };
00639 #endif
00640
00642 #if TBB_DEPRECATED
00643 size_type push_back( const_reference item )
00644 #else
00645
00646 iterator push_back( const_reference item )
00647 #endif
00648 {
00649 size_type k;
00650 void *ptr = internal_push_back(sizeof(T),k);
00651 internal_loop_guide loop(1, ptr);
00652 loop.init(&item);
00653 #if TBB_DEPRECATED
00654 return k;
00655 #else
00656 return iterator(*this, k, ptr);
00657 #endif
00658 }
00659
00661
00663 reference operator[]( size_type index ) {
00664 return internal_subscript(index);
00665 }
00666
00668 const_reference operator[]( size_type index ) const {
00669 return internal_subscript(index);
00670 }
00671
00673 reference at( size_type index ) {
00674 return internal_subscript_with_exceptions(index);
00675 }
00676
00678 const_reference at( size_type index ) const {
00679 return internal_subscript_with_exceptions(index);
00680 }
00681
00683 range_type range( size_t grainsize = 1) {
00684 return range_type( begin(), end(), grainsize );
00685 }
00686
00688 const_range_type range( size_t grainsize = 1 ) const {
00689 return const_range_type( begin(), end(), grainsize );
00690 }
00691
00692
00693
00695 size_type size() const {
00696 size_type sz = my_early_size, cp = internal_capacity();
00697 return cp < sz ? cp : sz;
00698 }
00699
00701 bool empty() const {return !my_early_size;}
00702
00704 size_type capacity() const {return internal_capacity();}
00705
00707
00709 void reserve( size_type n ) {
00710 if( n )
00711 internal_reserve(n, sizeof(T), max_size());
00712 }
00713
00715 void resize( size_type n ) {
00716 internal_resize( n, sizeof(T), max_size(), NULL, &destroy_array, &initialize_array );
00717 }
00718
00720 void resize( size_type n, const_reference t ) {
00721 internal_resize( n, sizeof(T), max_size(), static_cast<const void*>(&t), &destroy_array, &initialize_array_by );
00722 }
00723
00724 #if TBB_DEPRECATED
00726 void compact() {shrink_to_fit();}
00727 #endif
00728
00730 void shrink_to_fit();
00731
00733 size_type max_size() const {return (~size_type(0))/sizeof(T);}
00734
00735
00736
00737
00738
00740 iterator begin() {return iterator(*this,0);}
00742 iterator end() {return iterator(*this,size());}
00744 const_iterator begin() const {return const_iterator(*this,0);}
00746 const_iterator end() const {return const_iterator(*this,size());}
00748 const_iterator cbegin() const {return const_iterator(*this,0);}
00750 const_iterator cend() const {return const_iterator(*this,size());}
00752 reverse_iterator rbegin() {return reverse_iterator(end());}
00754 reverse_iterator rend() {return reverse_iterator(begin());}
00756 const_reverse_iterator rbegin() const {return const_reverse_iterator(end());}
00758 const_reverse_iterator rend() const {return const_reverse_iterator(begin());}
00760 const_reverse_iterator crbegin() const {return const_reverse_iterator(end());}
00762 const_reverse_iterator crend() const {return const_reverse_iterator(begin());}
00764 reference front() {
00765 __TBB_ASSERT( size()>0, NULL);
00766 return static_cast<T*>(my_segment[0].array)[0];
00767 }
00769 const_reference front() const {
00770 __TBB_ASSERT( size()>0, NULL);
00771 return static_cast<const T*>(my_segment[0].array)[0];
00772 }
00774 reference back() {
00775 __TBB_ASSERT( size()>0, NULL);
00776 return internal_subscript( size()-1 );
00777 }
00779 const_reference back() const {
00780 __TBB_ASSERT( size()>0, NULL);
00781 return internal_subscript( size()-1 );
00782 }
00784 allocator_type get_allocator() const { return this->my_allocator; }
00785
00787 void assign(size_type n, const_reference t) {
00788 clear();
00789 internal_resize( n, sizeof(T), max_size(), static_cast<const void*>(&t), &destroy_array, &initialize_array_by );
00790 }
00791
00793 template<class I>
00794 void assign(I first, I last) {
00795 clear(); internal_assign_range( first, last, static_cast<is_integer_tag<std::numeric_limits<I>::is_integer> *>(0) );
00796 }
00797
00799 void swap(concurrent_vector &vector) {
00800 if( this != &vector ) {
00801 concurrent_vector_base_v3::internal_swap(static_cast<concurrent_vector_base_v3&>(vector));
00802 std::swap(this->my_allocator, vector.my_allocator);
00803 }
00804 }
00805
00807
00808 void clear() {
00809 internal_clear(&destroy_array);
00810 }
00811
00813 ~concurrent_vector() {
00814 segment_t *table = my_segment;
00815 internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block );
00816
00817 }
00818
00819 const internal::concurrent_vector_base_v3 &internal_vector_base() const { return *this; }
00820 private:
00822 static void *internal_allocator(internal::concurrent_vector_base_v3 &vb, size_t k) {
00823 return static_cast<concurrent_vector<T, A>&>(vb).my_allocator.allocate(k);
00824 }
00826 void internal_free_segments(void *table[], segment_index_t k, segment_index_t first_block);
00827
00829 T& internal_subscript( size_type index ) const;
00830
00832 T& internal_subscript_with_exceptions( size_type index ) const;
00833
00835 void internal_assign_n(size_type n, const_pointer p) {
00836 internal_resize( n, sizeof(T), max_size(), static_cast<const void*>(p), &destroy_array, p? &initialize_array_by : &initialize_array );
00837 }
00838
00840 template<bool B> class is_integer_tag;
00841
00843 template<class I>
00844 void internal_assign_range(I first, I last, is_integer_tag<true> *) {
00845 internal_assign_n(static_cast<size_type>(first), &static_cast<T&>(last));
00846 }
00848 template<class I>
00849 void internal_assign_range(I first, I last, is_integer_tag<false> *) {
00850 internal_assign_iterators(first, last);
00851 }
00853 template<class I>
00854 void internal_assign_iterators(I first, I last);
00855
00857 static void __TBB_EXPORTED_FUNC initialize_array( void* begin, const void*, size_type n );
00858
00860 static void __TBB_EXPORTED_FUNC initialize_array_by( void* begin, const void* src, size_type n );
00861
00863 static void __TBB_EXPORTED_FUNC copy_array( void* dst, const void* src, size_type n );
00864
00866 static void __TBB_EXPORTED_FUNC assign_array( void* dst, const void* src, size_type n );
00867
00869 static void __TBB_EXPORTED_FUNC destroy_array( void* begin, size_type n );
00870
00872 class internal_loop_guide : internal::no_copy {
00873 public:
00874 const pointer array;
00875 const size_type n;
00876 size_type i;
00877 internal_loop_guide(size_type ntrials, void *ptr)
00878 : array(static_cast<pointer>(ptr)), n(ntrials), i(0) {}
00879 void init() { for(; i < n; ++i) new( &array[i] ) T(); }
00880 void init(const void *src) { for(; i < n; ++i) new( &array[i] ) T(*static_cast<const T*>(src)); }
00881 void copy(const void *src) { for(; i < n; ++i) new( &array[i] ) T(static_cast<const T*>(src)[i]); }
00882 void assign(const void *src) { for(; i < n; ++i) array[i] = static_cast<const T*>(src)[i]; }
00883 template<class I> void iterate(I &src) { for(; i < n; ++i, ++src) new( &array[i] ) T( *src ); }
00884 ~internal_loop_guide() {
00885 if(i < n)
00886 std::memset(array+i, 0, (n-i)*sizeof(value_type));
00887 }
00888 };
00889 };
00890
00891 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
00892 #pragma warning (push)
00893 #pragma warning (disable: 4701) // potentially uninitialized local variable "old"
00894 #endif
00895 template<typename T, class A>
00896 void concurrent_vector<T, A>::shrink_to_fit() {
00897 internal_segments_table old;
00898 __TBB_TRY {
00899 if( internal_compact( sizeof(T), &old, &destroy_array, ©_array ) )
00900 internal_free_segments( old.table, pointers_per_long_table, old.first_block );
00901 } __TBB_CATCH(...) {
00902 if( old.first_block )
00903 internal_free_segments( old.table, 1, old.first_block );
00904 __TBB_RETHROW();
00905 }
00906 }
00907 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
00908 #pragma warning (pop)
00909 #endif // warning 4701 is back
00910
00911 template<typename T, class A>
00912 void concurrent_vector<T, A>::internal_free_segments(void *table[], segment_index_t k, segment_index_t first_block) {
00913
00914 while( k > first_block ) {
00915 --k;
00916 T* array = static_cast<T*>(table[k]);
00917 table[k] = NULL;
00918 if( array > internal::vector_allocation_error_flag )
00919 this->my_allocator.deallocate( array, segment_size(k) );
00920 }
00921 T* array = static_cast<T*>(table[0]);
00922 if( array > internal::vector_allocation_error_flag ) {
00923 __TBB_ASSERT( first_block > 0, NULL );
00924 while(k > 0) table[--k] = NULL;
00925 this->my_allocator.deallocate( array, segment_size(first_block) );
00926 }
00927 }
00928
00929 template<typename T, class A>
00930 T& concurrent_vector<T, A>::internal_subscript( size_type index ) const {
00931 __TBB_ASSERT( index < my_early_size, "index out of bounds" );
00932 size_type j = index;
00933 segment_index_t k = segment_base_index_of( j );
00934 __TBB_ASSERT( (segment_t*)my_segment != my_storage || k < pointers_per_short_table, "index is being allocated" );
00935
00936 T* array = static_cast<T*>( tbb::internal::itt_hide_load_word(my_segment[k].array));
00937 __TBB_ASSERT( array != internal::vector_allocation_error_flag, "the instance is broken by bad allocation. Use at() instead" );
00938 __TBB_ASSERT( array, "index is being allocated" );
00939 return array[j];
00940 }
00941
00942 template<typename T, class A>
00943 T& concurrent_vector<T, A>::internal_subscript_with_exceptions( size_type index ) const {
00944 if( index >= my_early_size )
00945 internal::throw_exception(internal::eid_out_of_range);
00946 size_type j = index;
00947 segment_index_t k = segment_base_index_of( j );
00948 if( (segment_t*)my_segment == my_storage && k >= pointers_per_short_table )
00949 internal::throw_exception(internal::eid_segment_range_error);
00950 void *array = my_segment[k].array;
00951 if( array <= internal::vector_allocation_error_flag )
00952 internal::throw_exception(internal::eid_index_range_error);
00953 return static_cast<T*>(array)[j];
00954 }
00955
00956 template<typename T, class A> template<class I>
00957 void concurrent_vector<T, A>::internal_assign_iterators(I first, I last) {
00958 __TBB_ASSERT(my_early_size == 0, NULL);
00959 size_type n = std::distance(first, last);
00960 if( !n ) return;
00961 internal_reserve(n, sizeof(T), max_size());
00962 my_early_size = n;
00963 segment_index_t k = 0;
00964 size_type sz = segment_size( my_first_block );
00965 while( sz < n ) {
00966 internal_loop_guide loop(sz, my_segment[k].array);
00967 loop.iterate(first);
00968 n -= sz;
00969 if( !k ) k = my_first_block;
00970 else { ++k; sz <<= 1; }
00971 }
00972 internal_loop_guide loop(n, my_segment[k].array);
00973 loop.iterate(first);
00974 }
00975
00976 template<typename T, class A>
00977 void concurrent_vector<T, A>::initialize_array( void* begin, const void *, size_type n ) {
00978 internal_loop_guide loop(n, begin); loop.init();
00979 }
00980
00981 template<typename T, class A>
00982 void concurrent_vector<T, A>::initialize_array_by( void* begin, const void *src, size_type n ) {
00983 internal_loop_guide loop(n, begin); loop.init(src);
00984 }
00985
00986 template<typename T, class A>
00987 void concurrent_vector<T, A>::copy_array( void* dst, const void* src, size_type n ) {
00988 internal_loop_guide loop(n, dst); loop.copy(src);
00989 }
00990
00991 template<typename T, class A>
00992 void concurrent_vector<T, A>::assign_array( void* dst, const void* src, size_type n ) {
00993 internal_loop_guide loop(n, dst); loop.assign(src);
00994 }
00995
00996 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
00997
00998 #pragma warning (push)
00999 #pragma warning (disable: 4189)
01000 #endif
01001 template<typename T, class A>
01002 void concurrent_vector<T, A>::destroy_array( void* begin, size_type n ) {
01003 T* array = static_cast<T*>(begin);
01004 for( size_type j=n; j>0; --j )
01005 array[j-1].~T();
01006 }
01007 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
01008 #pragma warning (pop)
01009 #endif // warning 4189 is back
01010
01011
01012 template<typename T, class A1, class A2>
01013 inline bool operator==(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b) {
01014
01015 if(a.size() != b.size()) return false;
01016 typename concurrent_vector<T, A1>::const_iterator i(a.begin());
01017 typename concurrent_vector<T, A2>::const_iterator j(b.begin());
01018 for(; i != a.end(); ++i, ++j)
01019 if( !(*i == *j) ) return false;
01020 return true;
01021 }
01022
01023 template<typename T, class A1, class A2>
01024 inline bool operator!=(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b)
01025 { return !(a == b); }
01026
01027 template<typename T, class A1, class A2>
01028 inline bool operator<(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b)
01029 { return (std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end())); }
01030
01031 template<typename T, class A1, class A2>
01032 inline bool operator>(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b)
01033 { return b < a; }
01034
01035 template<typename T, class A1, class A2>
01036 inline bool operator<=(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b)
01037 { return !(b < a); }
01038
01039 template<typename T, class A1, class A2>
01040 inline bool operator>=(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b)
01041 { return !(a < b); }
01042
01043 template<typename T, class A>
01044 inline void swap(concurrent_vector<T, A> &a, concurrent_vector<T, A> &b)
01045 { a.swap( b ); }
01046
01047 }
01048
01049 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_Wp64)
01050 #pragma warning (pop)
01051 #endif // warning 4267 is back
01052
01053 #endif