Shadowrun: Awakened 29 September 2011 - Build 871
concurrent_queue.h
Go to the documentation of this file.
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_queue_H
00030 #define __TBB_concurrent_queue_H
00031 
00032 #include "_concurrent_queue_internal.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     /*overide*/ 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             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         assign( src );
00102     }
00103     
00105     ~concurrent_queue();
00106 
00108     void push( const T& source ) {
00109         internal_push( &source );
00110     }
00111 
00113 
00115     bool try_pop( T& result ) {
00116         return 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     /*overide*/ 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*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 
00273 
00275     bool try_push( const T& source ) {
00276         return internal_push_if_not_full( &source );
00277     }
00278 
00280 
00282     bool try_pop( T& destination ) {
00283         return internal_pop_if_present( &destination );
00284     }
00285 
00287 
00290     size_type size() const {return internal_size();}
00291 
00293     bool empty() const {return internal_empty();}
00294 
00296     size_type capacity() const {
00297         return my_capacity;
00298     }
00299 
00301 
00303     void set_capacity( size_type new_capacity ) {
00304         internal_set_capacity( new_capacity, sizeof(T) );
00305     }
00306 
00308     allocator_type get_allocator() const { return this->my_allocator; }
00309 
00311     void clear() ;
00312 
00313     typedef internal::concurrent_queue_iterator<concurrent_bounded_queue,T> iterator;
00314     typedef internal::concurrent_queue_iterator<concurrent_bounded_queue,const T> const_iterator;
00315 
00316     //------------------------------------------------------------------------
00317     // The iterators are intended only for debugging.  They are slow and not thread safe.
00318     //------------------------------------------------------------------------
00319     iterator unsafe_begin() {return iterator(*this);}
00320     iterator unsafe_end() {return iterator();}
00321     const_iterator unsafe_begin() const {return const_iterator(*this);}
00322     const_iterator unsafe_end() const {return const_iterator();}
00323 
00324 }; 
00325 
00326 template<typename T, class A>
00327 concurrent_bounded_queue<T,A>::~concurrent_bounded_queue() {
00328     clear();
00329     internal_finish_clear();
00330 }
00331 
00332 template<typename T, class A>
00333 void concurrent_bounded_queue<T,A>::clear() {
00334     while( !empty() ) {
00335         T value;
00336         internal_pop_if_present(&value);
00337     }
00338 }
00339 
00340 namespace deprecated {
00341 
00343 
00348 template<typename T, class A = cache_aligned_allocator<T> > 
00349 class concurrent_queue: public concurrent_bounded_queue<T,A> {
00350 #if !__TBB_TEMPLATE_FRIENDS_BROKEN
00351     template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
00352 #endif 
00353 
00354 public:
00356     explicit concurrent_queue(const A& a = A()) : 
00357         concurrent_bounded_queue<T,A>( a )
00358     {
00359     }
00360 
00362     concurrent_queue( const concurrent_queue& src, const A& a = A()) : 
00363         concurrent_bounded_queue<T,A>( src, a )
00364     {
00365     }
00366 
00368     template<typename InputIterator>
00369     concurrent_queue( InputIterator b /*begin*/, InputIterator e /*end*/, const A& a = A()) :
00370         concurrent_bounded_queue<T,A>( b, e, a )
00371     {
00372     }
00373 
00375 
00377     bool push_if_not_full( const T& source ) {
00378         return try_push( source );
00379     }
00380 
00382 
00386     bool pop_if_present( T& destination ) {
00387         return try_pop( destination );
00388     }
00389 
00390     typedef typename concurrent_bounded_queue<T,A>::iterator iterator;
00391     typedef typename concurrent_bounded_queue<T,A>::const_iterator const_iterator;
00392     //
00393     //------------------------------------------------------------------------
00394     // The iterators are intended only for debugging.  They are slow and not thread safe.
00395     //------------------------------------------------------------------------
00396     iterator begin() {return this->unsafe_begin();}
00397     iterator end() {return this->unsafe_end();}
00398     const_iterator begin() const {return this->unsafe_begin();}
00399     const_iterator end() const {return this->unsafe_end();}
00400 }; 
00401 
00402 }
00403     
00404 
00405 #if TBB_DEPRECATED
00406 using deprecated::concurrent_queue;
00407 #else
00408 using strict_ppl::concurrent_queue;    
00409 #endif
00410 
00411 } // namespace tbb
00412 
00413 #endif /* __TBB_concurrent_queue_H */

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net