concurrent_queue.h

00001 /*
00002     Copyright 2005-2011 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_queue_H
00022 #define __TBB_concurrent_queue_H
00023 
00024 #include "internal/_concurrent_queue_impl.h"
00025 
00026 namespace tbb {
00027 
00028 namespace strict_ppl {
00029 
00031 
00034 template<typename T, typename A = cache_aligned_allocator<T> > 
00035 class concurrent_queue: public internal::concurrent_queue_base_v3<T> {
00036     template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
00037 
00039     typedef typename A::template rebind<char>::other page_allocator_type;
00040     page_allocator_type my_allocator;
00041 
00043     /*override*/ virtual void *allocate_block( size_t n ) {
00044         void *b = reinterpret_cast<void*>(my_allocator.allocate( n ));
00045         if( !b )
00046             internal::throw_exception(internal::eid_bad_alloc); 
00047         return b;
00048     }
00049 
00051     /*override*/ virtual void deallocate_block( void *b, size_t n ) {
00052         my_allocator.deallocate( reinterpret_cast<char*>(b), n );
00053     }
00054 
00055 public:
00057     typedef T value_type;
00058 
00060     typedef T& reference;
00061 
00063     typedef const T& const_reference;
00064 
00066     typedef size_t size_type;
00067 
00069     typedef ptrdiff_t difference_type;
00070 
00072     typedef A allocator_type;
00073 
00075     explicit concurrent_queue(const allocator_type& a = allocator_type()) : 
00076         my_allocator( a )
00077     {
00078     }
00079 
00081     template<typename InputIterator>
00082     concurrent_queue( InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()) :
00083         my_allocator( a )
00084     {
00085         for( ; begin != end; ++begin )
00086             this->internal_push(&*begin);
00087     }
00088     
00090     concurrent_queue( const concurrent_queue& src, const allocator_type& a = allocator_type()) : 
00091         internal::concurrent_queue_base_v3<T>(), my_allocator( a )
00092     {
00093         this->assign( src );
00094     }
00095     
00097     ~concurrent_queue();
00098 
00100     void push( const T& source ) {
00101         this->internal_push( &source );
00102     }
00103 
00105 
00107     bool try_pop( T& result ) {
00108         return this->internal_try_pop( &result );
00109     }
00110 
00112     size_type unsafe_size() const {return this->internal_size();}
00113 
00115     bool empty() const {return this->internal_empty();}
00116 
00118     void clear() ;
00119 
00121     allocator_type get_allocator() const { return this->my_allocator; }
00122 
00123     typedef internal::concurrent_queue_iterator<concurrent_queue,T> iterator;
00124     typedef internal::concurrent_queue_iterator<concurrent_queue,const T> const_iterator;
00125 
00126     //------------------------------------------------------------------------
00127     // The iterators are intended only for debugging.  They are slow and not thread safe.
00128     //------------------------------------------------------------------------
00129     iterator unsafe_begin() {return iterator(*this);}
00130     iterator unsafe_end() {return iterator();}
00131     const_iterator unsafe_begin() const {return const_iterator(*this);}
00132     const_iterator unsafe_end() const {return const_iterator();}
00133 } ;
00134 
00135 template<typename T, class A>
00136 concurrent_queue<T,A>::~concurrent_queue() {
00137     clear();
00138     this->internal_finish_clear();
00139 }
00140 
00141 template<typename T, class A>
00142 void concurrent_queue<T,A>::clear() {
00143     while( !empty() ) {
00144         T value;
00145         this->internal_try_pop(&value);
00146     }
00147 }
00148 
00149 } // namespace strict_ppl
00150     
00152 
00157 template<typename T, class A = cache_aligned_allocator<T> >
00158 class concurrent_bounded_queue: public internal::concurrent_queue_base_v3 {
00159     template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
00160 
00162     typedef typename A::template rebind<char>::other page_allocator_type;
00163     page_allocator_type my_allocator;
00164 
00165     typedef typename concurrent_queue_base_v3::padded_page<T> padded_page;
00166  
00168     class destroyer: internal::no_copy {
00169         T& my_value;
00170     public:
00171         destroyer( T& value ) : my_value(value) {}
00172         ~destroyer() {my_value.~T();}          
00173     };
00174 
00175     T& get_ref( page& p, size_t index ) {
00176         __TBB_ASSERT( index<items_per_page, NULL );
00177         return (&static_cast<padded_page*>(static_cast<void*>(&p))->last)[index];
00178     }
00179 
00180     /*override*/ virtual void copy_item( page& dst, size_t index, const void* src ) {
00181         new( &get_ref(dst,index) ) T(*static_cast<const T*>(src)); 
00182     }
00183 
00184     /*override*/ virtual void copy_page_item( page& dst, size_t dindex, const page& src, size_t sindex ) {
00185         new( &get_ref(dst,dindex) ) T( get_ref( const_cast<page&>(src), sindex ) );
00186     }
00187 
00188     /*override*/ virtual void assign_and_destroy_item( void* dst, page& src, size_t index ) {
00189         T& from = get_ref(src,index);
00190         destroyer d(from);
00191         *static_cast<T*>(dst) = from;
00192     }
00193 
00194     /*override*/ virtual page *allocate_page() {
00195         size_t n = sizeof(padded_page) + (items_per_page-1)*sizeof(T);
00196         page *p = reinterpret_cast<page*>(my_allocator.allocate( n ));
00197         if( !p )
00198             internal::throw_exception(internal::eid_bad_alloc); 
00199         return p;
00200     }
00201 
00202     /*override*/ virtual void deallocate_page( page *p ) {
00203         size_t n = sizeof(padded_page) + (items_per_page-1)*sizeof(T);
00204         my_allocator.deallocate( reinterpret_cast<char*>(p), n );
00205     }
00206 
00207 public:
00209     typedef T value_type;
00210 
00212     typedef A allocator_type;
00213 
00215     typedef T& reference;
00216 
00218     typedef const T& const_reference;
00219 
00221 
00223     typedef std::ptrdiff_t size_type;
00224 
00226     typedef std::ptrdiff_t difference_type;
00227 
00229     explicit concurrent_bounded_queue(const allocator_type& a = allocator_type()) : 
00230         concurrent_queue_base_v3( sizeof(T) ), my_allocator( a )
00231     {
00232     }
00233 
00235     concurrent_bounded_queue( const concurrent_bounded_queue& src, const allocator_type& a = allocator_type()) : 
00236         concurrent_queue_base_v3( sizeof(T) ), my_allocator( a )
00237     {
00238         assign( src );
00239     }
00240 
00242     template<typename InputIterator>
00243     concurrent_bounded_queue( InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()) :
00244         concurrent_queue_base_v3( sizeof(T) ), my_allocator( a )
00245     {
00246         for( ; begin != end; ++begin )
00247             internal_push_if_not_full(&*begin);
00248     }
00249 
00251     ~concurrent_bounded_queue();
00252 
00254     void push( const T& source ) {
00255         internal_push( &source );
00256     }
00257 
00259 
00260     void pop( T& destination ) {
00261         internal_pop( &destination );
00262     }
00263 
00265 
00267     bool try_push( const T& source ) {
00268         return internal_push_if_not_full( &source );
00269     }
00270 
00272 
00274     bool try_pop( T& destination ) {
00275         return internal_pop_if_present( &destination );
00276     }
00277 
00279 
00282     size_type size() const {return internal_size();}
00283 
00285     bool empty() const {return internal_empty();}
00286 
00288     size_type capacity() const {
00289         return my_capacity;
00290     }
00291 
00293 
00295     void set_capacity( size_type new_capacity ) {
00296         internal_set_capacity( new_capacity, sizeof(T) );
00297     }
00298 
00300     allocator_type get_allocator() const { return this->my_allocator; }
00301 
00303     void clear() ;
00304 
00305     typedef internal::concurrent_queue_iterator<concurrent_bounded_queue,T> iterator;
00306     typedef internal::concurrent_queue_iterator<concurrent_bounded_queue,const T> const_iterator;
00307 
00308     //------------------------------------------------------------------------
00309     // The iterators are intended only for debugging.  They are slow and not thread safe.
00310     //------------------------------------------------------------------------
00311     iterator unsafe_begin() {return iterator(*this);}
00312     iterator unsafe_end() {return iterator();}
00313     const_iterator unsafe_begin() const {return const_iterator(*this);}
00314     const_iterator unsafe_end() const {return const_iterator();}
00315 
00316 }; 
00317 
00318 template<typename T, class A>
00319 concurrent_bounded_queue<T,A>::~concurrent_bounded_queue() {
00320     clear();
00321     internal_finish_clear();
00322 }
00323 
00324 template<typename T, class A>
00325 void concurrent_bounded_queue<T,A>::clear() {
00326     while( !empty() ) {
00327         T value;
00328         internal_pop_if_present(&value);
00329     }
00330 }
00331 
00332 namespace deprecated {
00333 
00335 
00340 template<typename T, class A = cache_aligned_allocator<T> > 
00341 class concurrent_queue: public concurrent_bounded_queue<T,A> {
00342 #if !__TBB_TEMPLATE_FRIENDS_BROKEN
00343     template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
00344 #endif 
00345 
00346 public:
00348     explicit concurrent_queue(const A& a = A()) : 
00349         concurrent_bounded_queue<T,A>( a )
00350     {
00351     }
00352 
00354     concurrent_queue( const concurrent_queue& src, const A& a = A()) : 
00355         concurrent_bounded_queue<T,A>( src, a )
00356     {
00357     }
00358 
00360     template<typename InputIterator>
00361     concurrent_queue( InputIterator b /*begin*/, InputIterator e /*end*/, const A& a = A()) :
00362         concurrent_bounded_queue<T,A>( b, e, a )
00363     {
00364     }
00365 
00367 
00369     bool push_if_not_full( const T& source ) {
00370         return this->try_push( source );
00371     }
00372 
00374 
00378     bool pop_if_present( T& destination ) {
00379         return this->try_pop( destination );
00380     }
00381 
00382     typedef typename concurrent_bounded_queue<T,A>::iterator iterator;
00383     typedef typename concurrent_bounded_queue<T,A>::const_iterator const_iterator;
00384     //
00385     //------------------------------------------------------------------------
00386     // The iterators are intended only for debugging.  They are slow and not thread safe.
00387     //------------------------------------------------------------------------
00388     iterator begin() {return this->unsafe_begin();}
00389     iterator end() {return this->unsafe_end();}
00390     const_iterator begin() const {return this->unsafe_begin();}
00391     const_iterator end() const {return this->unsafe_end();}
00392 }; 
00393 
00394 }
00395     
00396 
00397 #if TBB_DEPRECATED
00398 using deprecated::concurrent_queue;
00399 #else
00400 using strict_ppl::concurrent_queue;    
00401 #endif
00402 
00403 } // namespace tbb
00404 
00405 #endif /* __TBB_concurrent_queue_H */

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