Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | Related Pages

concurrent_queue.h

00001 /*
00002     Copyright 2005-2008 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 "tbb_stddef.h"
00025 #include "cache_aligned_allocator.h"
00026 #include "tbb_allocator.h"
00027 #include <new>
00028 
00029 namespace tbb {
00030 
00031 template<typename T, class A = cache_aligned_allocator<T> > 
00032 class concurrent_queue;
00033 
00035 namespace internal {
00036 
00037 class concurrent_queue_rep;
00038 class concurrent_queue_iterator_rep;
00039 class concurrent_queue_iterator_base_v3;
00040 template<typename Container, typename Value> class concurrent_queue_iterator;
00041 
00043 
00045 class concurrent_queue_base_v3: no_copy {
00047     concurrent_queue_rep* my_rep;
00048 
00049     friend class concurrent_queue_rep;
00050     friend struct micro_queue;
00051     friend class micro_queue_pop_finalizer;
00052     friend class concurrent_queue_iterator_rep;
00053     friend class concurrent_queue_iterator_base_v3;
00054 protected:
00056     struct page {
00057         page* next;
00058         uintptr mask; 
00059     };
00060 
00062     ptrdiff_t my_capacity;
00063    
00065     size_t items_per_page;
00066 
00068     size_t item_size;
00069 
00070 private:
00071     virtual void copy_item( page& dst, size_t index, const void* src ) = 0;
00072     virtual void assign_and_destroy_item( void* dst, page& src, size_t index ) = 0;
00073 protected:
00074     concurrent_queue_base_v3( size_t item_size );
00075     virtual ~concurrent_queue_base_v3();
00076 
00078     void internal_push( const void* src );
00079 
00081     void internal_pop( void* dst );
00082 
00084     bool internal_push_if_not_full( const void* src );
00085 
00087 
00088     bool internal_pop_if_present( void* dst );
00089 
00091     ptrdiff_t internal_size() const;
00092 
00094     void internal_set_capacity( ptrdiff_t capacity, size_t element_size );
00095 
00097     virtual page *allocate_page() = 0;
00098 
00100     virtual void deallocate_page( page *p ) = 0;
00101 
00103     void internal_finish_clear() ;
00104 
00106     void internal_throw_exception() const;
00107 };
00108 
00109 typedef concurrent_queue_base_v3 concurrent_queue_base ;
00110 
00112 
00113 class concurrent_queue_iterator_base_v3 {
00115 
00116     concurrent_queue_iterator_rep* my_rep;
00117 
00118     template<typename C, typename T, typename U>
00119     friend bool operator==( const concurrent_queue_iterator<C,T>& i, const concurrent_queue_iterator<C,U>& j );
00120 
00121     template<typename C, typename T, typename U>
00122     friend bool operator!=( const concurrent_queue_iterator<C,T>& i, const concurrent_queue_iterator<C,U>& j );
00123 protected:
00125     mutable void* my_item;
00126 
00128     concurrent_queue_iterator_base_v3() : my_rep(NULL), my_item(NULL) {}
00129 
00131     concurrent_queue_iterator_base_v3( const concurrent_queue_iterator_base_v3& i ) : my_rep(NULL), my_item(NULL) {
00132         assign(i);
00133     }
00134 
00136     concurrent_queue_iterator_base_v3( const concurrent_queue_base& queue );
00137 
00139     void assign( const concurrent_queue_iterator_base_v3& i );
00140 
00142     void advance();
00143 
00145     ~concurrent_queue_iterator_base_v3();
00146 };
00147 
00148 typedef concurrent_queue_iterator_base_v3 concurrent_queue_iterator_base;
00149 
00151 
00153 template<typename Container, typename Value>
00154 class concurrent_queue_iterator: public concurrent_queue_iterator_base_v3 {
00155 #if !defined(_MSC_VER) || defined(__INTEL_COMPILER)
00156     template<typename T, class A>
00157     friend class ::tbb::concurrent_queue;
00158 #else
00159 public: // workaround for MSVC
00160 #endif 
00161 
00162     concurrent_queue_iterator( const concurrent_queue_base& queue ) :
00163         concurrent_queue_iterator_base_v3(queue)
00164     {
00165     }
00166 public:
00167     concurrent_queue_iterator() {}
00168 
00171     concurrent_queue_iterator( const concurrent_queue_iterator<Container,typename Container::value_type>& other ) :
00172         concurrent_queue_iterator_base_v3(other)
00173     {}
00174 
00176     concurrent_queue_iterator& operator=( const concurrent_queue_iterator& other ) {
00177         assign(other);
00178         return *this;
00179     }
00180 
00182     Value& operator*() const {
00183         return *static_cast<Value*>(my_item);
00184     }
00185 
00186     Value* operator->() const {return &operator*();}
00187 
00189     concurrent_queue_iterator& operator++() {
00190         advance();
00191         return *this;
00192     }
00193 
00195     Value* operator++(int) {
00196         Value* result = &operator*();
00197         operator++();
00198         return result;
00199     }
00200 }; // concurrent_queue_iterator
00201 
00202 
00203 template<typename C, typename T, typename U>
00204 bool operator==( const concurrent_queue_iterator<C,T>& i, const concurrent_queue_iterator<C,U>& j ) {
00205     return i.my_item==j.my_item;
00206 }
00207 
00208 template<typename C, typename T, typename U>
00209 bool operator!=( const concurrent_queue_iterator<C,T>& i, const concurrent_queue_iterator<C,U>& j ) {
00210     return i.my_item!=j.my_item;
00211 }
00212 
00213 } // namespace internal;
00214 
00216 
00218 
00221 template<typename T, class A>
00222 class concurrent_queue: public internal::concurrent_queue_base_v3 {
00223     template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
00224 
00226     typedef typename A::template rebind<char>::other page_allocator_type;
00227     page_allocator_type my_allocator;
00228 
00230     class destroyer {
00231         T& my_value;
00232     public:
00233         destroyer( T& value ) : my_value(value) {}
00234         ~destroyer() {my_value.~T();}          
00235     };
00236 
00237     T& get_ref( page& page, size_t index ) {
00238         __TBB_ASSERT( index<items_per_page, NULL );
00239         return static_cast<T*>(static_cast<void*>(&page+1))[index];
00240     }
00241 
00242     /*override*/ virtual void copy_item( page& dst, size_t index, const void* src ) {
00243         new( &get_ref(dst,index) ) T(*static_cast<const T*>(src)); 
00244     }
00245 
00246     /*override*/ virtual void assign_and_destroy_item( void* dst, page& src, size_t index ) {
00247         T& from = get_ref(src,index);
00248         destroyer d(from);
00249         *static_cast<T*>(dst) = from;
00250     }
00251 
00252     /*overide*/ virtual page *allocate_page() {
00253         size_t n = sizeof(page) + items_per_page*item_size;
00254         page *p = reinterpret_cast<page*>(my_allocator.allocate( n ));
00255         if( !p ) internal_throw_exception(); 
00256         return p;
00257     }
00258     
00259     /*override*/ virtual void deallocate_page( page *p ) {
00260         size_t n = sizeof(page) + items_per_page*item_size;
00261         my_allocator.deallocate( reinterpret_cast<char*>(p), n );
00262     }
00263 
00264 public:
00266     typedef T value_type;
00267 
00269     typedef A allocator_type;
00270 
00272     typedef T& reference;
00273 
00275     typedef const T& const_reference;
00276 
00278 
00280     typedef std::ptrdiff_t size_type;
00281 
00283     typedef std::ptrdiff_t difference_type;
00284 
00286     concurrent_queue(const allocator_type  &a = allocator_type()) : 
00287         concurrent_queue_base_v3( sizeof(T) )
00288             , my_allocator( a )
00289     {
00290     }
00291 
00293     ~concurrent_queue();
00294 
00296     void push( const T& source ) {
00297         internal_push( &source );
00298     }
00299 
00301 
00302     void pop( T& destination ) {
00303         internal_pop( &destination );
00304     }
00305 
00307 
00309     bool push_if_not_full( const T& source ) {
00310         return internal_push_if_not_full( &source );
00311     }
00312 
00314 
00316     bool pop_if_present( T& destination ) {
00317         return internal_pop_if_present( &destination );
00318     }
00319 
00321 
00324     size_type size() const {return internal_size();}
00325 
00327     bool empty() const {return size()<=0;}
00328 
00330     size_type capacity() const {
00331         return my_capacity;
00332     }
00333 
00335 
00337     void set_capacity( size_type capacity ) {
00338         internal_set_capacity( capacity, sizeof(T) );
00339     }
00340 
00342     allocator_type get_allocator() const { return this->my_allocator; }
00343 
00345     void clear() ;
00346 
00347     typedef internal::concurrent_queue_iterator<concurrent_queue,T> iterator;
00348     typedef internal::concurrent_queue_iterator<concurrent_queue,const T> const_iterator;
00349 
00350     //------------------------------------------------------------------------
00351     // The iterators are intended only for debugging.  They are slow and not thread safe.
00352     //------------------------------------------------------------------------
00353     iterator begin() {return iterator(*this);}
00354     iterator end() {return iterator();}
00355     const_iterator begin() const {return const_iterator(*this);}
00356     const_iterator end() const {return const_iterator();}
00357     
00358 }; 
00359 
00360 template<typename T, class A>
00361 concurrent_queue<T,A>::~concurrent_queue() {
00362     clear();
00363 }
00364 
00365 template<typename T, class A>
00366 void concurrent_queue<T,A>::clear() {
00367     while( !empty() ) {
00368         T value;
00369         internal_pop_if_present(&value);
00370     }
00371     internal_finish_clear();
00372 }
00373 
00374 } // namespace tbb
00375 
00376 #endif /* __TBB_concurrent_queue_H */

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