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