#ifndef __TBB_concurrent_queue_H
#define __TBB_concurrent_queue_H
#include "internal/_concurrent_queue_impl.h"
namespace tbb {
namespace strict_ppl {
@ingroup
template<typename T, typename A = cache_aligned_allocator<T> >
class concurrent_queue: public internal::concurrent_queue_base_v3<T> {
template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
typedef typename A::template rebind<char>::other page_allocator_type;
page_allocator_type my_allocator;
virtual void *allocate_block( size_t n ) {
void *b = reinterpret_cast<void*>(my_allocator.allocate( n ));
if( !b )
internal::throw_exception(internal::eid_bad_alloc);
return b;
}
virtual void deallocate_block( void *b, size_t n ) {
my_allocator.deallocate( reinterpret_cast<char*>(b), n );
}
public:
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef A allocator_type;
explicit concurrent_queue(const allocator_type& a = allocator_type()) :
my_allocator( a )
{
}
template<typename InputIterator>
concurrent_queue( InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()) :
my_allocator( a )
{
for( ; begin != end; ++begin )
this->internal_push(&*begin);
}
concurrent_queue( const concurrent_queue& src, const allocator_type& a = allocator_type()) :
internal::concurrent_queue_base_v3<T>(), my_allocator( a )
{
this->assign( src );
}
~concurrent_queue();
void push( const T& source ) {
this->internal_push( &source );
}
bool try_pop( T& result ) {
return this->internal_try_pop( &result );
}
size_type unsafe_size() const {return this->internal_size();}
bool empty() const {return this->internal_empty();}
void clear() ;
allocator_type get_allocator() const { return this->my_allocator; }
typedef internal::concurrent_queue_iterator<concurrent_queue,T> iterator;
typedef internal::concurrent_queue_iterator<concurrent_queue,const T> const_iterator;
iterator unsafe_begin() {return iterator(*this);}
iterator unsafe_end() {return iterator();}
const_iterator unsafe_begin() const {return const_iterator(*this);}
const_iterator unsafe_end() const {return const_iterator();}
} ;
template<typename T, class A>
concurrent_queue<T,A>::~concurrent_queue() {
clear();
this->internal_finish_clear();
}
template<typename T, class A>
void concurrent_queue<T,A>::clear() {
while( !empty() ) {
T value;
this->internal_try_pop(&value);
}
}
}
@ingroup
template<typename T, class A = cache_aligned_allocator<T> >
class concurrent_bounded_queue: public internal::concurrent_queue_base_v3 {
template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
typedef typename A::template rebind<char>::other page_allocator_type;
page_allocator_type my_allocator;
typedef typename concurrent_queue_base_v3::padded_page<T> padded_page;
class destroyer: internal::no_copy {
T& my_value;
public:
destroyer( T& value ) : my_value(value) {}
~destroyer() {my_value.~T();}
};
T& get_ref( page& p, size_t index ) {
__TBB_ASSERT( index<items_per_page, NULL );
return (&static_cast<padded_page*>(static_cast<void*>(&p))->last)[index];
}
virtual void copy_item( page& dst, size_t index, const void* src ) {
new( &get_ref(dst,index) ) T(*static_cast<const T*>(src));
}
virtual void copy_page_item( page& dst, size_t dindex, const page& src, size_t sindex ) {
new( &get_ref(dst,dindex) ) T( get_ref( const_cast<page&>(src), sindex ) );
}
virtual void assign_and_destroy_item( void* dst, page& src, size_t index ) {
T& from = get_ref(src,index);
destroyer d(from);
*static_cast<T*>(dst) = from;
}
virtual page *allocate_page() {
size_t n = sizeof(padded_page) + (items_per_page-1)*sizeof(T);
page *p = reinterpret_cast<page*>(my_allocator.allocate( n ));
if( !p )
internal::throw_exception(internal::eid_bad_alloc);
return p;
}
virtual void deallocate_page( page *p ) {
size_t n = sizeof(padded_page) + (items_per_page-1)*sizeof(T);
my_allocator.deallocate( reinterpret_cast<char*>(p), n );
}
public:
typedef T value_type;
typedef A allocator_type;
typedef T& reference;
typedef const T& const_reference;
typedef std::ptrdiff_t size_type;
typedef std::ptrdiff_t difference_type;
explicit concurrent_bounded_queue(const allocator_type& a = allocator_type()) :
concurrent_queue_base_v3( sizeof(T) ), my_allocator( a )
{
}
concurrent_bounded_queue( const concurrent_bounded_queue& src, const allocator_type& a = allocator_type()) :
concurrent_queue_base_v3( sizeof(T) ), my_allocator( a )
{
assign( src );
}
template<typename InputIterator>
concurrent_bounded_queue( InputIterator begin, InputIterator end, const allocator_type& a = allocator_type()) :
concurrent_queue_base_v3( sizeof(T) ), my_allocator( a )
{
for( ; begin != end; ++begin )
internal_push_if_not_full(&*begin);
}
~concurrent_bounded_queue();
void push( const T& source ) {
internal_push( &source );
}
void pop( T& destination ) {
internal_pop( &destination );
}
#if TBB_USE_EXCEPTIONS
void abort() {
internal_abort();
}
#endif
bool try_push( const T& source ) {
return internal_push_if_not_full( &source );
}
bool try_pop( T& destination ) {
return internal_pop_if_present( &destination );
}
size_type size() const {return internal_size();}
bool empty() const {return internal_empty();}
size_type capacity() const {
return my_capacity;
}
void set_capacity( size_type new_capacity ) {
internal_set_capacity( new_capacity, sizeof(T) );
}
allocator_type get_allocator() const { return this->my_allocator; }
void clear() ;
typedef internal::concurrent_queue_iterator<concurrent_bounded_queue,T> iterator;
typedef internal::concurrent_queue_iterator<concurrent_bounded_queue,const T> const_iterator;
iterator unsafe_begin() {return iterator(*this);}
iterator unsafe_end() {return iterator();}
const_iterator unsafe_begin() const {return const_iterator(*this);}
const_iterator unsafe_end() const {return const_iterator();}
};
template<typename T, class A>
concurrent_bounded_queue<T,A>::~concurrent_bounded_queue() {
clear();
internal_finish_clear();
}
template<typename T, class A>
void concurrent_bounded_queue<T,A>::clear() {
while( !empty() ) {
T value;
internal_pop_if_present(&value);
}
}
namespace deprecated {
@ingroup
template<typename T, class A = cache_aligned_allocator<T> >
class concurrent_queue: public concurrent_bounded_queue<T,A> {
#if !__TBB_TEMPLATE_FRIENDS_BROKEN
template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
#endif
public:
explicit concurrent_queue(const A& a = A()) :
concurrent_bounded_queue<T,A>( a )
{
}
concurrent_queue( const concurrent_queue& src, const A& a = A()) :
concurrent_bounded_queue<T,A>( src, a )
{
}
template<typename InputIterator>
concurrent_queue( InputIterator b , InputIterator e , const A& a = A()) :
concurrent_bounded_queue<T,A>( b, e, a )
{
}
bool push_if_not_full( const T& source ) {
return this->try_push( source );
}
@deprecated
bool pop_if_present( T& destination ) {
return this->try_pop( destination );
}
typedef typename concurrent_bounded_queue<T,A>::iterator iterator;
typedef typename concurrent_bounded_queue<T,A>::const_iterator const_iterator;
iterator begin() {return this->unsafe_begin();}
iterator end() {return this->unsafe_end();}
const_iterator begin() const {return this->unsafe_begin();}
const_iterator end() const {return this->unsafe_end();}
};
}
#if TBB_DEPRECATED
using deprecated::concurrent_queue;
#else
using strict_ppl::concurrent_queue;
#endif
}
#endif