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

- File List
- File Members

# concurrent_queue.h

    00001 /*
    00002     Copyright 2005-2012 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_queue_H
    00030 #define __TBB_concurrent_queue_H
    00031
    00032 #include "internal/_concurrent_queue_impl.h"
    00033
    00034 namespace tbb {
    00035
    00036 namespace strict_ppl {
    00037
    00039
    00042 template<typename T, typename A = cache_aligned_allocator<T> >
    00043 class concurrent_queue: public internal::concurrent_queue_base_v3<T> {
    00044     template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
    00045
    00047     typedef typename A::template rebind<char>::other page_allocator_type;
    00048     page_allocator_type my_allocator;
    00049
    00051     /*override*/ virtual void *allocate_block( size_t n ) {
    00052         void *b = reinterpret_cast<void*>(my_allocator.allocate( n ));
    00053         if( !b )
    00054             internal::throw_exception(internal::eid_bad_alloc);
    00055         return b;
    00056     }
    00057
    00059     /*override*/ virtual void deallocate_block( void *b, size_t n ) {
    00060         my_allocator.deallocate( reinterpret_cast<char*>(b), n );
    00061     }
    00062
    00063 public:
    00065     typedef T value_type;
    00066
    00068     typedef T& reference;
    00069
    00071     typedef const T& const_reference;
    00072
    00074     typedef size_t size_type;
    00075
    00077     typedef ptrdiff_t difference_type;
    00078
    00080     typedef A allocator_type;
    00081
    00083     explicit concurrent_queue(const allocator_type& a = allocator_type()) :
    00084         my_allocator( a )
    00085     {
    00086     }
    00087
    00089     template<typename InputIterator>
    00090     concurrent_queue( InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()) :
    00091         my_allocator( a )
    00092     {
    00093         for( ; begin != end; ++begin )
    00094             this->internal_push(&*begin);
    00095     }
    00096
    00098     concurrent_queue( const concurrent_queue& src, const allocator_type& a = allocator_type()) :
    00099         internal::concurrent_queue_base_v3<T>(), my_allocator( a )
    00100     {
    00101         this->assign( src );
    00102     }
    00103
    00105     ~concurrent_queue();
    00106
    00108     void push( const T& source ) {
    00109         this->internal_push( &source );
    00110     }
    00111
    00113
    00115     bool try_pop( T& result ) {
    00116         return this->internal_try_pop( &result );
    00117     }
    00118
    00120     size_type unsafe_size() const {return this->internal_size();}
    00121
    00123     bool empty() const {return this->internal_empty();}
    00124
    00126     void clear() ;
    00127
    00129     allocator_type get_allocator() const { return this->my_allocator; }
    00130
    00131     typedef internal::concurrent_queue_iterator<concurrent_queue,T> iterator;
    00132     typedef internal::concurrent_queue_iterator<concurrent_queue,const T> const_iterator;
    00133
    00134     //------------------------------------------------------------------------
    00135     // The iterators are intended only for debugging.  They are slow and not thread safe.
    00136     //------------------------------------------------------------------------
    00137     iterator unsafe_begin() {return iterator(*this);}
    00138     iterator unsafe_end() {return iterator();}
    00139     const_iterator unsafe_begin() const {return const_iterator(*this);}
    00140     const_iterator unsafe_end() const {return const_iterator();}
    00141 } ;
    00142
    00143 template<typename T, class A>
    00144 concurrent_queue<T,A>::~concurrent_queue() {
    00145     clear();
    00146     this->internal_finish_clear();
    00147 }
    00148
    00149 template<typename T, class A>
    00150 void concurrent_queue<T,A>::clear() {
    00151     while( !empty() ) {
    00152         T value;
    00153         this->internal_try_pop(&value);
    00154     }
    00155 }
    00156
    00157 } // namespace strict_ppl
    00158
    00160
    00165 template<typename T, class A = cache_aligned_allocator<T> >
    00166 class concurrent_bounded_queue: public internal::concurrent_queue_base_v3 {
    00167     template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
    00168
    00170     typedef typename A::template rebind<char>::other page_allocator_type;
    00171     page_allocator_type my_allocator;
    00172
    00173     typedef typename concurrent_queue_base_v3::padded_page<T> padded_page;
    00174
    00176     class destroyer: internal::no_copy {
    00177         T& my_value;
    00178     public:
    00179         destroyer( T& value ) : my_value(value) {}
    00180         ~destroyer() {my_value.~T();}
    00181     };
    00182
    00183     T& get_ref( page& p, size_t index ) {
    00184         __TBB_ASSERT( index<items_per_page, NULL );
    00185         return (&static_cast<padded_page*>(static_cast<void*>(&p))->last)[index];
    00186     }
    00187
    00188     /*override*/ virtual void copy_item( page& dst, size_t index, const void* src ) {
    00189         new( &get_ref(dst,index) ) T(*static_cast<const T*>(src));
    00190     }
    00191
    00192     /*override*/ virtual void copy_page_item( page& dst, size_t dindex, const page& src, size_t sindex ) {
    00193         new( &get_ref(dst,dindex) ) T( get_ref( const_cast<page&>(src), sindex ) );
    00194     }
    00195
    00196     /*override*/ virtual void assign_and_destroy_item( void* dst, page& src, size_t index ) {
    00197         T& from = get_ref(src,index);
    00198         destroyer d(from);
    00199         *static_cast<T*>(dst) = from;
    00200     }
    00201
    00202     /*override*/ virtual page *allocate_page() {
    00203         size_t n = sizeof(padded_page) + (items_per_page-1)*sizeof(T);
    00204         page *p = reinterpret_cast<page*>(my_allocator.allocate( n ));
    00205         if( !p )
    00206             internal::throw_exception(internal::eid_bad_alloc);
    00207         return p;
    00208     }
    00209
    00210     /*override*/ virtual void deallocate_page( page *p ) {
    00211         size_t n = sizeof(padded_page) + (items_per_page-1)*sizeof(T);
    00212         my_allocator.deallocate( reinterpret_cast<char*>(p), n );
    00213     }
    00214
    00215 public:
    00217     typedef T value_type;
    00218
    00220     typedef A allocator_type;
    00221
    00223     typedef T& reference;
    00224
    00226     typedef const T& const_reference;
    00227
    00229
    00231     typedef std::ptrdiff_t size_type;
    00232
    00234     typedef std::ptrdiff_t difference_type;
    00235
    00237     explicit concurrent_bounded_queue(const allocator_type& a = allocator_type()) :
    00238         concurrent_queue_base_v3( sizeof(T) ), my_allocator( a )
    00239     {
    00240     }
    00241
    00243     concurrent_bounded_queue( const concurrent_bounded_queue& src, const allocator_type& a = allocator_type()) :
    00244         concurrent_queue_base_v3( sizeof(T) ), my_allocator( a )
    00245     {
    00246         assign( src );
    00247     }
    00248
    00250     template<typename InputIterator>
    00251     concurrent_bounded_queue( InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()) :
    00252         concurrent_queue_base_v3( sizeof(T) ), my_allocator( a )
    00253     {
    00254         for( ; begin != end; ++begin )
    00255             internal_push_if_not_full(&*begin);
    00256     }
    00257
    00259     ~concurrent_bounded_queue();
    00260
    00262     void push( const T& source ) {
    00263         internal_push( &source );
    00264     }
    00265
    00267
    00268     void pop( T& destination ) {
    00269         internal_pop( &destination );
    00270     }
    00271
    00272 #if TBB_USE_EXCEPTIONS
    00274     void abort() {
    00275         internal_abort();
    00276     }
    00277 #endif
    00278
    00280
    00282     bool try_push( const T& source ) {
    00283         return internal_push_if_not_full( &source );
    00284     }
    00285
    00287
    00289     bool try_pop( T& destination ) {
    00290         return internal_pop_if_present( &destination );
    00291     }
    00292
    00294
    00297     size_type size() const {return internal_size();}
    00298
    00300     bool empty() const {return internal_empty();}
    00301
    00303     size_type capacity() const {
    00304         return my_capacity;
    00305     }
    00306
    00308
    00310     void set_capacity( size_type new_capacity ) {
    00311         internal_set_capacity( new_capacity, sizeof(T) );
    00312     }
    00313
    00315     allocator_type get_allocator() const { return this->my_allocator; }
    00316
    00318     void clear() ;
    00319
    00320     typedef internal::concurrent_queue_iterator<concurrent_bounded_queue,T> iterator;
    00321     typedef internal::concurrent_queue_iterator<concurrent_bounded_queue,const T> const_iterator;
    00322
    00323     //------------------------------------------------------------------------
    00324     // The iterators are intended only for debugging.  They are slow and not thread safe.
    00325     //------------------------------------------------------------------------
    00326     iterator unsafe_begin() {return iterator(*this);}
    00327     iterator unsafe_end() {return iterator();}
    00328     const_iterator unsafe_begin() const {return const_iterator(*this);}
    00329     const_iterator unsafe_end() const {return const_iterator();}
    00330
    00331 };
    00332
    00333 template<typename T, class A>
    00334 concurrent_bounded_queue<T,A>::~concurrent_bounded_queue() {
    00335     clear();
    00336     internal_finish_clear();
    00337 }
    00338
    00339 template<typename T, class A>
    00340 void concurrent_bounded_queue<T,A>::clear() {
    00341     while( !empty() ) {
    00342         T value;
    00343         internal_pop_if_present(&value);
    00344     }
    00345 }
    00346
    00347 namespace deprecated {
    00348
    00350
    00355 template<typename T, class A = cache_aligned_allocator<T> >
    00356 class concurrent_queue: public concurrent_bounded_queue<T,A> {
    00357 #if !__TBB_TEMPLATE_FRIENDS_BROKEN
    00358     template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
    00359 #endif
    00360
    00361 public:
    00363     explicit concurrent_queue(const A& a = A()) :
    00364         concurrent_bounded_queue<T,A>( a )
    00365     {
    00366     }
    00367
    00369     concurrent_queue( const concurrent_queue& src, const A& a = A()) :
    00370         concurrent_bounded_queue<T,A>( src, a )
    00371     {
    00372     }
    00373
    00375     template<typename InputIterator>
    00376     concurrent_queue( InputIterator b /*begin*/, InputIterator e /*end*/, const A& a = A()) :
    00377         concurrent_bounded_queue<T,A>( b, e, a )
    00378     {
    00379     }
    00380
    00382
    00384     bool push_if_not_full( const T& source ) {
    00385         return this->try_push( source );
    00386     }
    00387
    00389
    00393     bool pop_if_present( T& destination ) {
    00394         return this->try_pop( destination );
    00395     }
    00396
    00397     typedef typename concurrent_bounded_queue<T,A>::iterator iterator;
    00398     typedef typename concurrent_bounded_queue<T,A>::const_iterator const_iterator;
    00399     //
    00400     //------------------------------------------------------------------------
    00401     // The iterators are intended only for debugging.  They are slow and not thread safe.
    00402     //------------------------------------------------------------------------
    00403     iterator begin() {return this->unsafe_begin();}
    00404     iterator end() {return this->unsafe_end();}
    00405     const_iterator begin() const {return this->unsafe_begin();}
    00406     const_iterator end() const {return this->unsafe_end();}
    00407 };
    00408
    00409 }
    00410
    00411
    00412 #if TBB_DEPRECATED
    00413 using deprecated::concurrent_queue;
    00414 #else
    00415 using strict_ppl::concurrent_queue;
    00416 #endif
    00417
    00418 } // namespace tbb
    00419
    00420 #endif /* __TBB_concurrent_queue_H */

Copyright © 2005-2012 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.