File indexing completed on 2025-01-18 10:12:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef __TBB_concurrent_queue_H
0018 #define __TBB_concurrent_queue_H
0019
0020 #define __TBB_concurrent_queue_H_include_area
0021 #include "internal/_warning_suppress_enable_notice.h"
0022
0023 #include "internal/_concurrent_queue_impl.h"
0024 #include "internal/_allocator_traits.h"
0025
0026 namespace tbb {
0027
0028 namespace strict_ppl {
0029
0030
0031
0032
0033
0034 template<typename T, typename A = cache_aligned_allocator<T> >
0035 class concurrent_queue: public internal::concurrent_queue_base_v3<T> {
0036 template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
0037
0038
0039 typedef typename tbb::internal::allocator_rebind<A, char>::type page_allocator_type;
0040 page_allocator_type my_allocator;
0041
0042
0043 virtual void *allocate_block( size_t n ) __TBB_override {
0044 void *b = reinterpret_cast<void*>(my_allocator.allocate( n ));
0045 if( !b )
0046 internal::throw_exception(internal::eid_bad_alloc);
0047 return b;
0048 }
0049
0050
0051 virtual void deallocate_block( void *b, size_t n ) __TBB_override {
0052 my_allocator.deallocate( reinterpret_cast<char*>(b), n );
0053 }
0054
0055 static void copy_construct_item(T* location, const void* src){
0056 new (location) T(*static_cast<const T*>(src));
0057 }
0058
0059 #if __TBB_CPP11_RVALUE_REF_PRESENT
0060 static void move_construct_item(T* location, const void* src) {
0061 new (location) T( std::move(*static_cast<T*>(const_cast<void*>(src))) );
0062 }
0063 #endif
0064 public:
0065
0066 typedef T value_type;
0067
0068
0069 typedef T& reference;
0070
0071
0072 typedef const T& const_reference;
0073
0074
0075 typedef size_t size_type;
0076
0077
0078 typedef ptrdiff_t difference_type;
0079
0080
0081 typedef A allocator_type;
0082
0083
0084 explicit concurrent_queue(const allocator_type& a = allocator_type()) :
0085 my_allocator( a )
0086 {
0087 }
0088
0089
0090 template<typename InputIterator>
0091 concurrent_queue( InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()) :
0092 my_allocator( a )
0093 {
0094 for( ; begin != end; ++begin )
0095 this->push(*begin);
0096 }
0097
0098
0099 concurrent_queue( const concurrent_queue& src, const allocator_type& a = allocator_type()) :
0100 internal::concurrent_queue_base_v3<T>(), my_allocator( a )
0101 {
0102 this->assign( src, copy_construct_item );
0103 }
0104
0105 #if __TBB_CPP11_RVALUE_REF_PRESENT
0106
0107 concurrent_queue( concurrent_queue&& src ) :
0108 internal::concurrent_queue_base_v3<T>(), my_allocator( std::move(src.my_allocator) )
0109 {
0110 this->internal_swap( src );
0111 }
0112
0113 concurrent_queue( concurrent_queue&& src, const allocator_type& a ) :
0114 internal::concurrent_queue_base_v3<T>(), my_allocator( a )
0115 {
0116
0117
0118 if( my_allocator == src.my_allocator) {
0119 this->internal_swap( src );
0120 } else {
0121
0122 this->assign( src, move_construct_item );
0123 src.clear();
0124 }
0125 }
0126 #endif
0127
0128
0129 ~concurrent_queue();
0130
0131
0132 void push( const T& source ) {
0133 this->internal_push( &source, copy_construct_item );
0134 }
0135
0136 #if __TBB_CPP11_RVALUE_REF_PRESENT
0137 void push( T&& source ) {
0138 this->internal_push( &source, move_construct_item );
0139 }
0140
0141 #if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
0142 template<typename... Arguments>
0143 void emplace( Arguments&&... args ) {
0144 push( T(std::forward<Arguments>( args )...) );
0145 }
0146 #endif
0147 #endif
0148
0149
0150
0151
0152 bool try_pop( T& result ) {
0153 return this->internal_try_pop( &result );
0154 }
0155
0156
0157 size_type unsafe_size() const {return this->internal_size();}
0158
0159
0160 bool empty() const {return this->internal_empty();}
0161
0162
0163 void clear() ;
0164
0165
0166 allocator_type get_allocator() const { return this->my_allocator; }
0167
0168 typedef internal::concurrent_queue_iterator<concurrent_queue,T> iterator;
0169 typedef internal::concurrent_queue_iterator<concurrent_queue,const T> const_iterator;
0170
0171
0172
0173
0174 iterator unsafe_begin() {return iterator(*this);}
0175 iterator unsafe_end() {return iterator();}
0176 const_iterator unsafe_begin() const {return const_iterator(*this);}
0177 const_iterator unsafe_end() const {return const_iterator();}
0178 } ;
0179
0180 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
0181
0182 template<typename InputIterator,
0183 typename T = typename std::iterator_traits<InputIterator>::value_type,
0184 typename A = cache_aligned_allocator<T>
0185 > concurrent_queue(InputIterator, InputIterator, const A& = A())
0186 -> concurrent_queue<T, A>;
0187 #endif
0188
0189 template<typename T, class A>
0190 concurrent_queue<T,A>::~concurrent_queue() {
0191 clear();
0192 this->internal_finish_clear();
0193 }
0194
0195 template<typename T, class A>
0196 void concurrent_queue<T,A>::clear() {
0197 T value;
0198 while( !empty() ) try_pop(value);
0199 }
0200
0201 }
0202
0203
0204
0205
0206
0207
0208
0209 template<typename T, class A = cache_aligned_allocator<T> >
0210 class concurrent_bounded_queue: public internal::concurrent_queue_base_v8 {
0211 template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
0212 typedef typename tbb::internal::allocator_rebind<A, char>::type page_allocator_type;
0213
0214
0215 page_allocator_type my_allocator;
0216
0217 typedef typename concurrent_queue_base_v3::padded_page<T> padded_page;
0218 typedef typename concurrent_queue_base_v3::copy_specifics copy_specifics;
0219
0220
0221 class destroyer: internal::no_copy {
0222 T& my_value;
0223 public:
0224 destroyer( T& value ) : my_value(value) {}
0225 ~destroyer() {my_value.~T();}
0226 };
0227
0228 T& get_ref( page& p, size_t index ) {
0229 __TBB_ASSERT( index<items_per_page, NULL );
0230 return (&static_cast<padded_page*>(static_cast<void*>(&p))->last)[index];
0231 }
0232
0233 virtual void copy_item( page& dst, size_t index, const void* src ) __TBB_override {
0234 new( &get_ref(dst,index) ) T(*static_cast<const T*>(src));
0235 }
0236
0237 #if __TBB_CPP11_RVALUE_REF_PRESENT
0238 virtual void move_item( page& dst, size_t index, const void* src ) __TBB_override {
0239 new( &get_ref(dst,index) ) T( std::move(*static_cast<T*>(const_cast<void*>(src))) );
0240 }
0241 #else
0242 virtual void move_item( page&, size_t, const void* ) __TBB_override {
0243 __TBB_ASSERT( false, "Unreachable code" );
0244 }
0245 #endif
0246
0247 virtual void copy_page_item( page& dst, size_t dindex, const page& src, size_t sindex ) __TBB_override {
0248 new( &get_ref(dst,dindex) ) T( get_ref( const_cast<page&>(src), sindex ) );
0249 }
0250
0251 #if __TBB_CPP11_RVALUE_REF_PRESENT
0252 virtual void move_page_item( page& dst, size_t dindex, const page& src, size_t sindex ) __TBB_override {
0253 new( &get_ref(dst,dindex) ) T( std::move(get_ref( const_cast<page&>(src), sindex )) );
0254 }
0255 #else
0256 virtual void move_page_item( page&, size_t, const page&, size_t ) __TBB_override {
0257 __TBB_ASSERT( false, "Unreachable code" );
0258 }
0259 #endif
0260
0261 virtual void assign_and_destroy_item( void* dst, page& src, size_t index ) __TBB_override {
0262 T& from = get_ref(src,index);
0263 destroyer d(from);
0264 *static_cast<T*>(dst) = tbb::internal::move( from );
0265 }
0266
0267 virtual page *allocate_page() __TBB_override {
0268 size_t n = sizeof(padded_page) + (items_per_page-1)*sizeof(T);
0269 page *p = reinterpret_cast<page*>(my_allocator.allocate( n ));
0270 if( !p )
0271 internal::throw_exception(internal::eid_bad_alloc);
0272 return p;
0273 }
0274
0275 virtual void deallocate_page( page *p ) __TBB_override {
0276 size_t n = sizeof(padded_page) + (items_per_page-1)*sizeof(T);
0277 my_allocator.deallocate( reinterpret_cast<char*>(p), n );
0278 }
0279
0280 public:
0281
0282 typedef T value_type;
0283
0284
0285 typedef A allocator_type;
0286
0287
0288 typedef T& reference;
0289
0290
0291 typedef const T& const_reference;
0292
0293
0294
0295
0296 typedef std::ptrdiff_t size_type;
0297
0298
0299 typedef std::ptrdiff_t difference_type;
0300
0301
0302 explicit concurrent_bounded_queue(const allocator_type& a = allocator_type()) :
0303 concurrent_queue_base_v8( sizeof(T) ), my_allocator( a )
0304 {
0305 }
0306
0307
0308 concurrent_bounded_queue( const concurrent_bounded_queue& src, const allocator_type& a = allocator_type())
0309 : concurrent_queue_base_v8( sizeof(T) ), my_allocator( a )
0310 {
0311 assign( src );
0312 }
0313
0314 #if __TBB_CPP11_RVALUE_REF_PRESENT
0315
0316 concurrent_bounded_queue( concurrent_bounded_queue&& src )
0317 : concurrent_queue_base_v8( sizeof(T) ), my_allocator( std::move(src.my_allocator) )
0318 {
0319 internal_swap( src );
0320 }
0321
0322 concurrent_bounded_queue( concurrent_bounded_queue&& src, const allocator_type& a )
0323 : concurrent_queue_base_v8( sizeof(T) ), my_allocator( a )
0324 {
0325
0326
0327 if( my_allocator == src.my_allocator) {
0328 this->internal_swap( src );
0329 } else {
0330
0331 this->move_content( src );
0332 src.clear();
0333 }
0334 }
0335 #endif
0336
0337
0338 template<typename InputIterator>
0339 concurrent_bounded_queue( InputIterator begin, InputIterator end,
0340 const allocator_type& a = allocator_type())
0341 : concurrent_queue_base_v8( sizeof(T) ), my_allocator( a )
0342 {
0343 for( ; begin != end; ++begin )
0344 internal_push_if_not_full(&*begin);
0345 }
0346
0347
0348 ~concurrent_bounded_queue();
0349
0350
0351 void push( const T& source ) {
0352 internal_push( &source );
0353 }
0354
0355 #if __TBB_CPP11_RVALUE_REF_PRESENT
0356
0357 void push( T&& source ) {
0358 internal_push_move( &source );
0359 }
0360
0361 #if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
0362 template<typename... Arguments>
0363 void emplace( Arguments&&... args ) {
0364 push( T(std::forward<Arguments>( args )...) );
0365 }
0366 #endif
0367 #endif
0368
0369
0370
0371 void pop( T& destination ) {
0372 internal_pop( &destination );
0373 }
0374
0375 #if TBB_USE_EXCEPTIONS
0376
0377 void abort() {
0378 internal_abort();
0379 }
0380 #endif
0381
0382
0383
0384
0385 bool try_push( const T& source ) {
0386 return internal_push_if_not_full( &source );
0387 }
0388
0389 #if __TBB_CPP11_RVALUE_REF_PRESENT
0390
0391
0392
0393 bool try_push( T&& source ) {
0394 return internal_push_move_if_not_full( &source );
0395 }
0396 #if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
0397 template<typename... Arguments>
0398 bool try_emplace( Arguments&&... args ) {
0399 return try_push( T(std::forward<Arguments>( args )...) );
0400 }
0401 #endif
0402 #endif
0403
0404
0405
0406
0407 bool try_pop( T& destination ) {
0408 return internal_pop_if_present( &destination );
0409 }
0410
0411
0412
0413
0414
0415 size_type size() const {return internal_size();}
0416
0417
0418 bool empty() const {return internal_empty();}
0419
0420
0421 size_type capacity() const {
0422 return my_capacity;
0423 }
0424
0425
0426
0427
0428 void set_capacity( size_type new_capacity ) {
0429 internal_set_capacity( new_capacity, sizeof(T) );
0430 }
0431
0432
0433 allocator_type get_allocator() const { return this->my_allocator; }
0434
0435
0436 void clear() ;
0437
0438 typedef internal::concurrent_queue_iterator<concurrent_bounded_queue,T> iterator;
0439 typedef internal::concurrent_queue_iterator<concurrent_bounded_queue,const T> const_iterator;
0440
0441
0442
0443
0444 iterator unsafe_begin() {return iterator(*this);}
0445 iterator unsafe_end() {return iterator();}
0446 const_iterator unsafe_begin() const {return const_iterator(*this);}
0447 const_iterator unsafe_end() const {return const_iterator();}
0448
0449 };
0450
0451 #if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
0452
0453 template<typename InputIterator,
0454 typename T = typename std::iterator_traits<InputIterator>::value_type,
0455 typename A = cache_aligned_allocator<T>
0456 > concurrent_bounded_queue(InputIterator, InputIterator, const A& = A())
0457 -> concurrent_bounded_queue<T, A>;
0458 #endif
0459
0460 template<typename T, class A>
0461 concurrent_bounded_queue<T,A>::~concurrent_bounded_queue() {
0462 clear();
0463 internal_finish_clear();
0464 }
0465
0466 template<typename T, class A>
0467 void concurrent_bounded_queue<T,A>::clear() {
0468 T value;
0469 while( try_pop(value) ) ;
0470 }
0471
0472 using strict_ppl::concurrent_queue;
0473
0474 }
0475
0476 #include "internal/_warning_suppress_disable_notice.h"
0477 #undef __TBB_concurrent_queue_H_include_area
0478
0479 #endif