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