![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
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.