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 <memory>
00028 #include <limits>
00029 #include <new>
00030 #include <cstring>
00031 #include "atomic.h"
00032 #include "cache_aligned_allocator.h"
00033 #include "blocked_range.h"
00034
00035 #include "tbb_machine.h"
00036
00037 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_Wp64)
00038
00039 #pragma warning (push)
00040 #pragma warning (disable: 4267)
00041 #endif
00042
00043 namespace tbb {
00044
00045 template<typename T, class A = cache_aligned_allocator<T> >
00046 class concurrent_vector;
00047
00049 #define __TBB_BAD_ALLOC reinterpret_cast<void*>(size_t(63))
00050
00052 namespace internal {
00053
00055 void* __TBB_EXPORTED_FUNC itt_load_pointer_v3( const void* src );
00056
00058
00059 class concurrent_vector_base_v3 {
00060 protected:
00061
00062
00063 typedef size_t segment_index_t;
00064 typedef size_t size_type;
00065
00066
00067 enum {
00068
00069 default_initial_segments = 1,
00071 pointers_per_short_table = 3,
00072 pointers_per_long_table = sizeof(segment_index_t) * 8
00073 };
00074
00075
00076 struct segment_t {
00077 void* array;
00078 #if TBB_USE_ASSERT
00079 ~segment_t() {
00080 __TBB_ASSERT( array <= __TBB_BAD_ALLOC, "should have been freed by clear" );
00081 }
00082 #endif
00083 };
00084
00085
00086
00088 void* (*vector_allocator_ptr)(concurrent_vector_base_v3 &, size_t);
00089
00091 atomic<size_type> my_first_block;
00092
00094 atomic<size_type> my_early_size;
00095
00097 atomic<segment_t*> my_segment;
00098
00100 segment_t my_storage[pointers_per_short_table];
00101
00102
00103
00104 concurrent_vector_base_v3() {
00105 my_early_size = 0;
00106 my_first_block = 0;
00107 for( segment_index_t i = 0; i < pointers_per_short_table; i++)
00108 my_storage[i].array = NULL;
00109 my_segment = my_storage;
00110 }
00111 __TBB_EXPORTED_METHOD ~concurrent_vector_base_v3();
00112
00113 static segment_index_t segment_index_of( size_type index ) {
00114 return segment_index_t( __TBB_Log2( index|1 ) );
00115 }
00116
00117 static segment_index_t segment_base( segment_index_t k ) {
00118 return (segment_index_t(1)<<k & ~segment_index_t(1));
00119 }
00120
00121 static inline segment_index_t segment_base_index_of( segment_index_t &index ) {
00122 segment_index_t k = segment_index_of( index );
00123 index -= segment_base(k);
00124 return k;
00125 }
00126
00127 static size_type segment_size( segment_index_t k ) {
00128 return segment_index_t(1)<<k;
00129 }
00130
00132 typedef void (__TBB_EXPORTED_FUNC *internal_array_op1)(void* begin, size_type n );
00133
00135 typedef void (__TBB_EXPORTED_FUNC *internal_array_op2)(void* dst, const void* src, size_type n );
00136
00138 struct internal_segments_table {
00139 segment_index_t first_block;
00140 void* table[pointers_per_long_table];
00141 };
00142
00143 void __TBB_EXPORTED_METHOD internal_reserve( size_type n, size_type element_size, size_type max_size );
00144 size_type __TBB_EXPORTED_METHOD internal_capacity() const;
00145 void __TBB_EXPORTED_METHOD internal_grow_to_at_least( size_type new_size, size_type element_size, internal_array_op2 init, const void *src );
00146 void internal_grow( size_type start, size_type finish, size_type element_size, internal_array_op2 init, const void *src );
00147 size_type __TBB_EXPORTED_METHOD internal_grow_by( size_type delta, size_type element_size, internal_array_op2 init, const void *src );
00148 void* __TBB_EXPORTED_METHOD internal_push_back( size_type element_size, size_type& index );
00149 segment_index_t __TBB_EXPORTED_METHOD internal_clear( internal_array_op1 destroy );
00150 void* __TBB_EXPORTED_METHOD internal_compact( size_type element_size, void *table, internal_array_op1 destroy, internal_array_op2 copy );
00151 void __TBB_EXPORTED_METHOD internal_copy( const concurrent_vector_base_v3& src, size_type element_size, internal_array_op2 copy );
00152 void __TBB_EXPORTED_METHOD internal_assign( const concurrent_vector_base_v3& src, size_type element_size,
00153 internal_array_op1 destroy, internal_array_op2 assign, internal_array_op2 copy );
00154 void __TBB_EXPORTED_METHOD internal_throw_exception(size_type) const;
00155 void __TBB_EXPORTED_METHOD internal_swap(concurrent_vector_base_v3& v);
00156
00157 private:
00159 class helper;
00160 friend class helper;
00161 };
00162
00163 typedef concurrent_vector_base_v3 concurrent_vector_base;
00164
00166
00168 template<typename Container, typename Value>
00169 class vector_iterator
00170 {
00172 Container* my_vector;
00173
00175 size_t my_index;
00176
00178
00179 mutable Value* my_item;
00180
00181 template<typename C, typename T>
00182 friend vector_iterator<C,T> operator+( ptrdiff_t offset, const vector_iterator<C,T>& v );
00183
00184 template<typename C, typename T, typename U>
00185 friend bool operator==( const vector_iterator<C,T>& i, const vector_iterator<C,U>& j );
00186
00187 template<typename C, typename T, typename U>
00188 friend bool operator<( const vector_iterator<C,T>& i, const vector_iterator<C,U>& j );
00189
00190 template<typename C, typename T, typename U>
00191 friend ptrdiff_t operator-( const vector_iterator<C,T>& i, const vector_iterator<C,U>& j );
00192
00193 template<typename C, typename U>
00194 friend class internal::vector_iterator;
00195
00196 #if !defined(_MSC_VER) || defined(__INTEL_COMPILER)
00197 template<typename T, class A>
00198 friend class tbb::concurrent_vector;
00199 #else
00200 public:
00201 #endif
00202
00203 vector_iterator( const Container& vector, size_t index ) :
00204 my_vector(const_cast<Container*>(&vector)),
00205 my_index(index),
00206 my_item(NULL)
00207 {}
00208
00209 public:
00211 vector_iterator() : my_vector(NULL), my_index(~size_t(0)), my_item(NULL) {}
00212
00213 vector_iterator( const vector_iterator<Container,typename Container::value_type>& other ) :
00214 my_vector(other.my_vector),
00215 my_index(other.my_index),
00216 my_item(other.my_item)
00217 {}
00218
00219 vector_iterator operator+( ptrdiff_t offset ) const {
00220 return vector_iterator( *my_vector, my_index+offset );
00221 }
00222 vector_iterator &operator+=( ptrdiff_t offset ) {
00223 my_index+=offset;
00224 my_item = NULL;
00225 return *this;
00226 }
00227 vector_iterator operator-( ptrdiff_t offset ) const {
00228 return vector_iterator( *my_vector, my_index-offset );
00229 }
00230 vector_iterator &operator-=( ptrdiff_t offset ) {
00231 my_index-=offset;
00232 my_item = NULL;
00233 return *this;
00234 }
00235 Value& operator*() const {
00236 Value* item = my_item;
00237 if( !item ) {
00238 item = my_item = &my_vector->internal_subscript(my_index);
00239 }
00240 __TBB_ASSERT( item==&my_vector->internal_subscript(my_index), "corrupt cache" );
00241 return *item;
00242 }
00243 Value& operator[]( ptrdiff_t k ) const {
00244 return my_vector->internal_subscript(my_index+k);
00245 }
00246 Value* operator->() const {return &operator*();}
00247
00249 vector_iterator& operator++() {
00250 size_t k = ++my_index;
00251 if( my_item ) {
00252
00253 if( (k& (k-2))==0 ) {
00254
00255 my_item= NULL;
00256 } else {
00257 ++my_item;
00258 }
00259 }
00260 return *this;
00261 }
00262
00264 vector_iterator& operator--() {
00265 __TBB_ASSERT( my_index>0, "operator--() applied to iterator already at beginning of concurrent_vector" );
00266 size_t k = my_index--;
00267 if( my_item ) {
00268
00269 if( (k& (k-2))==0 ) {
00270
00271 my_item= NULL;
00272 } else {
00273 --my_item;
00274 }
00275 }
00276 return *this;
00277 }
00278
00280 vector_iterator operator++(int) {
00281 vector_iterator result = *this;
00282 operator++();
00283 return result;
00284 }
00285
00287 vector_iterator operator--(int) {
00288 vector_iterator result = *this;
00289 operator--();
00290 return result;
00291 }
00292
00293
00294
00295 typedef ptrdiff_t difference_type;
00296 typedef Value value_type;
00297 typedef Value* pointer;
00298 typedef Value& reference;
00299 typedef std::random_access_iterator_tag iterator_category;
00300 };
00301
00302 template<typename Container, typename T>
00303 vector_iterator<Container,T> operator+( ptrdiff_t offset, const vector_iterator<Container,T>& v ) {
00304 return vector_iterator<Container,T>( *v.my_vector, v.my_index+offset );
00305 }
00306
00307 template<typename Container, typename T, typename U>
00308 bool operator==( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
00309 return i.my_index==j.my_index && i.my_vector == j.my_vector;
00310 }
00311
00312 template<typename Container, typename T, typename U>
00313 bool operator!=( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
00314 return !(i==j);
00315 }
00316
00317 template<typename Container, typename T, typename U>
00318 bool operator<( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
00319 return i.my_index<j.my_index;
00320 }
00321
00322 template<typename Container, typename T, typename U>
00323 bool operator>( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
00324 return j<i;
00325 }
00326
00327 template<typename Container, typename T, typename U>
00328 bool operator>=( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
00329 return !(i<j);
00330 }
00331
00332 template<typename Container, typename T, typename U>
00333 bool operator<=( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
00334 return !(j<i);
00335 }
00336
00337 template<typename Container, typename T, typename U>
00338 ptrdiff_t operator-( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) {
00339 return ptrdiff_t(i.my_index)-ptrdiff_t(j.my_index);
00340 }
00341
00342 template<typename T, class A>
00343 class allocator_base {
00344 public:
00345 typedef typename A::template
00346 rebind<T>::other allocator_type;
00347 allocator_type my_allocator;
00348
00349 allocator_base(const allocator_type &a = allocator_type() ) : my_allocator(a) {}
00350 };
00351
00352 }
00354
00356
00410 template<typename T, class A>
00411 class concurrent_vector: protected internal::allocator_base<T, A>,
00412 private internal::concurrent_vector_base_v3 {
00413 private:
00414 template<typename I>
00415 class generic_range_type: public blocked_range<I> {
00416 public:
00417 typedef T value_type;
00418 typedef T& reference;
00419 typedef const T& const_reference;
00420 typedef I iterator;
00421 typedef ptrdiff_t difference_type;
00422 generic_range_type( I begin_, I end_, size_t grainsize = 1) : blocked_range<I>(begin_,end_,grainsize) {}
00423 template<typename U>
00424 generic_range_type( const generic_range_type<U>& r) : blocked_range<I>(r.begin(),r.end(),r.grainsize()) {}
00425 generic_range_type( generic_range_type& r, split ) : blocked_range<I>(r,split()) {}
00426 };
00427
00428 template<typename C, typename U>
00429 friend class internal::vector_iterator;
00430 public:
00431
00432
00433
00434 typedef internal::concurrent_vector_base_v3::size_type size_type;
00435 typedef typename internal::allocator_base<T, A>::allocator_type allocator_type;
00436
00437 typedef T value_type;
00438 typedef ptrdiff_t difference_type;
00439 typedef T& reference;
00440 typedef const T& const_reference;
00441 typedef T *pointer;
00442 typedef const T *const_pointer;
00443
00444 typedef internal::vector_iterator<concurrent_vector,T> iterator;
00445 typedef internal::vector_iterator<concurrent_vector,const T> const_iterator;
00446
00447 #if !defined(_MSC_VER) || _CPPLIB_VER>=300
00448
00449 typedef std::reverse_iterator<iterator> reverse_iterator;
00450 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00451 #else
00452
00453 typedef std::reverse_iterator<iterator,T,T&,T*> reverse_iterator;
00454 typedef std::reverse_iterator<const_iterator,T,const T&,const T*> const_reverse_iterator;
00455 #endif
00456
00457
00458
00459
00460 typedef generic_range_type<iterator> range_type;
00461 typedef generic_range_type<const_iterator> const_range_type;
00462
00463
00464
00465
00466
00468 explicit concurrent_vector(const allocator_type &a = allocator_type())
00469 : internal::allocator_base<T, A>(a)
00470 {
00471 vector_allocator_ptr = &internal_allocator;
00472 }
00473
00475 concurrent_vector( const concurrent_vector& vector, const allocator_type& a = allocator_type() )
00476 : internal::allocator_base<T, A>(a)
00477 {
00478 vector_allocator_ptr = &internal_allocator;
00479 internal_copy(vector, sizeof(T), ©_array);
00480 }
00481
00483 template<class M>
00484 concurrent_vector( const concurrent_vector<T, M>& vector, const allocator_type& a = allocator_type() )
00485 : internal::allocator_base<T, A>(a)
00486 {
00487 vector_allocator_ptr = &internal_allocator;
00488 internal_copy(vector.internal_vector_base(), sizeof(T), ©_array);
00489 }
00490
00492 explicit concurrent_vector(size_type n)
00493 {
00494 vector_allocator_ptr = &internal_allocator;
00495 if ( !n ) return;
00496 internal_reserve(n, sizeof(T), max_size()); my_early_size = n;
00497 __TBB_ASSERT( my_first_block == segment_index_of(n-1)+1, NULL );
00498 initialize_array(static_cast<T*>(my_segment[0].array), NULL, n);
00499 }
00500
00502 concurrent_vector(size_type n, const_reference t, const allocator_type& a = allocator_type())
00503 : internal::allocator_base<T, A>(a)
00504 {
00505 vector_allocator_ptr = &internal_allocator;
00506 internal_assign( n, t );
00507 }
00508
00510 template<class I>
00511 concurrent_vector(I first, I last, const allocator_type &a = allocator_type())
00512 : internal::allocator_base<T, A>(a)
00513 {
00514 vector_allocator_ptr = &internal_allocator;
00515 internal_assign(first, last, static_cast<is_integer_tag<std::numeric_limits<I>::is_integer> *>(0) );
00516 }
00517
00519 concurrent_vector& operator=( const concurrent_vector& vector ) {
00520 if( this != &vector )
00521 concurrent_vector_base_v3::internal_assign(vector, sizeof(T), &destroy_array, &assign_array, ©_array);
00522 return *this;
00523 }
00524
00526 template<class M>
00527 concurrent_vector& operator=( const concurrent_vector<T, M>& vector ) {
00528 if( static_cast<void*>( this ) != static_cast<const void*>( &vector ) )
00529 concurrent_vector_base_v3::internal_assign(vector.internal_vector_base(),
00530 sizeof(T), &destroy_array, &assign_array, ©_array);
00531 return *this;
00532 }
00533
00534
00535
00536
00538
00539 size_type grow_by( size_type delta ) {
00540 return delta ? internal_grow_by( delta, sizeof(T), &initialize_array, NULL ) : my_early_size;
00541 }
00542
00544
00545 size_type grow_by( size_type delta, const_reference t ) {
00546 return delta ? internal_grow_by( delta, sizeof(T), &initialize_array_by, static_cast<const void*>(&t) ) : my_early_size;
00547 }
00548
00550 void grow_to_at_least( size_type n ) {
00551 if( my_early_size<n )
00552 internal_grow_to_at_least( n, sizeof(T), &initialize_array, NULL );
00553 };
00554
00556 size_type push_back( const_reference item ) {
00557 size_type k;
00558 internal_loop_guide loop(1, internal_push_back(sizeof(T),k));
00559 loop.init(&item);
00560 return k;
00561 }
00562
00564
00566 reference operator[]( size_type index ) {
00567 return internal_subscript(index);
00568 }
00569
00571 const_reference operator[]( size_type index ) const {
00572 return internal_subscript(index);
00573 }
00574
00576 reference at( size_type index ) {
00577 return internal_subscript_with_exceptions(index);
00578 }
00579
00581 const_reference at( size_type index ) const {
00582 return internal_subscript_with_exceptions(index);
00583 }
00584
00586 range_type range( size_t grainsize = 1) {
00587 return range_type( begin(), end(), grainsize );
00588 }
00589
00591 const_range_type range( size_t grainsize = 1 ) const {
00592 return const_range_type( begin(), end(), grainsize );
00593 }
00594
00595
00596
00598 size_type size() const {return my_early_size;}
00599
00601 bool empty() const {return !my_early_size;}
00602
00604 size_type capacity() const {return internal_capacity();}
00605
00607
00609 void reserve( size_type n ) {
00610 if( n )
00611 internal_reserve(n, sizeof(T), max_size());
00612 }
00613
00615 void compact();
00616
00618 size_type max_size() const {return (~size_type(0))/sizeof(T);}
00619
00620
00621
00622
00623
00625 iterator begin() {return iterator(*this,0);}
00627 iterator end() {return iterator(*this,size());}
00629 const_iterator begin() const {return const_iterator(*this,0);}
00631 const_iterator end() const {return const_iterator(*this,size());}
00633 reverse_iterator rbegin() {return reverse_iterator(end());}
00635 reverse_iterator rend() {return reverse_iterator(begin());}
00637 const_reverse_iterator rbegin() const {return const_reverse_iterator(end());}
00639 const_reverse_iterator rend() const {return const_reverse_iterator(begin());}
00641 reference front() {
00642 __TBB_ASSERT( size()>0, NULL);
00643 return static_cast<T*>(my_segment[0].array)[0];
00644 }
00646 const_reference front() const {
00647 __TBB_ASSERT( size()>0, NULL);
00648 return static_cast<const T*>(my_segment[0].array)[0];
00649 }
00651 reference back() {
00652 __TBB_ASSERT( size()>0, NULL);
00653 return internal_subscript( my_early_size-1 );
00654 }
00656 const_reference back() const {
00657 __TBB_ASSERT( size()>0, NULL);
00658 return internal_subscript( my_early_size-1 );
00659 }
00661 allocator_type get_allocator() const { return this->my_allocator; }
00662
00664 void assign(size_type n, const_reference t) { clear(); internal_assign( n, t ); }
00665
00667 template<class I>
00668 void assign(I first, I last) {
00669 clear(); internal_assign( first, last, static_cast<is_integer_tag<std::numeric_limits<I>::is_integer> *>(0) );
00670 }
00671
00673 void swap(concurrent_vector &vector) {
00674 if( this != &vector ) {
00675 concurrent_vector_base_v3::internal_swap(static_cast<concurrent_vector_base_v3&>(vector));
00676 std::swap(this->my_allocator, vector.my_allocator);
00677 }
00678 }
00679
00681
00682 void clear() {
00683 internal_clear(&destroy_array);
00684 }
00685
00687 ~concurrent_vector() {
00688 segment_t *table = my_segment;
00689 internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block );
00690
00691 }
00692
00693 const internal::concurrent_vector_base_v3 &internal_vector_base() const { return *this; }
00694 private:
00696 static void *internal_allocator(internal::concurrent_vector_base_v3 &vb, size_t k) {
00697 return static_cast<concurrent_vector<T, A>&>(vb).my_allocator.allocate(k);
00698 }
00700 void internal_free_segments(void *table[], segment_index_t k, segment_index_t first_block);
00701
00703 T& internal_subscript( size_type index ) const;
00704
00706 T& internal_subscript_with_exceptions( size_type index ) const;
00707
00709 void internal_assign(size_type n, const_reference t);
00710
00712 template<bool B> class is_integer_tag;
00713
00715 template<class I>
00716 void internal_assign(I first, I last, is_integer_tag<true> *) {
00717 internal_assign(static_cast<size_type>(first), static_cast<T>(last));
00718 }
00720 template<class I>
00721 void internal_assign(I first, I last, is_integer_tag<false> *) {
00722 internal_assign_iterators(first, last);
00723 }
00725 template<class I>
00726 void internal_assign_iterators(I first, I last);
00727
00729 static void __TBB_EXPORTED_FUNC initialize_array( void* begin, const void*, size_type n );
00730
00732 static void __TBB_EXPORTED_FUNC initialize_array_by( void* begin, const void* src, size_type n );
00733
00735 static void __TBB_EXPORTED_FUNC copy_array( void* dst, const void* src, size_type n );
00736
00738 static void __TBB_EXPORTED_FUNC assign_array( void* dst, const void* src, size_type n );
00739
00741 static void __TBB_EXPORTED_FUNC destroy_array( void* begin, size_type n );
00742
00744 class internal_loop_guide : internal::no_copy {
00745 public:
00746 const pointer array;
00747 const size_type n;
00748 size_type i;
00749 internal_loop_guide(size_type ntrials, void *ptr)
00750 : array(static_cast<pointer>(ptr)), n(ntrials), i(0) {}
00751 void init() { for(; i < n; ++i) new( &array[i] ) T(); }
00752 void init(const void *src) { for(; i < n; ++i) new( &array[i] ) T(*static_cast<const T*>(src)); }
00753 void copy(const void *src) { for(; i < n; ++i) new( &array[i] ) T(static_cast<const T*>(src)[i]); }
00754 void assign(const void *src) { for(; i < n; ++i) array[i] = static_cast<const T*>(src)[i]; }
00755 template<class I> void iterate(I &src) { for(; i < n; ++i, ++src) new( &array[i] ) T( *src ); }
00756 ~internal_loop_guide() {
00757 if(i < n)
00758 std::memset(array+i, 0, (n-i)*sizeof(value_type));
00759 }
00760 };
00761 };
00762
00763 template<typename T, class A>
00764 void concurrent_vector<T, A>::compact() {
00765 internal_segments_table old;
00766 try {
00767 if( internal_compact( sizeof(T), &old, &destroy_array, ©_array ) )
00768 internal_free_segments( old.table, pointers_per_long_table, old.first_block );
00769 } catch(...) {
00770 if( old.first_block )
00771 internal_free_segments( old.table, 1, old.first_block );
00772 throw;
00773 }
00774 }
00775
00776 template<typename T, class A>
00777 void concurrent_vector<T, A>::internal_free_segments(void *table[], segment_index_t k, segment_index_t first_block) {
00778
00779 while( k > first_block ) {
00780 --k;
00781 T* array = static_cast<T*>(table[k]);
00782 table[k] = NULL;
00783 if( array > __TBB_BAD_ALLOC )
00784 this->my_allocator.deallocate( array, segment_size(k) );
00785 }
00786 T* array = static_cast<T*>(table[0]);
00787 if( array > __TBB_BAD_ALLOC ) {
00788 __TBB_ASSERT( first_block > 0, NULL );
00789 while(k > 0) table[--k] = NULL;
00790 this->my_allocator.deallocate( array, segment_size(first_block) );
00791 }
00792 }
00793
00794 template<typename T, class A>
00795 T& concurrent_vector<T, A>::internal_subscript( size_type index ) const {
00796 __TBB_ASSERT( index<size(), "index out of bounds" );
00797 size_type j = index;
00798 segment_index_t k = segment_base_index_of( j );
00799
00800 #if TBB_USE_THREADING_TOOLS
00801 return static_cast<T*>( tbb::internal::itt_load_pointer_v3(&my_segment[k].array))[j];
00802 #else
00803 return static_cast<T*>(my_segment[k].array)[j];
00804 #endif
00805 }
00806
00807 template<typename T, class A>
00808 T& concurrent_vector<T, A>::internal_subscript_with_exceptions( size_type index ) const {
00809 if( index >= size() )
00810 internal_throw_exception(0);
00811 size_type j = index;
00812 segment_index_t k = segment_base_index_of( j );
00813 if( my_segment == (segment_t*)my_storage && k >= pointers_per_short_table )
00814 internal_throw_exception(1);
00815 void *array = my_segment[k].array;
00816 if( array <= __TBB_BAD_ALLOC )
00817 internal_throw_exception(2);
00818 return static_cast<T*>(array)[j];
00819 }
00820
00821 template<typename T, class A>
00822 void concurrent_vector<T, A>::internal_assign(size_type n, const_reference t)
00823 {
00824 __TBB_ASSERT(my_early_size == 0, NULL);
00825 if( !n ) return;
00826 internal_reserve(n, sizeof(T), max_size());
00827 my_early_size = n;
00828 segment_index_t k = 0;
00829 size_type sz = segment_size( my_first_block );
00830 while( sz < n ) {
00831 initialize_array_by(static_cast<T*>(my_segment[k].array), static_cast<const void*>(&t), sz);
00832 n -= sz;
00833 if( !k ) k = my_first_block;
00834 else { ++k; sz <<= 1; }
00835 }
00836 initialize_array_by(static_cast<T*>(my_segment[k].array), static_cast<const void*>(&t), n);
00837 }
00838
00839 template<typename T, class A> template<class I>
00840 void concurrent_vector<T, A>::internal_assign_iterators(I first, I last) {
00841 __TBB_ASSERT(my_early_size == 0, NULL);
00842 size_type n = std::distance(first, last);
00843 if( !n ) return;
00844 internal_reserve(n, sizeof(T), max_size());
00845 my_early_size = n;
00846 segment_index_t k = 0;
00847 size_type sz = segment_size( my_first_block );
00848 while( sz < n ) {
00849 internal_loop_guide loop(sz, my_segment[k].array);
00850 loop.iterate(first);
00851 n -= sz;
00852 if( !k ) k = my_first_block;
00853 else { ++k; sz <<= 1; }
00854 }
00855 internal_loop_guide loop(n, my_segment[k].array);
00856 loop.iterate(first);
00857 }
00858
00859 template<typename T, class A>
00860 void concurrent_vector<T, A>::initialize_array( void* begin, const void *, size_type n ) {
00861 internal_loop_guide loop(n, begin); loop.init();
00862 }
00863
00864 template<typename T, class A>
00865 void concurrent_vector<T, A>::initialize_array_by( void* begin, const void *src, size_type n ) {
00866 internal_loop_guide loop(n, begin); loop.init(src);
00867 }
00868
00869 template<typename T, class A>
00870 void concurrent_vector<T, A>::copy_array( void* dst, const void* src, size_type n ) {
00871 internal_loop_guide loop(n, dst); loop.copy(src);
00872 }
00873
00874 template<typename T, class A>
00875 void concurrent_vector<T, A>::assign_array( void* dst, const void* src, size_type n ) {
00876 internal_loop_guide loop(n, dst); loop.assign(src);
00877 }
00878
00879 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
00880
00881 #pragma warning (push)
00882 #pragma warning (disable: 4189)
00883 #endif
00884 template<typename T, class A>
00885 void concurrent_vector<T, A>::destroy_array( void* begin, size_type n ) {
00886 T* array = static_cast<T*>(begin);
00887 for( size_type j=n; j>0; --j )
00888 array[j-1].~T();
00889 }
00890 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
00891 #pragma warning (pop)
00892 #endif // warning 4189 is back
00893
00894
00895 template<typename T, class A1, class A2>
00896 inline bool operator==(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b) {
00897
00898
00899 if(a.size() != b.size()) return false;
00900 typename concurrent_vector<T, A1>::const_iterator i(a.begin());
00901 typename concurrent_vector<T, A2>::const_iterator j(b.begin());
00902 for(; i != a.end(); ++i, ++j)
00903 if( !(*i == *j) ) return false;
00904 return true;
00905 }
00906
00907 template<typename T, class A1, class A2>
00908 inline bool operator!=(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b)
00909 { return !(a == b); }
00910
00911 template<typename T, class A1, class A2>
00912 inline bool operator<(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b)
00913 { return (std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end())); }
00914
00915 template<typename T, class A1, class A2>
00916 inline bool operator>(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b)
00917 { return b < a; }
00918
00919 template<typename T, class A1, class A2>
00920 inline bool operator<=(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b)
00921 { return !(b < a); }
00922
00923 template<typename T, class A1, class A2>
00924 inline bool operator>=(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b)
00925 { return !(a < b); }
00926
00927 template<typename T, class A>
00928 inline void swap(concurrent_vector<T, A> &a, concurrent_vector<T, A> &b)
00929 { a.swap( b ); }
00930
00931 }
00932
00933 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_Wp64)
00934 #pragma warning (pop)
00935 #endif // warning 4267 is back
00936
00937 #endif