concurrent_vector.h Source File

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# concurrent_vector.h

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

Copyright © 2005-2010 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.