![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
00001 /* 00002 Copyright 2005-2010 Intel Corporation. All Rights Reserved. 00003 00004 This file is part of Threading Building Blocks. 00005 00006 Threading Building Blocks is free software; you can redistribute it 00007 and/or modify it under the terms of the GNU General Public License 00008 version 2 as published by the Free Software Foundation. 00009 00010 Threading Building Blocks is distributed in the hope that it will be 00011 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00012 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with Threading Building Blocks; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00018 00019 As a special exception, you may use this file as part of a free software 00020 library without restriction. Specifically, if other files instantiate 00021 templates or use macros or inline functions from this file, or you compile 00022 this file and link it with other files to produce an executable, this 00023 file does not by itself cause the resulting executable to be covered by 00024 the GNU General Public License. This exception does not however 00025 invalidate any other reasons why the executable file might be covered by 00026 the GNU General Public License. 00027 */ 00028 00029 #ifndef __TBB_concurrent_vector_H 00030 #define __TBB_concurrent_vector_H 00031 00032 #include "tbb_stddef.h" 00033 #include "tbb_exception.h" 00034 #include "atomic.h" 00035 #include "cache_aligned_allocator.h" 00036 #include "blocked_range.h" 00037 #include "tbb_machine.h" 00038 #include <new> 00039 00040 #if !TBB_USE_EXCEPTIONS && _MSC_VER 00041 // Suppress "C++ exception handler used, but unwind semantics are not enabled" warning in STL headers 00042 #pragma warning (push) 00043 #pragma warning (disable: 4530) 00044 #endif 00045 00046 #include <algorithm> 00047 #include <iterator> 00048 00049 #if !TBB_USE_EXCEPTIONS && _MSC_VER 00050 #pragma warning (pop) 00051 #endif 00052 00053 #if _MSC_VER==1500 && !__INTEL_COMPILER 00054 // VS2008/VC9 seems to have an issue; limits pull in math.h 00055 #pragma warning( push ) 00056 #pragma warning( disable: 4985 ) 00057 #endif 00058 #include <limits> /* std::numeric_limits */ 00059 #if _MSC_VER==1500 && !__INTEL_COMPILER 00060 #pragma warning( pop ) 00061 #endif 00062 00063 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_Wp64) 00064 // Workaround for overzealous compiler warnings in /Wp64 mode 00065 #pragma warning (push) 00066 #pragma warning (disable: 4267) 00067 #endif 00068 00069 namespace tbb { 00070 00071 template<typename T, class A = cache_aligned_allocator<T> > 00072 class concurrent_vector; 00073 00075 namespace internal { 00076 00078 static void *const vector_allocation_error_flag = reinterpret_cast<void*>(size_t(63)); 00079 00081 void* __TBB_EXPORTED_FUNC itt_load_pointer_v3( const void* src ); 00082 00084 00085 class concurrent_vector_base_v3 { 00086 protected: 00087 00088 // Basic types declarations 00089 typedef size_t segment_index_t; 00090 typedef size_t size_type; 00091 00092 // Using enumerations due to Mac linking problems of static const variables 00093 enum { 00094 // Size constants 00095 default_initial_segments = 1, // 2 initial items 00097 pointers_per_short_table = 3, // to fit into 8 words of entire structure 00098 pointers_per_long_table = sizeof(segment_index_t) * 8 // one segment per bit 00099 }; 00100 00101 // Segment pointer. Can be zero-initialized 00102 struct segment_t { 00103 void* array; 00104 #if TBB_USE_ASSERT 00105 ~segment_t() { 00106 __TBB_ASSERT( array <= internal::vector_allocation_error_flag, "should have been freed by clear" ); 00107 } 00108 #endif /* TBB_USE_ASSERT */ 00109 }; 00110 00111 // Data fields 00112 00114 void* (*vector_allocator_ptr)(concurrent_vector_base_v3 &, size_t); 00115 00117 atomic<size_type> my_first_block; 00118 00120 atomic<size_type> my_early_size; 00121 00123 atomic<segment_t*> my_segment; 00124 00126 segment_t my_storage[pointers_per_short_table]; 00127 00128 // Methods 00129 00130 concurrent_vector_base_v3() { 00131 my_early_size = 0; 00132 my_first_block = 0; // here is not default_initial_segments 00133 for( segment_index_t i = 0; i < pointers_per_short_table; i++) 00134 my_storage[i].array = NULL; 00135 my_segment = my_storage; 00136 } 00137 __TBB_EXPORTED_METHOD ~concurrent_vector_base_v3(); 00138 00139 static segment_index_t segment_index_of( size_type index ) { 00140 return segment_index_t( __TBB_Log2( index|1 ) ); 00141 } 00142 00143 static segment_index_t segment_base( segment_index_t k ) { 00144 return (segment_index_t(1)<<k & ~segment_index_t(1)); 00145 } 00146 00147 static inline segment_index_t segment_base_index_of( segment_index_t &index ) { 00148 segment_index_t k = segment_index_of( index ); 00149 index -= segment_base(k); 00150 return k; 00151 } 00152 00153 static size_type segment_size( segment_index_t k ) { 00154 return segment_index_t(1)<<k; // fake value for k==0 00155 } 00156 00158 typedef void (__TBB_EXPORTED_FUNC *internal_array_op1)(void* begin, size_type n ); 00159 00161 typedef void (__TBB_EXPORTED_FUNC *internal_array_op2)(void* dst, const void* src, size_type n ); 00162 00164 struct internal_segments_table { 00165 segment_index_t first_block; 00166 void* table[pointers_per_long_table]; 00167 }; 00168 00169 void __TBB_EXPORTED_METHOD internal_reserve( size_type n, size_type element_size, size_type max_size ); 00170 size_type __TBB_EXPORTED_METHOD internal_capacity() const; 00171 void internal_grow( size_type start, size_type finish, size_type element_size, internal_array_op2 init, const void *src ); 00172 size_type __TBB_EXPORTED_METHOD internal_grow_by( size_type delta, size_type element_size, internal_array_op2 init, const void *src ); 00173 void* __TBB_EXPORTED_METHOD internal_push_back( size_type element_size, size_type& index ); 00174 segment_index_t __TBB_EXPORTED_METHOD internal_clear( internal_array_op1 destroy ); 00175 void* __TBB_EXPORTED_METHOD internal_compact( size_type element_size, void *table, internal_array_op1 destroy, internal_array_op2 copy ); 00176 void __TBB_EXPORTED_METHOD internal_copy( const concurrent_vector_base_v3& src, size_type element_size, internal_array_op2 copy ); 00177 void __TBB_EXPORTED_METHOD internal_assign( const concurrent_vector_base_v3& src, size_type element_size, 00178 internal_array_op1 destroy, internal_array_op2 assign, internal_array_op2 copy ); 00180 void __TBB_EXPORTED_METHOD internal_throw_exception(size_type) const; 00181 void __TBB_EXPORTED_METHOD internal_swap(concurrent_vector_base_v3& v); 00182 00183 void __TBB_EXPORTED_METHOD internal_resize( size_type n, size_type element_size, size_type max_size, const void *src, 00184 internal_array_op1 destroy, internal_array_op2 init ); 00185 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 ); 00186 00188 void __TBB_EXPORTED_METHOD internal_grow_to_at_least( size_type new_size, size_type element_size, internal_array_op2 init, const void *src ); 00189 private: 00191 class helper; 00192 friend class helper; 00193 }; 00194 00195 typedef concurrent_vector_base_v3 concurrent_vector_base; 00196 00198 00200 template<typename Container, typename Value> 00201 class vector_iterator 00202 { 00204 Container* my_vector; 00205 00207 size_t my_index; 00208 00210 00211 mutable Value* my_item; 00212 00213 template<typename C, typename T> 00214 friend vector_iterator<C,T> operator+( ptrdiff_t offset, const vector_iterator<C,T>& v ); 00215 00216 template<typename C, typename T, typename U> 00217 friend bool operator==( const vector_iterator<C,T>& i, const vector_iterator<C,U>& j ); 00218 00219 template<typename C, typename T, typename U> 00220 friend bool operator<( const vector_iterator<C,T>& i, const vector_iterator<C,U>& j ); 00221 00222 template<typename C, typename T, typename U> 00223 friend ptrdiff_t operator-( const vector_iterator<C,T>& i, const vector_iterator<C,U>& j ); 00224 00225 template<typename C, typename U> 00226 friend class internal::vector_iterator; 00227 00228 #if !defined(_MSC_VER) || defined(__INTEL_COMPILER) 00229 template<typename T, class A> 00230 friend class tbb::concurrent_vector; 00231 #else 00232 public: // workaround for MSVC 00233 #endif 00234 00235 vector_iterator( const Container& vector, size_t index, void *ptr = 0 ) : 00236 my_vector(const_cast<Container*>(&vector)), 00237 my_index(index), 00238 my_item(static_cast<Value*>(ptr)) 00239 {} 00240 00241 public: 00243 vector_iterator() : my_vector(NULL), my_index(~size_t(0)), my_item(NULL) {} 00244 00245 vector_iterator( const vector_iterator<Container,typename Container::value_type>& other ) : 00246 my_vector(other.my_vector), 00247 my_index(other.my_index), 00248 my_item(other.my_item) 00249 {} 00250 00251 vector_iterator operator+( ptrdiff_t offset ) const { 00252 return vector_iterator( *my_vector, my_index+offset ); 00253 } 00254 vector_iterator &operator+=( ptrdiff_t offset ) { 00255 my_index+=offset; 00256 my_item = NULL; 00257 return *this; 00258 } 00259 vector_iterator operator-( ptrdiff_t offset ) const { 00260 return vector_iterator( *my_vector, my_index-offset ); 00261 } 00262 vector_iterator &operator-=( ptrdiff_t offset ) { 00263 my_index-=offset; 00264 my_item = NULL; 00265 return *this; 00266 } 00267 Value& operator*() const { 00268 Value* item = my_item; 00269 if( !item ) { 00270 item = my_item = &my_vector->internal_subscript(my_index); 00271 } 00272 __TBB_ASSERT( item==&my_vector->internal_subscript(my_index), "corrupt cache" ); 00273 return *item; 00274 } 00275 Value& operator[]( ptrdiff_t k ) const { 00276 return my_vector->internal_subscript(my_index+k); 00277 } 00278 Value* operator->() const {return &operator*();} 00279 00281 vector_iterator& operator++() { 00282 size_t k = ++my_index; 00283 if( my_item ) { 00284 // Following test uses 2's-complement wizardry 00285 if( (k& (k-2))==0 ) { 00286 // k is a power of two that is at least k-2 00287 my_item= NULL; 00288 } else { 00289 ++my_item; 00290 } 00291 } 00292 return *this; 00293 } 00294 00296 vector_iterator& operator--() { 00297 __TBB_ASSERT( my_index>0, "operator--() applied to iterator already at beginning of concurrent_vector" ); 00298 size_t k = my_index--; 00299 if( my_item ) { 00300 // Following test uses 2's-complement wizardry 00301 if( (k& (k-2))==0 ) { 00302 // k is a power of two that is at least k-2 00303 my_item= NULL; 00304 } else { 00305 --my_item; 00306 } 00307 } 00308 return *this; 00309 } 00310 00312 vector_iterator operator++(int) { 00313 vector_iterator result = *this; 00314 operator++(); 00315 return result; 00316 } 00317 00319 vector_iterator operator--(int) { 00320 vector_iterator result = *this; 00321 operator--(); 00322 return result; 00323 } 00324 00325 // STL support 00326 00327 typedef ptrdiff_t difference_type; 00328 typedef Value value_type; 00329 typedef Value* pointer; 00330 typedef Value& reference; 00331 typedef std::random_access_iterator_tag iterator_category; 00332 }; 00333 00334 template<typename Container, typename T> 00335 vector_iterator<Container,T> operator+( ptrdiff_t offset, const vector_iterator<Container,T>& v ) { 00336 return vector_iterator<Container,T>( *v.my_vector, v.my_index+offset ); 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 && i.my_vector == j.my_vector; 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 !(i==j); 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.my_index<j.my_index; 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 bool operator>=( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) { 00361 return !(i<j); 00362 } 00363 00364 template<typename Container, typename T, typename U> 00365 bool operator<=( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) { 00366 return !(j<i); 00367 } 00368 00369 template<typename Container, typename T, typename U> 00370 ptrdiff_t operator-( const vector_iterator<Container,T>& i, const vector_iterator<Container,U>& j ) { 00371 return ptrdiff_t(i.my_index)-ptrdiff_t(j.my_index); 00372 } 00373 00374 template<typename T, class A> 00375 class allocator_base { 00376 public: 00377 typedef typename A::template 00378 rebind<T>::other allocator_type; 00379 allocator_type my_allocator; 00380 00381 allocator_base(const allocator_type &a = allocator_type() ) : my_allocator(a) {} 00382 }; 00383 00384 } // namespace internal 00386 00388 00449 template<typename T, class A> 00450 class concurrent_vector: protected internal::allocator_base<T, A>, 00451 private internal::concurrent_vector_base { 00452 private: 00453 template<typename I> 00454 class generic_range_type: public blocked_range<I> { 00455 public: 00456 typedef T value_type; 00457 typedef T& reference; 00458 typedef const T& const_reference; 00459 typedef I iterator; 00460 typedef ptrdiff_t difference_type; 00461 generic_range_type( I begin_, I end_, size_t grainsize_ = 1) : blocked_range<I>(begin_,end_,grainsize_) {} 00462 template<typename U> 00463 generic_range_type( const generic_range_type<U>& r) : blocked_range<I>(r.begin(),r.end(),r.grainsize()) {} 00464 generic_range_type( generic_range_type& r, split ) : blocked_range<I>(r,split()) {} 00465 }; 00466 00467 template<typename C, typename U> 00468 friend class internal::vector_iterator; 00469 public: 00470 //------------------------------------------------------------------------ 00471 // STL compatible types 00472 //------------------------------------------------------------------------ 00473 typedef internal::concurrent_vector_base_v3::size_type size_type; 00474 typedef typename internal::allocator_base<T, A>::allocator_type allocator_type; 00475 00476 typedef T value_type; 00477 typedef ptrdiff_t difference_type; 00478 typedef T& reference; 00479 typedef const T& const_reference; 00480 typedef T *pointer; 00481 typedef const T *const_pointer; 00482 00483 typedef internal::vector_iterator<concurrent_vector,T> iterator; 00484 typedef internal::vector_iterator<concurrent_vector,const T> const_iterator; 00485 00486 #if !defined(_MSC_VER) || _CPPLIB_VER>=300 00487 // Assume ISO standard definition of std::reverse_iterator 00488 typedef std::reverse_iterator<iterator> reverse_iterator; 00489 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00490 #else 00491 // Use non-standard std::reverse_iterator 00492 typedef std::reverse_iterator<iterator,T,T&,T*> reverse_iterator; 00493 typedef std::reverse_iterator<const_iterator,T,const T&,const T*> const_reverse_iterator; 00494 #endif /* defined(_MSC_VER) && (_MSC_VER<1300) */ 00495 00496 //------------------------------------------------------------------------ 00497 // Parallel algorithm support 00498 //------------------------------------------------------------------------ 00499 typedef generic_range_type<iterator> range_type; 00500 typedef generic_range_type<const_iterator> const_range_type; 00501 00502 //------------------------------------------------------------------------ 00503 // STL compatible constructors & destructors 00504 //------------------------------------------------------------------------ 00505 00507 explicit concurrent_vector(const allocator_type &a = allocator_type()) 00508 : internal::allocator_base<T, A>(a), internal::concurrent_vector_base() 00509 { 00510 vector_allocator_ptr = &internal_allocator; 00511 } 00512 00514 concurrent_vector( const concurrent_vector& vector, const allocator_type& a = allocator_type() ) 00515 : internal::allocator_base<T, A>(a), internal::concurrent_vector_base() 00516 { 00517 vector_allocator_ptr = &internal_allocator; 00518 __TBB_TRY { 00519 internal_copy(vector, sizeof(T), ©_array); 00520 } __TBB_CATCH(...) { 00521 segment_t *table = my_segment; 00522 internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block ); 00523 __TBB_RETHROW(); 00524 } 00525 } 00526 00528 template<class M> 00529 concurrent_vector( const concurrent_vector<T, M>& vector, const allocator_type& a = allocator_type() ) 00530 : internal::allocator_base<T, A>(a), internal::concurrent_vector_base() 00531 { 00532 vector_allocator_ptr = &internal_allocator; 00533 __TBB_TRY { 00534 internal_copy(vector.internal_vector_base(), sizeof(T), ©_array); 00535 } __TBB_CATCH(...) { 00536 segment_t *table = my_segment; 00537 internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block ); 00538 __TBB_RETHROW(); 00539 } 00540 } 00541 00543 explicit concurrent_vector(size_type n) 00544 { 00545 vector_allocator_ptr = &internal_allocator; 00546 __TBB_TRY { 00547 internal_resize( n, sizeof(T), max_size(), NULL, &destroy_array, &initialize_array ); 00548 } __TBB_CATCH(...) { 00549 segment_t *table = my_segment; 00550 internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block ); 00551 __TBB_RETHROW(); 00552 } 00553 } 00554 00556 concurrent_vector(size_type n, const_reference t, const allocator_type& a = allocator_type()) 00557 : internal::allocator_base<T, A>(a) 00558 { 00559 vector_allocator_ptr = &internal_allocator; 00560 __TBB_TRY { 00561 internal_resize( n, sizeof(T), max_size(), static_cast<const void*>(&t), &destroy_array, &initialize_array_by ); 00562 } __TBB_CATCH(...) { 00563 segment_t *table = my_segment; 00564 internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block ); 00565 __TBB_RETHROW(); 00566 } 00567 } 00568 00570 template<class I> 00571 concurrent_vector(I first, I last, const allocator_type &a = allocator_type()) 00572 : internal::allocator_base<T, A>(a) 00573 { 00574 vector_allocator_ptr = &internal_allocator; 00575 __TBB_TRY { 00576 internal_assign_range(first, last, static_cast<is_integer_tag<std::numeric_limits<I>::is_integer> *>(0) ); 00577 } __TBB_CATCH(...) { 00578 segment_t *table = my_segment; 00579 internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block ); 00580 __TBB_RETHROW(); 00581 } 00582 } 00583 00585 concurrent_vector& operator=( const concurrent_vector& vector ) { 00586 if( this != &vector ) 00587 internal_assign(vector, sizeof(T), &destroy_array, &assign_array, ©_array); 00588 return *this; 00589 } 00590 00592 template<class M> 00593 concurrent_vector& operator=( const concurrent_vector<T, M>& vector ) { 00594 if( static_cast<void*>( this ) != static_cast<const void*>( &vector ) ) 00595 internal_assign(vector.internal_vector_base(), 00596 sizeof(T), &destroy_array, &assign_array, ©_array); 00597 return *this; 00598 } 00599 00600 //------------------------------------------------------------------------ 00601 // Concurrent operations 00602 //------------------------------------------------------------------------ 00604 #if TBB_DEPRECATED 00605 00606 size_type grow_by( size_type delta ) { 00607 return delta ? internal_grow_by( delta, sizeof(T), &initialize_array, NULL ) : my_early_size; 00608 } 00609 #else 00610 00611 iterator grow_by( size_type delta ) { 00612 return iterator(*this, delta ? internal_grow_by( delta, sizeof(T), &initialize_array, NULL ) : my_early_size); 00613 } 00614 #endif 00615 00617 #if TBB_DEPRECATED 00618 00619 size_type grow_by( size_type delta, const_reference t ) { 00620 return delta ? internal_grow_by( delta, sizeof(T), &initialize_array_by, static_cast<const void*>(&t) ) : my_early_size; 00621 } 00622 #else 00623 00624 iterator grow_by( size_type delta, const_reference t ) { 00625 return iterator(*this, delta ? internal_grow_by( delta, sizeof(T), &initialize_array_by, static_cast<const void*>(&t) ) : my_early_size); 00626 } 00627 #endif 00628 00630 #if TBB_DEPRECATED 00631 00633 void grow_to_at_least( size_type n ) { 00634 if( n ) internal_grow_to_at_least_with_result( n, sizeof(T), &initialize_array, NULL ); 00635 }; 00636 #else 00637 00641 iterator grow_to_at_least( size_type n ) { 00642 size_type m=0; 00643 if( n ) { 00644 m = internal_grow_to_at_least_with_result( n, sizeof(T), &initialize_array, NULL ); 00645 if( m>n ) m=n; 00646 } 00647 return iterator(*this, m); 00648 }; 00649 #endif 00650 00652 #if TBB_DEPRECATED 00653 size_type push_back( const_reference item ) 00654 #else 00655 00656 iterator push_back( const_reference item ) 00657 #endif 00658 { 00659 size_type k; 00660 void *ptr = internal_push_back(sizeof(T),k); 00661 internal_loop_guide loop(1, ptr); 00662 loop.init(&item); 00663 #if TBB_DEPRECATED 00664 return k; 00665 #else 00666 return iterator(*this, k, ptr); 00667 #endif 00668 } 00669 00671 00673 reference operator[]( size_type index ) { 00674 return internal_subscript(index); 00675 } 00676 00678 const_reference operator[]( size_type index ) const { 00679 return internal_subscript(index); 00680 } 00681 00683 reference at( size_type index ) { 00684 return internal_subscript_with_exceptions(index); 00685 } 00686 00688 const_reference at( size_type index ) const { 00689 return internal_subscript_with_exceptions(index); 00690 } 00691 00693 range_type range( size_t grainsize = 1) { 00694 return range_type( begin(), end(), grainsize ); 00695 } 00696 00698 const_range_type range( size_t grainsize = 1 ) const { 00699 return const_range_type( begin(), end(), grainsize ); 00700 } 00701 //------------------------------------------------------------------------ 00702 // Capacity 00703 //------------------------------------------------------------------------ 00705 size_type size() const { 00706 size_type sz = my_early_size, cp = internal_capacity(); 00707 return cp < sz ? cp : sz; 00708 } 00709 00711 bool empty() const {return !my_early_size;} 00712 00714 size_type capacity() const {return internal_capacity();} 00715 00717 00719 void reserve( size_type n ) { 00720 if( n ) 00721 internal_reserve(n, sizeof(T), max_size()); 00722 } 00723 00725 void resize( size_type n ) { 00726 internal_resize( n, sizeof(T), max_size(), NULL, &destroy_array, &initialize_array ); 00727 } 00728 00730 void resize( size_type n, const_reference t ) { 00731 internal_resize( n, sizeof(T), max_size(), static_cast<const void*>(&t), &destroy_array, &initialize_array_by ); 00732 } 00733 00734 #if TBB_DEPRECATED 00735 00736 void compact() {shrink_to_fit();} 00737 #endif /* TBB_DEPRECATED */ 00738 00740 void shrink_to_fit(); 00741 00743 size_type max_size() const {return (~size_type(0))/sizeof(T);} 00744 00745 //------------------------------------------------------------------------ 00746 // STL support 00747 //------------------------------------------------------------------------ 00748 00750 iterator begin() {return iterator(*this,0);} 00752 iterator end() {return iterator(*this,size());} 00754 const_iterator begin() const {return const_iterator(*this,0);} 00756 const_iterator end() const {return const_iterator(*this,size());} 00758 const_iterator cbegin() const {return const_iterator(*this,0);} 00760 const_iterator cend() const {return const_iterator(*this,size());} 00762 reverse_iterator rbegin() {return reverse_iterator(end());} 00764 reverse_iterator rend() {return reverse_iterator(begin());} 00766 const_reverse_iterator rbegin() const {return const_reverse_iterator(end());} 00768 const_reverse_iterator rend() const {return const_reverse_iterator(begin());} 00770 const_reverse_iterator crbegin() const {return const_reverse_iterator(end());} 00772 const_reverse_iterator crend() const {return const_reverse_iterator(begin());} 00774 reference front() { 00775 __TBB_ASSERT( size()>0, NULL); 00776 return static_cast<T*>(my_segment[0].array)[0]; 00777 } 00779 const_reference front() const { 00780 __TBB_ASSERT( size()>0, NULL); 00781 return static_cast<const T*>(my_segment[0].array)[0]; 00782 } 00784 reference back() { 00785 __TBB_ASSERT( size()>0, NULL); 00786 return internal_subscript( size()-1 ); 00787 } 00789 const_reference back() const { 00790 __TBB_ASSERT( size()>0, NULL); 00791 return internal_subscript( size()-1 ); 00792 } 00794 allocator_type get_allocator() const { return this->my_allocator; } 00795 00797 void assign(size_type n, const_reference t) { 00798 clear(); 00799 internal_resize( n, sizeof(T), max_size(), static_cast<const void*>(&t), &destroy_array, &initialize_array_by ); 00800 } 00801 00803 template<class I> 00804 void assign(I first, I last) { 00805 clear(); internal_assign_range( first, last, static_cast<is_integer_tag<std::numeric_limits<I>::is_integer> *>(0) ); 00806 } 00807 00809 void swap(concurrent_vector &vector) { 00810 if( this != &vector ) { 00811 concurrent_vector_base_v3::internal_swap(static_cast<concurrent_vector_base_v3&>(vector)); 00812 std::swap(this->my_allocator, vector.my_allocator); 00813 } 00814 } 00815 00817 00818 void clear() { 00819 internal_clear(&destroy_array); 00820 } 00821 00823 ~concurrent_vector() { 00824 segment_t *table = my_segment; 00825 internal_free_segments( reinterpret_cast<void**>(table), internal_clear(&destroy_array), my_first_block ); 00826 // base class destructor call should be then 00827 } 00828 00829 const internal::concurrent_vector_base_v3 &internal_vector_base() const { return *this; } 00830 private: 00832 static void *internal_allocator(internal::concurrent_vector_base_v3 &vb, size_t k) { 00833 return static_cast<concurrent_vector<T, A>&>(vb).my_allocator.allocate(k); 00834 } 00836 void internal_free_segments(void *table[], segment_index_t k, segment_index_t first_block); 00837 00839 T& internal_subscript( size_type index ) const; 00840 00842 T& internal_subscript_with_exceptions( size_type index ) const; 00843 00845 void internal_assign_n(size_type n, const_pointer p) { 00846 internal_resize( n, sizeof(T), max_size(), static_cast<const void*>(p), &destroy_array, p? &initialize_array_by : &initialize_array ); 00847 } 00848 00850 template<bool B> class is_integer_tag; 00851 00853 template<class I> 00854 void internal_assign_range(I first, I last, is_integer_tag<true> *) { 00855 internal_assign_n(static_cast<size_type>(first), &static_cast<T&>(last)); 00856 } 00858 template<class I> 00859 void internal_assign_range(I first, I last, is_integer_tag<false> *) { 00860 internal_assign_iterators(first, last); 00861 } 00863 template<class I> 00864 void internal_assign_iterators(I first, I last); 00865 00867 static void __TBB_EXPORTED_FUNC initialize_array( void* begin, const void*, size_type n ); 00868 00870 static void __TBB_EXPORTED_FUNC initialize_array_by( void* begin, const void* src, size_type n ); 00871 00873 static void __TBB_EXPORTED_FUNC copy_array( void* dst, const void* src, size_type n ); 00874 00876 static void __TBB_EXPORTED_FUNC assign_array( void* dst, const void* src, size_type n ); 00877 00879 static void __TBB_EXPORTED_FUNC destroy_array( void* begin, size_type n ); 00880 00882 class internal_loop_guide : internal::no_copy { 00883 public: 00884 const pointer array; 00885 const size_type n; 00886 size_type i; 00887 internal_loop_guide(size_type ntrials, void *ptr) 00888 : array(static_cast<pointer>(ptr)), n(ntrials), i(0) {} 00889 void init() { for(; i < n; ++i) new( &array[i] ) T(); } 00890 void init(const void *src) { for(; i < n; ++i) new( &array[i] ) T(*static_cast<const T*>(src)); } 00891 void copy(const void *src) { for(; i < n; ++i) new( &array[i] ) T(static_cast<const T*>(src)[i]); } 00892 void assign(const void *src) { for(; i < n; ++i) array[i] = static_cast<const T*>(src)[i]; } 00893 template<class I> void iterate(I &src) { for(; i < n; ++i, ++src) new( &array[i] ) T( *src ); } 00894 ~internal_loop_guide() { 00895 if(i < n) // if exception raised, do zerroing on the rest of items 00896 std::memset(array+i, 0, (n-i)*sizeof(value_type)); 00897 } 00898 }; 00899 }; 00900 00901 template<typename T, class A> 00902 void concurrent_vector<T, A>::shrink_to_fit() { 00903 internal_segments_table old; 00904 __TBB_TRY { 00905 if( internal_compact( sizeof(T), &old, &destroy_array, ©_array ) ) 00906 internal_free_segments( old.table, pointers_per_long_table, old.first_block ); // free joined and unnecessary segments 00907 } __TBB_CATCH(...) { 00908 if( old.first_block ) // free segment allocated for compacting. Only for support of exceptions in ctor of user T[ype] 00909 internal_free_segments( old.table, 1, old.first_block ); 00910 __TBB_RETHROW(); 00911 } 00912 } 00913 00914 template<typename T, class A> 00915 void concurrent_vector<T, A>::internal_free_segments(void *table[], segment_index_t k, segment_index_t first_block) { 00916 // Free the arrays 00917 while( k > first_block ) { 00918 --k; 00919 T* array = static_cast<T*>(table[k]); 00920 table[k] = NULL; 00921 if( array > internal::vector_allocation_error_flag ) // check for correct segment pointer 00922 this->my_allocator.deallocate( array, segment_size(k) ); 00923 } 00924 T* array = static_cast<T*>(table[0]); 00925 if( array > internal::vector_allocation_error_flag ) { 00926 __TBB_ASSERT( first_block > 0, NULL ); 00927 while(k > 0) table[--k] = NULL; 00928 this->my_allocator.deallocate( array, segment_size(first_block) ); 00929 } 00930 } 00931 00932 template<typename T, class A> 00933 T& concurrent_vector<T, A>::internal_subscript( size_type index ) const { 00934 __TBB_ASSERT( index < my_early_size, "index out of bounds" ); 00935 size_type j = index; 00936 segment_index_t k = segment_base_index_of( j ); 00937 __TBB_ASSERT( (segment_t*)my_segment != my_storage || k < pointers_per_short_table, "index is being allocated" ); 00938 // no need in __TBB_load_with_acquire since thread works in own space or gets 00939 #if TBB_USE_THREADING_TOOLS 00940 T* array = static_cast<T*>( tbb::internal::itt_load_pointer_v3(&my_segment[k].array)); 00941 #else 00942 T* array = static_cast<T*>(my_segment[k].array); 00943 #endif /* TBB_USE_THREADING_TOOLS */ 00944 __TBB_ASSERT( array != internal::vector_allocation_error_flag, "the instance is broken by bad allocation. Use at() instead" ); 00945 __TBB_ASSERT( array, "index is being allocated" ); 00946 return array[j]; 00947 } 00948 00949 template<typename T, class A> 00950 T& concurrent_vector<T, A>::internal_subscript_with_exceptions( size_type index ) const { 00951 if( index >= my_early_size ) 00952 internal::throw_exception(internal::eid_out_of_range); // throw std::out_of_range 00953 size_type j = index; 00954 segment_index_t k = segment_base_index_of( j ); 00955 if( (segment_t*)my_segment == my_storage && k >= pointers_per_short_table ) 00956 internal::throw_exception(internal::eid_segment_range_error); // throw std::range_error 00957 void *array = my_segment[k].array; // no need in __TBB_load_with_acquire 00958 if( array <= internal::vector_allocation_error_flag ) // check for correct segment pointer 00959 internal::throw_exception(internal::eid_index_range_error); // throw std::range_error 00960 return static_cast<T*>(array)[j]; 00961 } 00962 00963 template<typename T, class A> template<class I> 00964 void concurrent_vector<T, A>::internal_assign_iterators(I first, I last) { 00965 __TBB_ASSERT(my_early_size == 0, NULL); 00966 size_type n = std::distance(first, last); 00967 if( !n ) return; 00968 internal_reserve(n, sizeof(T), max_size()); 00969 my_early_size = n; 00970 segment_index_t k = 0; 00971 size_type sz = segment_size( my_first_block ); 00972 while( sz < n ) { 00973 internal_loop_guide loop(sz, my_segment[k].array); 00974 loop.iterate(first); 00975 n -= sz; 00976 if( !k ) k = my_first_block; 00977 else { ++k; sz <<= 1; } 00978 } 00979 internal_loop_guide loop(n, my_segment[k].array); 00980 loop.iterate(first); 00981 } 00982 00983 template<typename T, class A> 00984 void concurrent_vector<T, A>::initialize_array( void* begin, const void *, size_type n ) { 00985 internal_loop_guide loop(n, begin); loop.init(); 00986 } 00987 00988 template<typename T, class A> 00989 void concurrent_vector<T, A>::initialize_array_by( void* begin, const void *src, size_type n ) { 00990 internal_loop_guide loop(n, begin); loop.init(src); 00991 } 00992 00993 template<typename T, class A> 00994 void concurrent_vector<T, A>::copy_array( void* dst, const void* src, size_type n ) { 00995 internal_loop_guide loop(n, dst); loop.copy(src); 00996 } 00997 00998 template<typename T, class A> 00999 void concurrent_vector<T, A>::assign_array( void* dst, const void* src, size_type n ) { 01000 internal_loop_guide loop(n, dst); loop.assign(src); 01001 } 01002 01003 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) 01004 // Workaround for overzealous compiler warning 01005 #pragma warning (push) 01006 #pragma warning (disable: 4189) 01007 #endif 01008 template<typename T, class A> 01009 void concurrent_vector<T, A>::destroy_array( void* begin, size_type n ) { 01010 T* array = static_cast<T*>(begin); 01011 for( size_type j=n; j>0; --j ) 01012 array[j-1].~T(); // destructors are supposed to not throw any exceptions 01013 } 01014 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) 01015 #pragma warning (pop) 01016 #endif // warning 4189 is back 01017 01018 // concurrent_vector's template functions 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 // Simply: return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); 01022 if(a.size() != b.size()) return false; 01023 typename concurrent_vector<T, A1>::const_iterator i(a.begin()); 01024 typename concurrent_vector<T, A2>::const_iterator j(b.begin()); 01025 for(; i != a.end(); ++i, ++j) 01026 if( !(*i == *j) ) return false; 01027 return true; 01028 } 01029 01030 template<typename T, class A1, class A2> 01031 inline bool operator!=(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b) 01032 { return !(a == b); } 01033 01034 template<typename T, class A1, class A2> 01035 inline bool operator<(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b) 01036 { return (std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end())); } 01037 01038 template<typename T, class A1, class A2> 01039 inline bool operator>(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b) 01040 { return b < a; } 01041 01042 template<typename T, class A1, class A2> 01043 inline bool operator<=(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b) 01044 { return !(b < a); } 01045 01046 template<typename T, class A1, class A2> 01047 inline bool operator>=(const concurrent_vector<T, A1> &a, const concurrent_vector<T, A2> &b) 01048 { return !(a < b); } 01049 01050 template<typename T, class A> 01051 inline void swap(concurrent_vector<T, A> &a, concurrent_vector<T, A> &b) 01052 { a.swap( b ); } 01053 01054 } // namespace tbb 01055 01056 #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_Wp64) 01057 #pragma warning (pop) 01058 #endif // warning 4267 is back 01059 01060 #endif /* __TBB_concurrent_vector_H */
Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.