_flow_graph_impl.h   _flow_graph_impl.h 
skipping to change at line 60 skipping to change at line 60
//! The leaf for source_body //! The leaf for source_body
template< typename Output, typename Body> template< typename Output, typename Body>
class source_body_leaf : public source_body<Output> { class source_body_leaf : public source_body<Output> {
public: public:
source_body_leaf( const Body &_body ) : body(_body), init_body(_bod y) { } source_body_leaf( const Body &_body ) : body(_body), init_body(_bod y) { }
/*override*/ bool operator()(Output &output) { return body( output ); } /*override*/ bool operator()(Output &output) { return body( output ); }
/*override*/ source_body_leaf* clone() { /*override*/ source_body_leaf* clone() {
return new source_body_leaf< Output, Body >(init_body); return new source_body_leaf< Output, Body >(init_body);
} }
Body get_body() { return body; }
private: private:
Body body; Body body;
Body init_body; Body init_body;
}; };
//! A functor that takes an Input and generates an Output //! A functor that takes an Input and generates an Output
template< typename Input, typename Output > template< typename Input, typename Output >
class function_body : tbb::internal::no_assign { class function_body : tbb::internal::no_assign {
public: public:
virtual ~function_body() {} virtual ~function_body() {}
skipping to change at line 283 skipping to change at line 284
T *v = my_q.front(); T *v = my_q.front();
my_q.pop(); my_q.pop();
return *v; return *v;
} }
}; };
//! A cache of predecessors that only supports try_get //! A cache of predecessors that only supports try_get
template< typename T, typename M=spin_mutex > template< typename T, typename M=spin_mutex >
class predecessor_cache : public node_cache< sender<T>, M > { class predecessor_cache : public node_cache< sender<T>, M > {
public: public:
typedef M my_mutex_type; typedef M my_mutex_type;
typedef T output_type; typedef T output_type;
typedef sender<output_type> predecessor_type; typedef sender<output_type> predecessor_type;
typedef receiver<output_type> successor_type; typedef receiver<output_type> successor_type;
predecessor_cache( ) : my_owner( NULL ) { } predecessor_cache( ) : my_owner( NULL ) { }
void set_owner( successor_type *owner ) { my_owner = owner; } void set_owner( successor_type *owner ) { my_owner = owner; }
bool get_item( output_type &v ) { bool get_item( output_type &v ) {
skipping to change at line 322 skipping to change at line 323
if ( my_owner) if ( my_owner)
src->register_successor( *my_owner ); src->register_successor( *my_owner );
} else { } else {
// Retain ownership of the edge // Retain ownership of the edge
this->add(*src); this->add(*src);
} }
} while ( msg == false ); } while ( msg == false );
return msg; return msg;
} }
void reset() {
if(!my_owner) {
return; // retain ownership of edges
}
for(;;) {
predecessor_type *src;
{
typename my_mutex_type::scoped_lock lock(this->my_mutex
);
if(this->internal_empty()) break;
src = &this->internal_pop();
}
src->register_successor( *my_owner);
}
}
protected: protected:
successor_type *my_owner; successor_type *my_owner;
}; };
//! An cache of predecessors that supports requests and reservations //! An cache of predecessors that supports requests and reservations
template< typename T, typename M=spin_mutex > template< typename T, typename M=spin_mutex >
class reservable_predecessor_cache : public predecessor_cache< T, M > { class reservable_predecessor_cache : public predecessor_cache< T, M > {
public: public:
typedef M my_mutex_type; typedef M my_mutex_type;
typedef T output_type; typedef T output_type;
typedef sender<T> predecessor_type; typedef sender<T> predecessor_type;
skipping to change at line 381 skipping to change at line 398
return true; return true;
} }
bool bool
try_consume( ) { try_consume( ) {
reserved_src->try_consume( ); reserved_src->try_consume( );
reserved_src = NULL; reserved_src = NULL;
return true; return true;
} }
void reset() {
reserved_src = NULL;
predecessor_cache<T,M>::reset();
}
private: private:
predecessor_type *reserved_src; predecessor_type *reserved_src;
}; };
//! An abstract cache of succesors //! An abstract cache of successors
template<typename T, typename M=spin_rw_mutex > template<typename T, typename M=spin_rw_mutex >
class successor_cache : tbb::internal::no_copy { class successor_cache : tbb::internal::no_copy {
protected: protected:
typedef M my_mutex_type; typedef M my_mutex_type;
my_mutex_type my_mutex; my_mutex_type my_mutex;
typedef std::list< receiver<T> * > my_successors_type; typedef std::list< receiver<T> * > my_successors_type;
my_successors_type my_successors; my_successors_type my_successors;
skipping to change at line 454 skipping to change at line 476
successor_cache( ) : my_owner(NULL) {} successor_cache( ) : my_owner(NULL) {}
void set_owner( sender<continue_msg> *owner ) { my_owner = owner; } void set_owner( sender<continue_msg> *owner ) { my_owner = owner; }
virtual ~successor_cache() {} virtual ~successor_cache() {}
void register_successor( receiver<continue_msg> &r ) { void register_successor( receiver<continue_msg> &r ) {
my_mutex_type::scoped_lock l(my_mutex, true); my_mutex_type::scoped_lock l(my_mutex, true);
my_successors.push_back( &r ); my_successors.push_back( &r );
if ( my_owner ) { if ( my_owner && r.is_continue_receiver() ) {
continue_receiver *cr = dynamic_cast< continue_receiver * > r.register_predecessor( *my_owner );
(&r);
if ( cr )
cr->register_predecessor( *my_owner );
} }
} }
void remove_successor( receiver<continue_msg> &r ) { void remove_successor( receiver<continue_msg> &r ) {
my_mutex_type::scoped_lock l(my_mutex, true); my_mutex_type::scoped_lock l(my_mutex, true);
for ( my_successors_type::iterator i = my_successors.begin(); for ( my_successors_type::iterator i = my_successors.begin();
i != my_successors.end(); ++i ) { i != my_successors.end(); ++i ) {
if ( *i == & r ) { if ( *i == & r ) {
if ( my_owner ) if ( my_owner )
r.remove_predecessor( *my_owner ); r.remove_predecessor( *my_owner );
 End of changes. 7 change blocks. 
7 lines changed or deleted 27 lines changed or added


 _flow_graph_item_buffer_impl.h   _flow_graph_item_buffer_impl.h 
skipping to change at line 130 skipping to change at line 130
bool pop_front(T &v) { bool pop_front(T &v) {
if(!item_valid(my_head)) { if(!item_valid(my_head)) {
return false; return false;
} }
fetch_front(v); fetch_front(v);
invalidate_front(); invalidate_front();
++my_head; ++my_head;
return true; return true;
} }
void clean_up_buffer() {
if (my_array) {
for( size_type i=0; i<my_array_size; ++i ) {
my_array[i].first.~input_type();
}
allocator_type().deallocate(my_array,my_array_size);
}
my_array = NULL;
my_head = my_tail = my_array_size = 0;
}
public: public:
//! Constructor //! Constructor
item_buffer( ) : my_array(NULL), my_array_size(0), item_buffer( ) : my_array(NULL), my_array_size(0),
my_head(0), my_tail(0) { my_head(0), my_tail(0) {
grow_my_array(initial_buffer_size); grow_my_array(initial_buffer_size);
} }
~item_buffer() { ~item_buffer() {
if (my_array) { clean_up_buffer();
for( size_type i=0; i<my_array_size; ++i ) {
my_array[i].first.~input_type();
}
allocator_type().deallocate(my_array,my_array_size);
}
} }
void reset() { clean_up_buffer(); grow_my_array(initial_buffer_size
); }
}; };
//! item_buffer with reservable front-end. NOTE: if reserving, do not //! item_buffer with reservable front-end. NOTE: if reserving, do not
//* complete operation with pop_front(); use consume_front(). //* complete operation with pop_front(); use consume_front().
//* No synchronization built-in. //* No synchronization built-in.
template<typename T, typename A=cache_aligned_allocator<T> > template<typename T, typename A=cache_aligned_allocator<T> >
class reservable_item_buffer : public item_buffer<T, A> { class reservable_item_buffer : public item_buffer<T, A> {
protected: protected:
using item_buffer<T, A>::buffer_empty; using item_buffer<T, A>::buffer_empty;
using item_buffer<T, A>::fetch_front; using item_buffer<T, A>::fetch_front;
using item_buffer<T, A>::invalidate_front; using item_buffer<T, A>::invalidate_front;
using item_buffer<T, A>::validate_front; using item_buffer<T, A>::validate_front;
using item_buffer<T, A>::item_valid; using item_buffer<T, A>::item_valid;
using item_buffer<T, A>::my_head; using item_buffer<T, A>::my_head;
public: public:
reservable_item_buffer() : item_buffer<T, A>(), my_reserved(false) {} reservable_item_buffer() : item_buffer<T, A>(), my_reserved(false) {}
void reset() {my_reserved = false; item_buffer<T,A>::reset(); }
protected: protected:
bool reserve_front(T &v) { bool reserve_front(T &v) {
if(my_reserved || !item_valid(my_head)) return false; if(my_reserved || !item_valid(my_head)) return false;
my_reserved = true; my_reserved = true;
// reserving the head // reserving the head
fetch_front(v); fetch_front(v);
// invalidate the head, but don't commit until consume is calle d // invalidate the head, but don't commit until consume is calle d
invalidate_front(); invalidate_front();
return true; return true;
 End of changes. 4 change blocks. 
6 lines changed or deleted 16 lines changed or added


 _flow_graph_join_impl.h   _flow_graph_join_impl.h 
skipping to change at line 127 skipping to change at line 127
} }
template< typename TagFuncTuple1, typename TagFuncTuple2> template< typename TagFuncTuple1, typename TagFuncTuple2>
static inline void copy_tag_functors(TagFuncTuple1 &my_inputs, TagF uncTuple2 &other_inputs) { static inline void copy_tag_functors(TagFuncTuple1 &my_inputs, TagF uncTuple2 &other_inputs) {
if(std::get<N-1>(other_inputs).my_original_func()) { if(std::get<N-1>(other_inputs).my_original_func()) {
std::get<N-1>(my_inputs).set_my_tag_func(std::get<N-1>(othe r_inputs).my_original_func()->clone()); std::get<N-1>(my_inputs).set_my_tag_func(std::get<N-1>(othe r_inputs).my_original_func()->clone());
std::get<N-1>(my_inputs).set_my_original_tag_func(std::get< N-1>(other_inputs).my_original_func()->clone()); std::get<N-1>(my_inputs).set_my_original_tag_func(std::get< N-1>(other_inputs).my_original_func()->clone());
} }
join_helper<N-1>::copy_tag_functors(my_inputs, other_inputs); join_helper<N-1>::copy_tag_functors(my_inputs, other_inputs);
} }
template<typename InputTuple>
static inline void reset_inputs(InputTuple &my_input) {
join_helper<N-1>::reset_inputs(my_input);
std::get<N-1>(my_input).reinitialize_port();
}
}; };
template< > template< >
struct join_helper<1> { struct join_helper<1> {
template< typename TupleType, typename PortType > template< typename TupleType, typename PortType >
static inline void set_join_node_pointer(TupleType &my_input, PortT ype *port) { static inline void set_join_node_pointer(TupleType &my_input, PortT ype *port) {
std::get<0>( my_input ).set_join_node_pointer(port); std::get<0>( my_input ).set_join_node_pointer(port);
} }
skipping to change at line 191 skipping to change at line 197
std::get<0>(my_tag_funcs) = NULL; std::get<0>(my_tag_funcs) = NULL;
} }
template< typename TagFuncTuple1, typename TagFuncTuple2> template< typename TagFuncTuple1, typename TagFuncTuple2>
static inline void copy_tag_functors(TagFuncTuple1 &my_inputs, TagF uncTuple2 &other_inputs) { static inline void copy_tag_functors(TagFuncTuple1 &my_inputs, TagF uncTuple2 &other_inputs) {
if(std::get<0>(other_inputs).my_original_func()) { if(std::get<0>(other_inputs).my_original_func()) {
std::get<0>(my_inputs).set_my_tag_func(std::get<0>(other_in puts).my_original_func()->clone()); std::get<0>(my_inputs).set_my_tag_func(std::get<0>(other_in puts).my_original_func()->clone());
std::get<0>(my_inputs).set_my_original_tag_func(std::get<0> (other_inputs).my_original_func()->clone()); std::get<0>(my_inputs).set_my_original_tag_func(std::get<0> (other_inputs).my_original_func()->clone());
} }
} }
template<typename InputTuple>
static inline void reset_inputs(InputTuple &my_input) {
std::get<0>(my_input).reinitialize_port();
}
}; };
//! The two-phase join port //! The two-phase join port
template< typename T > template< typename T >
class reserving_port : public receiver<T> { class reserving_port : public receiver<T> {
public: public:
typedef T input_type; typedef T input_type;
typedef sender<T> predecessor_type; typedef sender<T> predecessor_type;
private: private:
// ----------- Aggregator ------------ // ----------- Aggregator ------------
skipping to change at line 330 skipping to change at line 340
reserving_port_operation op_data(rel_res); reserving_port_operation op_data(rel_res);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
//! Complete use of the port //! Complete use of the port
void consume( ) { void consume( ) {
reserving_port_operation op_data(con_res); reserving_port_operation op_data(con_res);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
void reinitialize_port() {
my_predecessors.reset();
reserved = false;
}
protected:
/*override*/void reset_receiver() {
my_predecessors.reset();
}
private: private:
forwarding_base *my_join; forwarding_base *my_join;
reservable_predecessor_cache< T, null_mutex > my_predecessors; reservable_predecessor_cache< T, null_mutex > my_predecessors;
bool reserved; bool reserved;
}; };
//! queueing join_port //! queueing join_port
template<typename T> template<typename T>
class queueing_port : public receiver<T>, public item_buffer<T> { class queueing_port : public receiver<T>, public item_buffer<T> {
public: public:
skipping to change at line 443 skipping to change at line 464
} }
// reset_port is called when item is accepted by successor, but // reset_port is called when item is accepted by successor, but
// is initiated by join_node. // is initiated by join_node.
void reset_port() { void reset_port() {
queueing_port_operation op_data(res_port); queueing_port_operation op_data(res_port);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return; return;
} }
void reinitialize_port() {
item_buffer<T>::reset();
}
protected:
/*override*/void reset_receiver() {
// nothing to do. We queue, so no predecessor cache
}
private: private:
forwarding_base *my_join; forwarding_base *my_join;
}; };
#include "_flow_graph_tagged_buffer_impl.h" #include "_flow_graph_tagged_buffer_impl.h"
template< typename T > template< typename T >
class tag_matching_port : public receiver<T>, public tagged_buffer< tag _value, T, NO_TAG > { class tag_matching_port : public receiver<T>, public tagged_buffer< tag _value, T, NO_TAG > {
public: public:
typedef T input_type; typedef T input_type;
typedef sender<T> predecessor_type; typedef sender<T> predecessor_type;
typedef tag_matching_port<T> my_node_type; // for forwarding, if n eeded typedef tag_matching_port<T> my_node_type; // for forwarding, if n eeded
typedef function_body<input_type, tag_value> my_tag_func_type; typedef function_body<input_type, tag_value> my_tag_func_type;
typedef tagged_buffer<tag_value,T,NO_TAG> my_buffer_type;
private: private:
// ----------- Aggregator ------------ // ----------- Aggregator ------------
private: private:
enum op_type { try__put, get__item, res_port }; enum op_type { try__put, get__item, res_port };
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
typedef tag_matching_port<T> my_class; typedef tag_matching_port<T> my_class;
class tag_matching_port_operation : public aggregated_operation<tag _matching_port_operation> { class tag_matching_port_operation : public aggregated_operation<tag _matching_port_operation> {
public: public:
char type; char type;
skipping to change at line 581 skipping to change at line 613
// is initiated by join_node. // is initiated by join_node.
void reset_port() { void reset_port() {
tag_matching_port_operation op_data(res_port); tag_matching_port_operation op_data(res_port);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return; return;
} }
my_tag_func_type *my_func() { return my_tag_func; } my_tag_func_type *my_func() { return my_tag_func; }
my_tag_func_type *my_original_func() { return my_original_tag_func; } my_tag_func_type *my_original_func() { return my_original_tag_func; }
void reinitialize_port() {
my_buffer_type::reset();
}
protected:
/*override*/void reset_receiver() {
// nothing to do. We queue, so no predecessor cache
}
private: private:
// need map of tags to values // need map of tags to values
forwarding_base *my_join; forwarding_base *my_join;
my_tag_func_type *my_tag_func; my_tag_func_type *my_tag_func;
my_tag_func_type *my_original_tag_func; my_tag_func_type *my_original_tag_func;
}; // tag_matching_port }; // tag_matching_port
using namespace graph_policy_namespace; using namespace graph_policy_namespace;
template<graph_buffer_policy JP, typename InputTuple, typename OutputTu ple> template<graph_buffer_policy JP, typename InputTuple, typename OutputTu ple>
skipping to change at line 630 skipping to change at line 672
// if all input_ports have predecessors, spawn forward to try and c onsume tuples // if all input_ports have predecessors, spawn forward to try and c onsume tuples
void decrement_port_count() { void decrement_port_count() {
if(ports_with_no_inputs.fetch_and_decrement() == 1) { if(ports_with_no_inputs.fetch_and_decrement() == 1) {
task::enqueue( * new ( task::allocate_additional_child_of( *(this->my_root_task) ) ) task::enqueue( * new ( task::allocate_additional_child_of( *(this->my_root_task) ) )
forward_task<my_node_type>(*my_node) ); forward_task<my_node_type>(*my_node) );
} }
} }
input_type &input_ports() { return my_inputs; } input_type &input_ports() { return my_inputs; }
protected: protected:
void reset() {
// called outside of parallel contexts
ports_with_no_inputs = N;
join_helper<N>::reset_inputs(my_inputs);
}
// all methods on input ports should be called under mutual exclusi on from join_node_base. // all methods on input ports should be called under mutual exclusi on from join_node_base.
bool tuple_build_may_succeed() { bool tuple_build_may_succeed() {
return !ports_with_no_inputs; return !ports_with_no_inputs;
} }
bool try_to_make_tuple(output_type &out) { bool try_to_make_tuple(output_type &out) {
if(ports_with_no_inputs) return false; if(ports_with_no_inputs) return false;
return join_helper<N>::reserve(my_inputs, out); return join_helper<N>::reserve(my_inputs, out);
} }
skipping to change at line 690 skipping to change at line 740
void decrement_port_count() { void decrement_port_count() {
if(ports_with_no_items.fetch_and_decrement() == 1) { if(ports_with_no_items.fetch_and_decrement() == 1) {
task::enqueue( * new ( task::allocate_additional_child_of( *(this->my_root_task) ) ) task::enqueue( * new ( task::allocate_additional_child_of( *(this->my_root_task) ) )
forward_task<my_node_type>(*my_node) ); forward_task<my_node_type>(*my_node) );
} }
} }
void increment_port_count() { __TBB_ASSERT(false, NULL); } // shou ld never be called void increment_port_count() { __TBB_ASSERT(false, NULL); } // shou ld never be called
input_type &input_ports() { return my_inputs; } input_type &input_ports() { return my_inputs; }
protected: protected:
void reset() {
reset_port_count();
join_helper<N>::reset_inputs(my_inputs);
}
// all methods on input ports should be called under mutual exclusi on from join_node_base. // all methods on input ports should be called under mutual exclusi on from join_node_base.
bool tuple_build_may_succeed() { bool tuple_build_may_succeed() {
return !ports_with_no_items; return !ports_with_no_items;
} }
bool try_to_make_tuple(output_type &out) { bool try_to_make_tuple(output_type &out) {
if(ports_with_no_items) return false; if(ports_with_no_items) return false;
return join_helper<N>::get_items(my_inputs, out); return join_helper<N>::get_items(my_inputs, out);
} }
skipping to change at line 865 skipping to change at line 922
tag_matching_FE_operation op_data(t, inc_count); tag_matching_FE_operation op_data(t, inc_count);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return; return;
} }
void decrement_port_count() { __TBB_ASSERT(false, NULL); } void decrement_port_count() { __TBB_ASSERT(false, NULL); }
void increment_port_count() { __TBB_ASSERT(false, NULL); } // shou ld never be called void increment_port_count() { __TBB_ASSERT(false, NULL); } // shou ld never be called
input_type &input_ports() { return my_inputs; } input_type &input_ports() { return my_inputs; }
protected: protected:
void reset() {
// called outside of parallel contexts
join_helper<N>::reset_inputs(my_inputs);
my_tag_buffer::reset(); // have to reset the tag counts
output_buffer_type::reset(); // also the queue of outputs
my_node->current_tag = NO_TAG;
}
// all methods on input ports should be called under mutual exclusi on from join_node_base. // all methods on input ports should be called under mutual exclusi on from join_node_base.
bool tuple_build_may_succeed() { // called from back-end bool tuple_build_may_succeed() { // called from back-end
tag_matching_FE_operation op_data(may_succeed); tag_matching_FE_operation op_data(may_succeed);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.status == SUCCEEDED; return op_data.status == SUCCEEDED;
} }
// cannot lock while calling back to input_ports. current_tag will only be set // cannot lock while calling back to input_ports. current_tag will only be set
// and reset under the aggregator, so it will remain consistent. // and reset under the aggregator, so it will remain consistent.
skipping to change at line 1028 skipping to change at line 1096
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.status == SUCCEEDED; return op_data.status == SUCCEEDED;
} }
bool try_get( output_type &v) { bool try_get( output_type &v) {
join_node_base_operation op_data(v, try__get); join_node_base_operation op_data(v, try__get);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.status == SUCCEEDED; return op_data.status == SUCCEEDED;
} }
protected:
/*override*/void reset() {
input_ports_type::reset();
}
private: private:
broadcast_cache<output_type, null_rw_mutex> my_successors; broadcast_cache<output_type, null_rw_mutex> my_successors;
friend class forward_task< join_node_base<JP, InputTuple, OutputTup le> >; friend class forward_task< join_node_base<JP, InputTuple, OutputTup le> >;
void forward() { void forward() {
join_node_base_operation op_data(do_fwrd); join_node_base_operation op_data(do_fwrd);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
}; };
 End of changes. 13 change blocks. 
0 lines changed or deleted 74 lines changed or added


 _flow_graph_node_impl.h   _flow_graph_node_impl.h 
skipping to change at line 125 skipping to change at line 125
//! Removes src from the list of cached predecessors. //! Removes src from the list of cached predecessors.
/* override */ bool remove_predecessor( predecessor_type &src ) { /* override */ bool remove_predecessor( predecessor_type &src ) {
my_operation op_data(rem_pred); my_operation op_data(rem_pred);
op_data.r = &src; op_data.r = &src;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return true; return true;
} }
protected: protected:
void reset_function_input_base() {
my_concurrency = 0;
if(my_queue) {
my_queue->reset();
}
my_predecessors.reset();
}
task *my_root_task; task *my_root_task;
const size_t my_max_concurrency; const size_t my_max_concurrency;
size_t my_concurrency; size_t my_concurrency;
function_input_queue<input_type, A> *my_queue; function_input_queue<input_type, A> *my_queue;
predecessor_cache<input_type, null_mutex > my_predecessors; predecessor_cache<input_type, null_mutex > my_predecessors;
/*override*/void reset_receiver() {
my_predecessors.reset();
}
private: private:
friend class apply_body_task< my_class, input_type >; friend class apply_body_task< my_class, input_type >;
friend class forward_task< my_class >; friend class forward_task< my_class >;
class my_operation : public aggregated_operation< my_operation > { class my_operation : public aggregated_operation< my_operation > {
public: public:
char type; char type;
union { union {
input_type *elem; input_type *elem;
skipping to change at line 190 skipping to change at line 202
else else
item_was_retrieved = my_predecessors.get_item(i ); item_was_retrieved = my_predecessors.get_item(i );
if (item_was_retrieved) { if (item_was_retrieved) {
++my_concurrency; ++my_concurrency;
spawn_body_task(i); spawn_body_task(i);
} }
} }
break; break;
case tryput: internal_try_put(tmp); break; case tryput: internal_try_put(tmp); break;
case try_fwd: internal_forward(tmp); break; case try_fwd: internal_forward(tmp); break;
} }
} }
} }
//! Put to the node //! Put to the node
void internal_try_put(my_operation *op) { void internal_try_put(my_operation *op) {
__TBB_ASSERT(my_max_concurrency != 0, NULL); __TBB_ASSERT(my_max_concurrency != 0, NULL);
if (my_concurrency < my_max_concurrency) { if (my_concurrency < my_max_concurrency) {
++my_concurrency; ++my_concurrency;
spawn_body_task(*(op->elem)); spawn_body_task(*(op->elem));
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
skipping to change at line 296 skipping to change at line 308
Body copy_function_object() { Body copy_function_object() {
internal::function_body<input_type, output_type> &body_ref = *t his->my_body; internal::function_body<input_type, output_type> &body_ref = *t his->my_body;
return dynamic_cast< internal::function_body_leaf<input_type, o utput_type, Body> & >(body_ref).get_body(); return dynamic_cast< internal::function_body_leaf<input_type, o utput_type, Body> & >(body_ref).get_body();
} }
void apply_body_impl( const input_type &i) { void apply_body_impl( const input_type &i) {
successors().try_put( (*my_body)(i) ); successors().try_put( (*my_body)(i) );
} }
protected: protected:
void reset_function_input() {
base_type::reset_function_input_base();
}
function_body<input_type, output_type> *my_body; function_body<input_type, output_type> *my_body;
virtual broadcast_cache<output_type > &successors() = 0; virtual broadcast_cache<output_type > &successors() = 0;
}; };
//! Implements methods for a function node that takes a type Input as i nput //! Implements methods for a function node that takes a type Input as i nput
// and has a tuple of output ports specified. // and has a tuple of output ports specified.
template< typename Input, typename OutputPortSet, typename A> template< typename Input, typename OutputPortSet, typename A>
class multifunction_input : public function_input_base<Input, A, multif unction_input<Input,OutputPortSet,A> > { class multifunction_input : public function_input_base<Input, A, multif unction_input<Input,OutputPortSet,A> > {
public: public:
skipping to change at line 346 skipping to change at line 363
return dynamic_cast< internal::multifunction_body_leaf<input_ty pe, output_ports_type, Body> & >(body_ref).get_body(); return dynamic_cast< internal::multifunction_body_leaf<input_ty pe, output_ports_type, Body> & >(body_ref).get_body();
} }
void apply_body_impl( const input_type &i) { void apply_body_impl( const input_type &i) {
(*my_body)(i, my_output_ports); (*my_body)(i, my_output_ports);
} }
output_ports_type &output_ports(){ return my_output_ports; } output_ports_type &output_ports(){ return my_output_ports; }
protected: protected:
void reset() {
base_type::reset_function_input_base();
}
multifunction_body<input_type, output_ports_type> *my_body; multifunction_body<input_type, output_ports_type> *my_body;
output_ports_type my_output_ports; output_ports_type my_output_ports;
}; };
// template to refer to an output port of a multifunction_node // template to refer to an output port of a multifunction_node
template<size_t N, typename MOP> template<size_t N, typename MOP>
typename std::tuple_element<N, typename MOP::output_ports_type>::type & output_port(MOP &op) { typename std::tuple_element<N, typename MOP::output_ports_type>::type & output_port(MOP &op) {
return std::get<N>(op.output_ports()); return std::get<N>(op.output_ports());
} }
 End of changes. 5 change blocks. 
1 lines changed or deleted 23 lines changed or added


 _flow_graph_or_impl.h   _flow_graph_or_impl.h 
skipping to change at line 128 skipping to change at line 128
template<typename T> template<typename T>
class or_input_port : public receiver<T> { class or_input_port : public receiver<T> {
private: private:
size_t my_index; size_t my_index;
put_base *my_or_node; put_base *my_or_node;
public: public:
void set_up(put_base *p, size_t i) { my_index = i; my_or_node = p; } void set_up(put_base *p, size_t i) { my_index = i; my_or_node = p; }
bool try_put(const T &v) { bool try_put(const T &v) {
return my_or_node->try_put_with_index(my_index, reinterpret_cas t<void *>(const_cast<T*>(&v))); return my_or_node->try_put_with_index(my_index, reinterpret_cas t<void *>(const_cast<T*>(&v)));
} }
protected:
/*override*/void reset_receiver() {}
}; };
template<typename InputTuple, typename OutputType, typename StructTypes > template<typename InputTuple, typename OutputType, typename StructTypes >
class or_node_FE : public put_base { class or_node_FE : public put_base {
public: public:
static const int N = std::tuple_size<InputTuple>::value; static const int N = std::tuple_size<InputTuple>::value;
typedef OutputType output_type; typedef OutputType output_type;
typedef InputTuple input_type; typedef InputTuple input_type;
or_node_FE( ) { or_node_FE( ) {
skipping to change at line 239 skipping to change at line 241
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.status == SUCCEEDED; return op_data.status == SUCCEEDED;
} }
bool try_put_with_index(size_t indx, void *v) { bool try_put_with_index(size_t indx, void *v) {
or_node_base_operation op_data(indx, v, try__put); or_node_base_operation op_data(indx, v, try__put);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.status == SUCCEEDED; return op_data.status == SUCCEEDED;
} }
protected:
/*override*/void reset() {}
private: private:
broadcast_cache<output_type, null_rw_mutex> my_successors; broadcast_cache<output_type, null_rw_mutex> my_successors;
}; };
// type generators // type generators
template<typename OutputTuple> template<typename OutputTuple>
struct or_types { struct or_types {
static const int N = std::tuple_size<OutputTuple>::value; static const int N = std::tuple_size<OutputTuple>::value;
typedef typename wrap_tuple_elements<N,or_input_port,OutputTuple>:: type input_ports_type; typedef typename wrap_tuple_elements<N,or_input_port,OutputTuple>:: type input_ports_type;
typedef typename or_output_type<OutputTuple>::type output_type; typedef typename or_output_type<OutputTuple>::type output_type;
 End of changes. 2 change blocks. 
0 lines changed or deleted 5 lines changed or added


 _flow_graph_tagged_buffer_impl.h   _flow_graph_tagged_buffer_impl.h 
skipping to change at line 123 skipping to change at line 123
size_t l_mask = sz-1; size_t l_mask = sz-1;
size_t h = hash(t) & l_mask; size_t h = hash(t) & l_mask;
__TBB_ASSERT(free_list, "Error: free list not set up."); __TBB_ASSERT(free_list, "Error: free list not set up.");
element_type* my_elem = free_list; free_list = free_list->next; element_type* my_elem = free_list; free_list = free_list->next;
my_elem->t = t; my_elem->t = t;
my_elem->v = v; my_elem->v = v;
my_elem->next = ar[h]; my_elem->next = ar[h];
ar[h] = my_elem; ar[h] = my_elem;
} }
public: void internal_initialize_buffer() {
tagged_buffer() : my_size(INITIAL_SIZE), nelements(0) {
array = pointer_array_allocator_type().allocate(my_size); array = pointer_array_allocator_type().allocate(my_size);
for(size_t i = 0; i < my_size; ++i) array[i] = NULL; for(size_t i = 0; i < my_size; ++i) array[i] = NULL;
lists = new list_array_type(INITIAL_SIZE/2, element_type(), Allocat or()); lists = new list_array_type(INITIAL_SIZE/2, element_type(), Allocat or());
set_up_free_list(&free_list, lists, INITIAL_SIZE/2); set_up_free_list(&free_list, lists, INITIAL_SIZE/2);
} }
~tagged_buffer() { void internal_free_buffer() {
if(array) { if(array) {
pointer_array_allocator_type().deallocate(array, my_size); pointer_array_allocator_type().deallocate(array, my_size);
array = NULL;
} }
if(lists) { if(lists) {
delete lists; delete lists;
lists = NULL;
} }
my_size = INITIAL_SIZE;
nelements = 0;
}
public:
tagged_buffer() : my_size(INITIAL_SIZE), nelements(0) {
internal_initialize_buffer();
}
~tagged_buffer() {
internal_free_buffer();
}
void reset() {
internal_free_buffer();
internal_initialize_buffer();
} }
bool tagged_insert(TagType t, value_type v) { bool tagged_insert(TagType t, value_type v) {
pointer_type p; pointer_type p;
if(tagged_find_ref(t, p)) { if(tagged_find_ref(t, p)) {
*p = v; // replace the value *p = v; // replace the value
return false; return false;
} }
++nelements; ++nelements;
if(nelements*2 > my_size) grow_array(); if(nelements*2 > my_size) grow_array();
 End of changes. 5 change blocks. 
3 lines changed or deleted 20 lines changed or added


 atomic.h   atomic.h 
skipping to change at line 32 skipping to change at line 32
this file and link it with other files to produce an executable, this this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered b y invalidate any other reasons why the executable file might be covered b y
the GNU General Public License. the GNU General Public License.
*/ */
#ifndef __TBB_atomic_H #ifndef __TBB_atomic_H
#define __TBB_atomic_H #define __TBB_atomic_H
#include <cstddef>
#include "tbb_stddef.h" #include "tbb_stddef.h"
#include <cstddef>
#if _MSC_VER #if _MSC_VER
#define __TBB_LONG_LONG __int64 #define __TBB_LONG_LONG __int64
#else #else
#define __TBB_LONG_LONG long long #define __TBB_LONG_LONG long long
#endif /* _MSC_VER */ #endif /* _MSC_VER */
#include "tbb_machine.h" #include "tbb_machine.h"
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
 End of changes. 2 change blocks. 
1 lines changed or deleted 1 lines changed or added


 concurrent_hash_map.h   concurrent_hash_map.h 
skipping to change at line 598 skipping to change at line 598
node( const Key &key ) : item(key, T()) {} node( const Key &key ) : item(key, T()) {}
node( const Key &key, const T &t ) : item(key, t) {} node( const Key &key, const T &t ) : item(key, t) {}
// exception-safe allocation, see C++ Standard 2003, clause 5.3.4p1 7 // exception-safe allocation, see C++ Standard 2003, clause 5.3.4p1 7
void *operator new( size_t /*size*/, node_allocator_type &a ) { void *operator new( size_t /*size*/, node_allocator_type &a ) {
void *ptr = a.allocate(1); void *ptr = a.allocate(1);
if(!ptr) if(!ptr)
tbb::internal::throw_exception(tbb::internal::eid_bad_alloc ); tbb::internal::throw_exception(tbb::internal::eid_bad_alloc );
return ptr; return ptr;
} }
// match placement-new form above to be called if exception thrown in constructor // match placement-new form above to be called if exception thrown in constructor
void operator delete( void *ptr, node_allocator_type &a ) {return a .deallocate(static_cast<node*>(ptr),1); } void operator delete( void *ptr, node_allocator_type &a ) { a.deall ocate(static_cast<node*>(ptr),1); }
}; };
void delete_node( node_base *n ) { void delete_node( node_base *n ) {
my_allocator.destroy( static_cast<node*>(n) ); my_allocator.destroy( static_cast<node*>(n) );
my_allocator.deallocate( static_cast<node*>(n), 1); my_allocator.deallocate( static_cast<node*>(n), 1);
} }
node *search_bucket( const key_type &key, bucket *b ) const { node *search_bucket( const key_type &key, bucket *b ) const {
node *n = static_cast<node*>( b->node_list ); node *n = static_cast<node*>( b->node_list );
while( is_valid(n) && !my_hash_compare.equal(key, n->item.first) ) while( is_valid(n) && !my_hash_compare.equal(key, n->item.first) )
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 concurrent_lru_cache.h   concurrent_lru_cache.h 
skipping to change at line 142 skipping to change at line 142
return handle_object::move(h); return handle_object::move(h);
} }
static handle_move_t move(handle_object& h){ static handle_move_t move(handle_object& h){
__TBB_ASSERT(h.my_cache_pointer,"move from the same object twic e ?"); __TBB_ASSERT(h.my_cache_pointer,"move from the same object twic e ?");
concurrent_lru_cache * cache_pointer = NULL; concurrent_lru_cache * cache_pointer = NULL;
std::swap(cache_pointer,h.my_cache_pointer); std::swap(cache_pointer,h.my_cache_pointer);
return handle_move_t(*cache_pointer,h.my_map_record_ref); return handle_move_t(*cache_pointer,h.my_map_record_ref);
} }
private: private:
void operator=(handle_object&); void operator=(handle_object&);
#if __SUNPRO_CC
// Presumably due to a compiler error, private copy constructor
// breaks expressions like handle h = cache[key];
public:
#endif
handle_object(handle_object &); handle_object(handle_object &);
}; };
private: private:
//TODO: looks like aggregator_operation is a perfect match for statical ly typed variant type //TODO: looks like aggregator_operation is a perfect match for statical ly typed variant type
struct aggregator_operation : tbb::internal::aggregated_operation<aggre gator_operation>{ struct aggregator_operation : tbb::internal::aggregated_operation<aggre gator_operation>{
enum e_op_type {op_retive, op_signal_end_of_usage}; enum e_op_type {op_retive, op_signal_end_of_usage};
//TODO: try to use pointer to function apply_visitor here //TODO: try to use pointer to function apply_visitor here
//TODO: try virtual functions and measure the difference //TODO: try virtual functions and measure the difference
e_op_type my_operation_type; e_op_type my_operation_type;
aggregator_operation(e_op_type operation_type): my_operation_type(o peration_type) {} aggregator_operation(e_op_type operation_type): my_operation_type(o peration_type) {}
 End of changes. 1 change blocks. 
0 lines changed or deleted 5 lines changed or added


 flow_graph.h   flow_graph.h 
skipping to change at line 43 skipping to change at line 43
#include "atomic.h" #include "atomic.h"
#include "spin_mutex.h" #include "spin_mutex.h"
#include "null_mutex.h" #include "null_mutex.h"
#include "spin_rw_mutex.h" #include "spin_rw_mutex.h"
#include "null_rw_mutex.h" #include "null_rw_mutex.h"
#include "task.h" #include "task.h"
#include "concurrent_vector.h" #include "concurrent_vector.h"
#include "internal/_aggregator_impl.h" #include "internal/_aggregator_impl.h"
// use the VC10 or gcc version of tuple if it is available. // use the VC10 or gcc version of tuple if it is available.
#if TBB_IMPLEMENT_CPP0X && (!defined(_MSC_VER) || _MSC_VER < 1600) #if __TBB_CPP11_TUPLE_PRESENT
#define TBB_PREVIEW_TUPLE 1 #include <tuple>
#include "compat/tuple"
#else #else
#include <tuple> #include "compat/tuple"
#endif #endif
#include<list> #include<list>
#include<queue> #include<queue>
/** @file /** @file
\brief The graph related classes and functions \brief The graph related classes and functions
There are some applications that best express dependencies as messages There are some applications that best express dependencies as messages
passed between nodes in a graph. These messages may contain data or passed between nodes in a graph. These messages may contain data or
skipping to change at line 71 skipping to change at line 70
*/ */
namespace tbb { namespace tbb {
namespace flow { namespace flow {
//! An enumeration the provides the two most common concurrency levels: unl imited and serial //! An enumeration the provides the two most common concurrency levels: unl imited and serial
enum concurrency { unlimited = 0, serial = 1 }; enum concurrency { unlimited = 0, serial = 1 };
namespace interface6 { namespace interface6 {
namespace internal {
template<typename T, typename M>
class successor_cache;
}
//! An empty class used for messages that mean "I'm done" //! An empty class used for messages that mean "I'm done"
class continue_msg {}; class continue_msg {};
template< typename T > class sender; template< typename T > class sender;
template< typename T > class receiver; template< typename T > class receiver;
class continue_receiver; class continue_receiver;
//! Pure virtual template class that defines a sender of messages of type T //! Pure virtual template class that defines a sender of messages of type T
template< typename T > template< typename T >
class sender { class sender {
skipping to change at line 109 skipping to change at line 113
//! Reserves an item in the sender //! Reserves an item in the sender
virtual bool try_reserve( T & ) { return false; } virtual bool try_reserve( T & ) { return false; }
//! Releases the reserved item //! Releases the reserved item
virtual bool try_release( ) { return false; } virtual bool try_release( ) { return false; }
//! Consumes the reserved item //! Consumes the reserved item
virtual bool try_consume( ) { return false; } virtual bool try_consume( ) { return false; }
}; };
template< typename T > class limiter_node; // needed for resetting decreme
nter
//! Pure virtual template class that defines a receiver of messages of type T //! Pure virtual template class that defines a receiver of messages of type T
template< typename T > template< typename T >
class receiver { class receiver {
public: public:
//! The input type of this receiver //! The input type of this receiver
typedef T input_type; typedef T input_type;
//! The predecessor type for this node //! The predecessor type for this node
typedef sender<T> predecessor_type; typedef sender<T> predecessor_type;
skipping to change at line 130 skipping to change at line 136
virtual ~receiver() {} virtual ~receiver() {}
//! Put an item to the receiver //! Put an item to the receiver
virtual bool try_put( const T& t ) = 0; virtual bool try_put( const T& t ) = 0;
//! Add a predecessor to the node //! Add a predecessor to the node
virtual bool register_predecessor( predecessor_type & ) { return false; } virtual bool register_predecessor( predecessor_type & ) { return false; }
//! Remove a predecessor from the node //! Remove a predecessor from the node
virtual bool remove_predecessor( predecessor_type & ) { return false; } virtual bool remove_predecessor( predecessor_type & ) { return false; }
protected:
//! put receiver back in initial state
template<typename U> friend class limiter_node;
virtual void reset_receiver() = 0;
template<typename TT, typename M>
friend class internal::successor_cache;
virtual bool is_continue_receiver() { return false; }
}; };
//! Base class for receivers of completion messages //! Base class for receivers of completion messages
/** These receivers automatically reset, but cannot be explicitly waited on */ /** These receivers automatically reset, but cannot be explicitly waited on */
class continue_receiver : public receiver< continue_msg > { class continue_receiver : public receiver< continue_msg > {
public: public:
//! The input type //! The input type
typedef continue_msg input_type; typedef continue_msg input_type;
skipping to change at line 195 skipping to change at line 209
} }
execute(); execute();
return true; return true;
} }
protected: protected:
spin_mutex my_mutex; spin_mutex my_mutex;
int my_predecessor_count; int my_predecessor_count;
int my_current_count; int my_current_count;
int my_initial_predecessor_count; int my_initial_predecessor_count;
// the friend declaration in the base class did not eliminate the "prot
ected class"
// error in gcc 4.1.2
template<typename U> friend class limiter_node;
/*override*/void reset_receiver() {
my_current_count = 0;
}
//! Does whatever should happen when the threshold is reached //! Does whatever should happen when the threshold is reached
/** This should be very fast or else spawn a task. This is /** This should be very fast or else spawn a task. This is
called while the sender is blocked in the try_put(). */ called while the sender is blocked in the try_put(). */
virtual void execute() = 0; virtual void execute() = 0;
template<typename TT, typename M>
friend class internal::successor_cache;
/*override*/ bool is_continue_receiver() { return true; }
}; };
#include "internal/_flow_graph_impl.h" #include "internal/_flow_graph_impl.h"
using namespace internal::graph_policy_namespace; using namespace internal::graph_policy_namespace;
class graph; class graph;
class graph_node; class graph_node;
template <typename GraphContainerType, typename GraphNodeType> template <typename GraphContainerType, typename GraphNodeType>
class graph_iterator { class graph_iterator {
skipping to change at line 390 skipping to change at line 413
#if TBB_USE_EXCEPTIONS #if TBB_USE_EXCEPTIONS
} }
catch(...) { catch(...) {
my_root_task->set_ref_count(1); my_root_task->set_ref_count(1);
my_context->reset(); my_context->reset();
caught_exception = true; caught_exception = true;
cancelled = true; cancelled = true;
throw; throw;
} }
#endif #endif
my_context->reset(); // consistent with behavior in catch()
my_root_task->set_ref_count(1); my_root_task->set_ref_count(1);
} }
} }
//! Returns the root task of the graph //! Returns the root task of the graph
task * root_task() { task * root_task() {
return my_root_task; return my_root_task;
} }
// ITERATORS // ITERATORS
skipping to change at line 425 skipping to change at line 449
const_iterator end() const { return const_iterator(this, false); } const_iterator end() const { return const_iterator(this, false); }
//! start const iterator //! start const iterator
const_iterator cbegin() const { return const_iterator(this, true); } const_iterator cbegin() const { return const_iterator(this, true); }
//! end const iterator //! end const iterator
const_iterator cend() const { return const_iterator(this, false); } const_iterator cend() const { return const_iterator(this, false); }
//! return status of graph execution //! return status of graph execution
bool is_cancelled() { return cancelled; } bool is_cancelled() { return cancelled; }
bool exception_thrown() { return caught_exception; } bool exception_thrown() { return caught_exception; }
// un-thread-safe state reset.
void reset();
private: private:
task *my_root_task; task *my_root_task;
task_group_context *my_context; task_group_context *my_context;
bool own_context; bool own_context;
bool cancelled; bool cancelled;
bool caught_exception; bool caught_exception;
graph_node *my_nodes, *my_nodes_last; graph_node *my_nodes, *my_nodes_last;
spin_mutex nodelist_mutex; spin_mutex nodelist_mutex;
skipping to change at line 478 skipping to change at line 505
protected: protected:
graph& my_graph; graph& my_graph;
graph_node *next, *prev; graph_node *next, *prev;
public: public:
graph_node(graph& g) : my_graph(g) { graph_node(graph& g) : my_graph(g) {
my_graph.register_node(this); my_graph.register_node(this);
} }
virtual ~graph_node() { virtual ~graph_node() {
my_graph.remove_node(this); my_graph.remove_node(this);
} }
protected:
virtual void reset() = 0;
}; };
inline void graph::register_node(graph_node *n) { inline void graph::register_node(graph_node *n) {
n->next = NULL; n->next = NULL;
{ {
spin_mutex::scoped_lock lock(nodelist_mutex); spin_mutex::scoped_lock lock(nodelist_mutex);
n->prev = my_nodes_last; n->prev = my_nodes_last;
if (my_nodes_last) my_nodes_last->next = n; if (my_nodes_last) my_nodes_last->next = n;
my_nodes_last = n; my_nodes_last = n;
if (!my_nodes) my_nodes = n; if (!my_nodes) my_nodes = n;
skipping to change at line 503 skipping to change at line 533
spin_mutex::scoped_lock lock(nodelist_mutex); spin_mutex::scoped_lock lock(nodelist_mutex);
__TBB_ASSERT(my_nodes && my_nodes_last, "graph::remove_node: Error: no registered nodes"); __TBB_ASSERT(my_nodes && my_nodes_last, "graph::remove_node: Error: no registered nodes");
if (n->prev) n->prev->next = n->next; if (n->prev) n->prev->next = n->next;
if (n->next) n->next->prev = n->prev; if (n->next) n->next->prev = n->prev;
if (my_nodes_last == n) my_nodes_last = n->prev; if (my_nodes_last == n) my_nodes_last = n->prev;
if (my_nodes == n) my_nodes = n->next; if (my_nodes == n) my_nodes = n->next;
} }
n->prev = n->next = NULL; n->prev = n->next = NULL;
} }
inline void graph::reset() {
// reset context
if(my_context) my_context->reset();
cancelled = false;
caught_exception = false;
// reset all the nodes comprising the graph
for(iterator ii = begin(); ii != end(); ++ii) {
graph_node *my_p = &(*ii);
my_p->reset();
}
}
#include "internal/_flow_graph_node_impl.h" #include "internal/_flow_graph_node_impl.h"
//! An executable node that acts as a source, i.e. it has no predecessors //! An executable node that acts as a source, i.e. it has no predecessors
template < typename Output > template < typename Output >
class source_node : public graph_node, public sender< Output > { class source_node : public graph_node, public sender< Output > {
using graph_node::my_graph; using graph_node::my_graph;
public: public:
//! The type of the output message, which is complete //! The type of the output message, which is complete
typedef Output output_type; typedef Output output_type;
skipping to change at line 564 skipping to change at line 606
//! Request an item from the node //! Request an item from the node
/*override */ bool try_get( output_type &v ) { /*override */ bool try_get( output_type &v ) {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
if ( my_reserved ) if ( my_reserved )
return false; return false;
if ( my_has_cached_item ) { if ( my_has_cached_item ) {
v = my_cached_item; v = my_cached_item;
my_has_cached_item = false; my_has_cached_item = false;
} else if ( (*my_body)(v) == false ) { return true;
return false;
} }
return true; return false;
} }
//! Reserves an item. //! Reserves an item.
/* override */ bool try_reserve( output_type &v ) { /* override */ bool try_reserve( output_type &v ) {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
if ( my_reserved ) { if ( my_reserved ) {
return false; return false;
} }
if ( !my_has_cached_item && (*my_body)(my_cached_item) )
my_has_cached_item = true;
if ( my_has_cached_item ) { if ( my_has_cached_item ) {
v = my_cached_item; v = my_cached_item;
my_reserved = true; my_reserved = true;
return true; return true;
} else { } else {
return false; return false;
} }
} }
//! Release a reserved item. //! Release a reserved item.
skipping to change at line 620 skipping to change at line 658
} }
//! Activates a node that was created in the inactive state //! Activates a node that was created in the inactive state
void activate() { void activate() {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
my_active = true; my_active = true;
if ( !my_successors.empty() ) if ( !my_successors.empty() )
spawn_put(); spawn_put();
} }
template<class Body>
Body copy_function_object() {
internal::source_body<output_type> &body_ref = *this->my_body;
return dynamic_cast< internal::source_body_leaf<output_type, Body>
& >(body_ref).get_body();
}
protected:
//! resets the node to its initial state
void reset() {
my_active = init_my_active;
my_reserved =false;
if(my_has_cached_item) {
my_has_cached_item = false;
}
}
private: private:
task *my_root_task; task *my_root_task;
spin_mutex my_mutex; spin_mutex my_mutex;
bool my_active; bool my_active;
bool init_my_active; bool init_my_active;
internal::source_body<output_type> *my_body; internal::source_body<output_type> *my_body;
internal::broadcast_cache< output_type > my_successors; internal::broadcast_cache< output_type > my_successors;
bool my_reserved; bool my_reserved;
bool my_has_cached_item; bool my_has_cached_item;
output_type my_cached_item; output_type my_cached_item;
friend class internal::source_task< source_node< output_type > >; friend class internal::source_task< source_node< output_type > >;
// used by apply_body, can invoke body of node.
bool try_reserve_apply_body(output_type &v) {
spin_mutex::scoped_lock lock(my_mutex);
if ( my_reserved ) {
return false;
}
if ( !my_has_cached_item && (*my_body)(my_cached_item) )
my_has_cached_item = true;
if ( my_has_cached_item ) {
v = my_cached_item;
my_reserved = true;
return true;
} else {
return false;
}
}
//! Applies the body //! Applies the body
/* override */ void apply_body( ) { /* override */ void apply_body( ) {
output_type v; output_type v;
if ( try_reserve(v) == false ) if ( !try_reserve_apply_body(v) )
return; return;
if ( my_successors.try_put( v ) ) if ( my_successors.try_put( v ) )
try_consume(); try_consume();
else else
try_release(); try_release();
} }
//! Spawns a task that applies the body //! Spawns a task that applies the body
/* override */ void spawn_put( ) { /* override */ void spawn_put( ) {
task::enqueue( * new ( task::allocate_additional_child_of( *my_root _task ) ) task::enqueue( * new ( task::allocate_additional_child_of( *my_root _task ) )
internal::source_task< source_node< output_type > >( *this ) ); internal::source_task< source_node< output_type > >( *this ) );
} }
}; }; // source_node
//! Implements a function node that supports Input -> Output //! Implements a function node that supports Input -> Output
template < typename Input, typename Output = continue_msg, graph_buffer_pol icy = queueing, typename Allocator=cache_aligned_allocator<Input> > template < typename Input, typename Output = continue_msg, graph_buffer_pol icy = queueing, typename Allocator=cache_aligned_allocator<Input> >
class function_node : public graph_node, public internal::function_input<In put,Output,Allocator>, public internal::function_output<Output> { class function_node : public graph_node, public internal::function_input<In put,Output,Allocator>, public internal::function_output<Output> {
using graph_node::my_graph; using graph_node::my_graph;
public: public:
typedef Input input_type; typedef Input input_type;
typedef Output output_type; typedef Output output_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
skipping to change at line 679 skipping to change at line 754
//! Copy constructor //! Copy constructor
function_node( const function_node& src ) : function_node( const function_node& src ) :
graph_node(src.my_graph), internal::function_input<input_type,outpu t_type,Allocator>( src ), graph_node(src.my_graph), internal::function_input<input_type,outpu t_type,Allocator>( src ),
fOutput_type() fOutput_type()
{} {}
bool try_put(const input_type &i) { return fInput_type::try_put(i); } bool try_put(const input_type &i) { return fInput_type::try_put(i); }
protected: protected:
// override of graph_node's reset.
/*override*/void reset() {fInput_type::reset_function_input(); }
/* override */ internal::broadcast_cache<output_type> &successors () { return fOutput_type::my_successors; } /* override */ internal::broadcast_cache<output_type> &successors () { return fOutput_type::my_successors; }
}; };
//! Implements a function node that supports Input -> Output //! Implements a function node that supports Input -> Output
template < typename Input, typename Output, typename Allocator > template < typename Input, typename Output, typename Allocator >
class function_node<Input,Output,queueing,Allocator> : public graph_node, p ublic internal::function_input<Input,Output,Allocator>, public internal::fu nction_output<Output> { class function_node<Input,Output,queueing,Allocator> : public graph_node, p ublic internal::function_input<Input,Output,Allocator>, public internal::fu nction_output<Output> {
using graph_node::my_graph; using graph_node::my_graph;
public: public:
typedef Input input_type; typedef Input input_type;
typedef Output output_type; typedef Output output_type;
skipping to change at line 709 skipping to change at line 788
{} {}
//! Copy constructor //! Copy constructor
function_node( const function_node& src ) : function_node( const function_node& src ) :
graph_node(src.my_graph), fInput_type( src, new queue_type() ), fOu tput_type() graph_node(src.my_graph), fInput_type( src, new queue_type() ), fOu tput_type()
{} {}
bool try_put(const input_type &i) { return fInput_type::try_put(i); } bool try_put(const input_type &i) { return fInput_type::try_put(i); }
protected: protected:
/*override*/void reset() { fInput_type::reset_function_input(); }
/* override */ internal::broadcast_cache<output_type> &successors () { return fOutput_type::my_successors; } /* override */ internal::broadcast_cache<output_type> &successors () { return fOutput_type::my_successors; }
}; };
#include "tbb/internal/_flow_graph_types_impl.h" #include "tbb/internal/_flow_graph_types_impl.h"
//! implements a function node that supports Input -> (set of outputs) //! implements a function node that supports Input -> (set of outputs)
// Output is a tuple of output types. // Output is a tuple of output types.
template < typename Input, typename Output, graph_buffer_policy = queueing, typename Allocator=cache_aligned_allocator<Input> > template < typename Input, typename Output, graph_buffer_policy = queueing, typename Allocator=cache_aligned_allocator<Input> >
class multifunction_node : class multifunction_node :
public graph_node, public graph_node,
skipping to change at line 747 skipping to change at line 829
typedef typename internal::function_input_queue<input_type,Allocator> q ueue_type; typedef typename internal::function_input_queue<input_type,Allocator> q ueue_type;
public: public:
template<typename Body> template<typename Body>
multifunction_node( graph &g, size_t concurrency, Body body ) : multifunction_node( graph &g, size_t concurrency, Body body ) :
graph_node(g), base_type(g,concurrency, body) graph_node(g), base_type(g,concurrency, body)
{} {}
multifunction_node( const multifunction_node &other) : multifunction_node( const multifunction_node &other) :
graph_node(other.my_graph), base_type(other) graph_node(other.my_graph), base_type(other)
{} {}
// all the guts are in multifunction_input... // all the guts are in multifunction_input...
protected:
/*override*/void reset() { base_type::reset(); }
}; // multifunction_node }; // multifunction_node
template < typename Input, typename Output, typename Allocator > template < typename Input, typename Output, typename Allocator >
class multifunction_node<Input,Output,queueing,Allocator> : public graph_no de, public internal::multifunction_input<Input, class multifunction_node<Input,Output,queueing,Allocator> : public graph_no de, public internal::multifunction_input<Input,
typename internal::wrap_tuple_elements<std::tuple_size<Output>::value, internal::function_output, Output>::type, Allocator> { typename internal::wrap_tuple_elements<std::tuple_size<Output>::value, internal::function_output, Output>::type, Allocator> {
using graph_node::my_graph; using graph_node::my_graph;
static const int N = std::tuple_size<Output>::value; static const int N = std::tuple_size<Output>::value;
public: public:
typedef Input input_type; typedef Input input_type;
typedef typename internal::wrap_tuple_elements<N, internal::function_ou tput, Output>::type output_ports_type; typedef typename internal::wrap_tuple_elements<N, internal::function_ou tput, Output>::type output_ports_type;
skipping to change at line 768 skipping to change at line 852
typedef typename internal::multifunction_input<input_type, output_ports _type, Allocator> base_type; typedef typename internal::multifunction_input<input_type, output_ports _type, Allocator> base_type;
typedef typename internal::function_input_queue<input_type,Allocator> q ueue_type; typedef typename internal::function_input_queue<input_type,Allocator> q ueue_type;
public: public:
template<typename Body> template<typename Body>
multifunction_node( graph &g, size_t concurrency, Body body) : multifunction_node( graph &g, size_t concurrency, Body body) :
graph_node(g), base_type(g,concurrency, body, new queue_type()) graph_node(g), base_type(g,concurrency, body, new queue_type())
{} {}
multifunction_node( const multifunction_node &other) : multifunction_node( const multifunction_node &other) :
graph_node(other.my_graph), base_type(other, new queue_type()) graph_node(other.my_graph), base_type(other, new queue_type())
{} {}
// all the guts are in multifunction_input...
protected:
/*override*/void reset() { base_type::reset(); }
}; // multifunction_node }; // multifunction_node
//! split_node: accepts a tuple as input, forwards each element of the tupl e to its //! split_node: accepts a tuple as input, forwards each element of the tupl e to its
// successors. The node has unlimited concurrency, so though it is marked as // successors. The node has unlimited concurrency, so though it is marked as
// "rejecting" it does not reject inputs. // "rejecting" it does not reject inputs.
template<typename TupleType, typename Allocator=cache_aligned_allocator<Tup leType> > template<typename TupleType, typename Allocator=cache_aligned_allocator<Tup leType> >
class split_node : public multifunction_node<TupleType, TupleType, rejectin g, Allocator> { class split_node : public multifunction_node<TupleType, TupleType, rejectin g, Allocator> {
static const int N = std::tuple_size<TupleType>::value; static const int N = std::tuple_size<TupleType>::value;
typedef multifunction_node<TupleType,TupleType,rejecting,Allocator> bas e_type; typedef multifunction_node<TupleType,TupleType,rejecting,Allocator> bas e_type;
public: public:
skipping to change at line 824 skipping to change at line 911
//! Copy constructor //! Copy constructor
continue_node( const continue_node& src ) : continue_node( const continue_node& src ) :
graph_node(src.my_graph), internal::continue_input<output_type>(src ), graph_node(src.my_graph), internal::continue_input<output_type>(src ),
internal::function_output<Output>() internal::function_output<Output>()
{} {}
bool try_put(const input_type &i) { return internal::continue_input<Out put>::try_put(i); } bool try_put(const input_type &i) { return internal::continue_input<Out put>::try_put(i); }
protected: protected:
/*override*/void reset() { internal::continue_input<Output>::reset_rece
iver(); }
/* override */ internal::broadcast_cache<output_type> &successors () { return fOutput_type::my_successors; } /* override */ internal::broadcast_cache<output_type> &successors () { return fOutput_type::my_successors; }
}; };
template< typename T > template< typename T >
class overwrite_node : public graph_node, public receiver<T>, public sender <T> { class overwrite_node : public graph_node, public receiver<T>, public sender <T> {
using graph_node::my_graph; using graph_node::my_graph;
public: public:
typedef T input_type; typedef T input_type;
typedef T output_type; typedef T output_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
skipping to change at line 903 skipping to change at line 992
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
return my_buffer_is_valid; return my_buffer_is_valid;
} }
void clear() { void clear() {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
my_buffer_is_valid = false; my_buffer_is_valid = false;
} }
protected: protected:
/*override*/void reset() { my_buffer_is_valid = false; }
spin_mutex my_mutex; spin_mutex my_mutex;
internal::broadcast_cache< T, null_rw_mutex > my_successors; internal::broadcast_cache< T, null_rw_mutex > my_successors;
T my_buffer; T my_buffer;
bool my_buffer_is_valid; bool my_buffer_is_valid;
/*override*/void reset_receiver() {}
}; };
template< typename T > template< typename T >
class write_once_node : public overwrite_node<T> { class write_once_node : public overwrite_node<T> {
public: public:
typedef T input_type; typedef T input_type;
typedef T output_type; typedef T output_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
skipping to change at line 974 skipping to change at line 1067
//! Removes s as a successor //! Removes s as a successor
virtual bool remove_successor( receiver<T> &r ) { virtual bool remove_successor( receiver<T> &r ) {
my_successors.remove_successor( r ); my_successors.remove_successor( r );
return true; return true;
} }
/* override */ bool try_put( const T &t ) { /* override */ bool try_put( const T &t ) {
my_successors.try_put(t); my_successors.try_put(t);
return true; return true;
} }
protected:
/*override*/void reset() {}
/*override*/void reset_receiver() {}
}; };
#include "internal/_flow_graph_item_buffer_impl.h" #include "internal/_flow_graph_item_buffer_impl.h"
//! Forwards messages in arbitrary order //! Forwards messages in arbitrary order
template <typename T, typename A=cache_aligned_allocator<T> > template <typename T, typename A=cache_aligned_allocator<T> >
class buffer_node : public graph_node, public reservable_item_buffer<T, A>, public receiver<T>, public sender<T> { class buffer_node : public graph_node, public reservable_item_buffer<T, A>, public receiver<T>, public sender<T> {
using graph_node::my_graph; using graph_node::my_graph;
public: public:
typedef T input_type; typedef T input_type;
skipping to change at line 1201 skipping to change at line 1297
return true; return true;
} }
//! Receive an item //! Receive an item
/** true is always returned */ /** true is always returned */
/* override */ bool try_put(const T &t) { /* override */ bool try_put(const T &t) {
buffer_operation op_data(t, put_item); buffer_operation op_data(t, put_item);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return true; return true;
} }
protected:
/*override*/void reset() {
reservable_item_buffer<T, A>::reset();
forwarder_busy = false;
}
/*override*/void reset_receiver() {
// nothing to do; no predecesor_cache
}
}; };
//! Forwards messages in FIFO order //! Forwards messages in FIFO order
template <typename T, typename A=cache_aligned_allocator<T> > template <typename T, typename A=cache_aligned_allocator<T> >
class queue_node : public buffer_node<T, A> { class queue_node : public buffer_node<T, A> {
protected: protected:
typedef typename buffer_node<T, A>::size_type size_type; typedef typename buffer_node<T, A>::size_type size_type;
typedef typename buffer_node<T, A>::buffer_operation queue_operation; typedef typename buffer_node<T, A>::buffer_operation queue_operation;
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
skipping to change at line 1324 skipping to change at line 1432
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
}; };
//! Forwards messages in priority order //! Forwards messages in priority order
template< typename T, typename Compare = std::less<T>, typename A=cache_ali gned_allocator<T> > template< typename T, typename Compare = std::less<T>, typename A=cache_ali gned_allocator<T> >
class priority_queue_node : public buffer_node<T, A> { class priority_queue_node : public buffer_node<T, A> {
public: public:
typedef T input_type; typedef T input_type;
typedef T output_type; typedef T output_type;
typedef buffer_node<T,A> base_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
//! Constructor //! Constructor
priority_queue_node( graph &g ) : buffer_node<T, A>(g), mark(0) {} priority_queue_node( graph &g ) : buffer_node<T, A>(g), mark(0) {}
//! Copy constructor //! Copy constructor
priority_queue_node( const priority_queue_node &src ) : buffer_node<T, A>(src), mark(0) {} priority_queue_node( const priority_queue_node &src ) : buffer_node<T, A>(src), mark(0) {}
protected: protected:
/*override*/void reset() {
mark = 0;
base_type::reset();
}
typedef typename buffer_node<T, A>::size_type size_type; typedef typename buffer_node<T, A>::size_type size_type;
typedef typename buffer_node<T, A>::item_type item_type; typedef typename buffer_node<T, A>::item_type item_type;
typedef typename buffer_node<T, A>::buffer_operation prio_operation; typedef typename buffer_node<T, A>::buffer_operation prio_operation;
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
/* override */ void handle_operations(prio_operation *op_list) { /* override */ void handle_operations(prio_operation *op_list) {
prio_operation *tmp /*, *pop_list*/ ; prio_operation *tmp /*, *pop_list*/ ;
bool try_forwarding=false; bool try_forwarding=false;
while (op_list) { while (op_list) {
skipping to change at line 1630 skipping to change at line 1745
task::enqueue( * new ( task::allocate_additional_child_of( *my_ root_task ) ) task::enqueue( * new ( task::allocate_additional_child_of( *my_ root_task ) )
internal::forward_task< limiter_node<T> >( *this ) ); internal::forward_task< limiter_node<T> >( *this ) );
return true; return true;
} }
//! Removes src from the list of cached predecessors. //! Removes src from the list of cached predecessors.
/* override */ bool remove_predecessor( predecessor_type &src ) { /* override */ bool remove_predecessor( predecessor_type &src ) {
my_predecessors.remove( src ); my_predecessors.remove( src );
return true; return true;
} }
protected:
/*override*/void reset() {
my_count = 0;
my_predecessors.reset();
decrement.reset_receiver();
}
/*override*/void reset_receiver() { my_predecessors.reset(); }
}; };
#include "internal/_flow_graph_join_impl.h" #include "internal/_flow_graph_join_impl.h"
using internal::reserving_port; using internal::reserving_port;
using internal::queueing_port; using internal::queueing_port;
using internal::tag_matching_port; using internal::tag_matching_port;
using internal::input_port; using internal::input_port;
using internal::tag_value; using internal::tag_value;
using internal::NO_TAG; using internal::NO_TAG;
 End of changes. 30 change blocks. 
12 lines changed or deleted 141 lines changed or added


 parallel_reduce.h   parallel_reduce.h 
skipping to change at line 177 skipping to change at line 177
} else __TBB_ASSERT(my_context==root_task,NULL);// because left lea f spawns right leafs without recycling } else __TBB_ASSERT(my_context==root_task,NULL);// because left lea f spawns right leafs without recycling
my_partition.execute(*this, my_range); my_partition.execute(*this, my_range);
if( my_context==left_child ) { if( my_context==left_child ) {
finish_type* parent_ptr = static_cast<finish_type*>(parent()); finish_type* parent_ptr = static_cast<finish_type*>(parent());
__TBB_ASSERT(my_body!=parent_ptr->zombie_space.begin(),NULL); __TBB_ASSERT(my_body!=parent_ptr->zombie_space.begin(),NULL);
itt_store_word_with_release(parent_ptr->my_body, my_body ); itt_store_word_with_release(parent_ptr->my_body, my_body );
} }
return NULL; return NULL;
} }
#if TBB_PREVIEW_DETERMINISTIC_REDUCE
//! Task type used to combine the partial results of parallel_determini stic_reduce. //! Task type used to combine the partial results of parallel_determini stic_reduce.
/** @ingroup algorithms */ /** @ingroup algorithms */
template<typename Body> template<typename Body>
class finish_deterministic_reduce: public task { class finish_deterministic_reduce: public task {
Body &my_left_body; Body &my_left_body;
Body my_right_body; Body my_right_body;
finish_deterministic_reduce( Body &body ) : finish_deterministic_reduce( Body &body ) :
my_left_body( body ), my_left_body( body ),
my_right_body( body, split() ) my_right_body( body, split() )
skipping to change at line 256 skipping to change at line 255
return NULL; return NULL;
} else { } else {
finish_type& c = *new( allocate_continuation() ) finish_type( m y_body ); finish_type& c = *new( allocate_continuation() ) finish_type( m y_body );
recycle_as_child_of(c); recycle_as_child_of(c);
c.set_ref_count(2); c.set_ref_count(2);
start_deterministic_reduce& b = *new( c.allocate_child() ) star t_deterministic_reduce( *this, c ); start_deterministic_reduce& b = *new( c.allocate_child() ) star t_deterministic_reduce( *this, c );
task::spawn(b); task::spawn(b);
return this; return this;
} }
} }
#endif /* TBB_PREVIEW_DETERMINISTIC_REDUCE */
} // namespace internal } // namespace internal
//! @endcond //! @endcond
} //namespace interfaceX } //namespace interfaceX
//! @cond INTERNAL //! @cond INTERNAL
namespace internal { namespace internal {
using interface6::internal::start_reduce; using interface6::internal::start_reduce;
#if TBB_PREVIEW_DETERMINISTIC_REDUCE
using interface6::internal::start_deterministic_reduce; using interface6::internal::start_deterministic_reduce;
#endif
//! Auxiliary class for parallel_reduce; for internal use only. //! Auxiliary class for parallel_reduce; for internal use only.
/** The adaptor class that implements \ref parallel_reduce_body_req "pa rallel_reduce Body" /** The adaptor class that implements \ref parallel_reduce_body_req "pa rallel_reduce Body"
using given \ref parallel_reduce_lambda_req "anonymous function obj ects". using given \ref parallel_reduce_lambda_req "anonymous function obj ects".
**/ **/
/** @ingroup algorithms */ /** @ingroup algorithms */
template<typename Range, typename Value, typename RealBody, typename Re duction> template<typename Range, typename Value, typename RealBody, typename Re duction>
class lambda_reduce_body { class lambda_reduce_body {
//FIXME: decide if my_real_body, my_reduction, and identity_element should be copied or referenced //FIXME: decide if my_real_body, my_reduction, and identity_element should be copied or referenced
// (might require some performance measurements) // (might require some performance measurements)
skipping to change at line 469 skipping to change at line 465
template<typename Range, typename Value, typename RealBody, typename Reduct ion> template<typename Range, typename Value, typename RealBody, typename Reduct ion>
Value parallel_reduce( const Range& range, const Value& identity, const Rea lBody& real_body, const Reduction& reduction, Value parallel_reduce( const Range& range, const Value& identity, const Rea lBody& real_body, const Reduction& reduction,
affinity_partitioner& partitioner, task_group_contex t& context ) { affinity_partitioner& partitioner, task_group_contex t& context ) {
internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(ident ity, real_body, reduction); internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(ident ity, real_body, reduction);
internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,R ealBody,Reduction>,affinity_partitioner> internal::start_reduce<Range,internal::lambda_reduce_body<Range,Value,R ealBody,Reduction>,affinity_partitioner>
::run( range, body, partitioner, co ntext ); ::run( range, body, partitioner, co ntext );
return body.result(); return body.result();
} }
#endif /* __TBB_TASK_GROUP_CONTEXT */ #endif /* __TBB_TASK_GROUP_CONTEXT */
#if TBB_PREVIEW_DETERMINISTIC_REDUCE
//! Parallel iteration with deterministic reduction and default partitioner . //! Parallel iteration with deterministic reduction and default partitioner .
/** @ingroup algorithms **/ /** @ingroup algorithms **/
template<typename Range, typename Body> template<typename Range, typename Body>
void parallel_deterministic_reduce( const Range& range, Body& body ) { void parallel_deterministic_reduce( const Range& range, Body& body ) {
internal::start_deterministic_reduce<Range,Body>::run( range, body ); internal::start_deterministic_reduce<Range,Body>::run( range, body );
} }
#if __TBB_TASK_GROUP_CONTEXT #if __TBB_TASK_GROUP_CONTEXT
//! Parallel iteration with deterministic reduction, simple partitioner and user-supplied context. //! Parallel iteration with deterministic reduction, simple partitioner and user-supplied context.
/** @ingroup algorithms **/ /** @ingroup algorithms **/
skipping to change at line 511 skipping to change at line 506
/** @ingroup algorithms **/ /** @ingroup algorithms **/
template<typename Range, typename Value, typename RealBody, typename Reduct ion> template<typename Range, typename Value, typename RealBody, typename Reduct ion>
Value parallel_deterministic_reduce( const Range& range, const Value& ident ity, const RealBody& real_body, const Reduction& reduction, Value parallel_deterministic_reduce( const Range& range, const Value& ident ity, const RealBody& real_body, const Reduction& reduction,
task_group_context& context ) { task_group_context& context ) {
internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(ident ity, real_body, reduction); internal::lambda_reduce_body<Range,Value,RealBody,Reduction> body(ident ity, real_body, reduction);
internal::start_deterministic_reduce<Range,internal::lambda_reduce_body <Range,Value,RealBody,Reduction> > internal::start_deterministic_reduce<Range,internal::lambda_reduce_body <Range,Value,RealBody,Reduction> >
::run( range, body, context ); ::run( range, body, context );
return body.result(); return body.result();
} }
#endif /* __TBB_TASK_GROUP_CONTEXT */ #endif /* __TBB_TASK_GROUP_CONTEXT */
#endif /* TBB_PREVIEW_DETERMINISTIC_REDUCE */
//@} //@}
} // namespace tbb } // namespace tbb
#endif /* __TBB_parallel_reduce_H */ #endif /* __TBB_parallel_reduce_H */
 End of changes. 6 change blocks. 
6 lines changed or deleted 0 lines changed or added


 pipeline.h   pipeline.h 
skipping to change at line 430 skipping to change at line 430
typedef token_helper<U,is_large_object<U>::value > u_helper; typedef token_helper<U,is_large_object<U>::value > u_helper;
typedef typename u_helper::pointer u_pointer; typedef typename u_helper::pointer u_pointer;
/*override*/ void* operator()(void* input) { /*override*/ void* operator()(void* input) {
t_pointer temp_input = t_helper::cast_from_void_ptr(input); t_pointer temp_input = t_helper::cast_from_void_ptr(input);
u_pointer output_u = u_helper::create_token(my_body(t_helper::token (temp_input))); u_pointer output_u = u_helper::create_token(my_body(t_helper::token (temp_input)));
t_helper::destroy_token(temp_input); t_helper::destroy_token(temp_input);
return u_helper::cast_to_void_ptr(output_u); return u_helper::cast_to_void_ptr(output_u);
} }
/*override*/ void finalize(void * input) {
t_pointer temp_input = t_helper::cast_from_void_ptr(input);
t_helper::destroy_token(temp_input);
}
public: public:
concrete_filter(tbb::filter::mode filter_mode, const Body& body) : filt er(filter_mode), my_body(body) {} concrete_filter(tbb::filter::mode filter_mode, const Body& body) : filt er(filter_mode), my_body(body) {}
}; };
// input // input
template<typename U, typename Body> template<typename U, typename Body>
class concrete_filter<void,U,Body>: public filter { class concrete_filter<void,U,Body>: public filter {
const Body& my_body; const Body& my_body;
typedef token_helper<U, is_large_object<U>::value > u_helper; typedef token_helper<U, is_large_object<U>::value > u_helper;
typedef typename u_helper::pointer u_pointer; typedef typename u_helper::pointer u_pointer;
skipping to change at line 471 skipping to change at line 476
const Body& my_body; const Body& my_body;
typedef token_helper<T, is_large_object<T>::value > t_helper; typedef token_helper<T, is_large_object<T>::value > t_helper;
typedef typename t_helper::pointer t_pointer; typedef typename t_helper::pointer t_pointer;
/*override*/ void* operator()(void* input) { /*override*/ void* operator()(void* input) {
t_pointer temp_input = t_helper::cast_from_void_ptr(input); t_pointer temp_input = t_helper::cast_from_void_ptr(input);
my_body(t_helper::token(temp_input)); my_body(t_helper::token(temp_input));
t_helper::destroy_token(temp_input); t_helper::destroy_token(temp_input);
return NULL; return NULL;
} }
/*override*/ void finalize(void* input) {
t_pointer temp_input = t_helper::cast_from_void_ptr(input);
t_helper::destroy_token(temp_input);
}
public: public:
concrete_filter(tbb::filter::mode filter_mode, const Body& body) : filt er(filter_mode), my_body(body) {} concrete_filter(tbb::filter::mode filter_mode, const Body& body) : filt er(filter_mode), my_body(body) {}
}; };
template<typename Body> template<typename Body>
class concrete_filter<void,void,Body>: public filter { class concrete_filter<void,void,Body>: public filter {
const Body& my_body; const Body& my_body;
/** Override privately because it is always called virtually */ /** Override privately because it is always called virtually */
/*override*/ void* operator()(void*) { /*override*/ void* operator()(void*) {
 End of changes. 2 change blocks. 
0 lines changed or deleted 10 lines changed or added


 spin_mutex.h   spin_mutex.h 
skipping to change at line 67 skipping to change at line 67
#endif #endif
} }
//! Represents acquisition of a mutex. //! Represents acquisition of a mutex.
class scoped_lock : internal::no_copy { class scoped_lock : internal::no_copy {
private: private:
//! Points to currently held mutex, or NULL if no lock is held. //! Points to currently held mutex, or NULL if no lock is held.
spin_mutex* my_mutex; spin_mutex* my_mutex;
//! Value to store into spin_mutex::flag to unlock the mutex. //! Value to store into spin_mutex::flag to unlock the mutex.
/** This variable is no longer used. Instead, 0 and 1 are used to
represent that the lock is free and acquired, respectively.
We keep the member variable here to ensure backward compatibili
ty */
__TBB_Flag my_unlock_value; __TBB_Flag my_unlock_value;
//! Like acquire, but with ITT instrumentation. //! Like acquire, but with ITT instrumentation.
void __TBB_EXPORTED_METHOD internal_acquire( spin_mutex& m ); void __TBB_EXPORTED_METHOD internal_acquire( spin_mutex& m );
//! Like try_acquire, but with ITT instrumentation. //! Like try_acquire, but with ITT instrumentation.
bool __TBB_EXPORTED_METHOD internal_try_acquire( spin_mutex& m ); bool __TBB_EXPORTED_METHOD internal_try_acquire( spin_mutex& m );
//! Like release, but with ITT instrumentation. //! Like release, but with ITT instrumentation.
void __TBB_EXPORTED_METHOD internal_release(); void __TBB_EXPORTED_METHOD internal_release();
friend class spin_mutex; friend class spin_mutex;
public: public:
//! Construct without acquiring a mutex. //! Construct without acquiring a mutex.
scoped_lock() : my_mutex(NULL), my_unlock_value(0) {} scoped_lock() : my_mutex(NULL), my_unlock_value(0) {}
//! Construct and acquire lock on a mutex. //! Construct and acquire lock on a mutex.
scoped_lock( spin_mutex& m ) { scoped_lock( spin_mutex& m ) : my_unlock_value(0) {
#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
my_mutex=NULL; my_mutex=NULL;
internal_acquire(m); internal_acquire(m);
#else #else
my_unlock_value = __TBB_LockByte(m.flag); __TBB_LockByte(m.flag);
my_mutex=&m; my_mutex=&m;
#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT*/ #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT*/
} }
//! Acquire lock. //! Acquire lock.
void acquire( spin_mutex& m ) { void acquire( spin_mutex& m ) {
#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
internal_acquire(m); internal_acquire(m);
#else #else
my_unlock_value = __TBB_LockByte(m.flag); __TBB_LockByte(m.flag);
my_mutex = &m; my_mutex = &m;
#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT*/ #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT*/
} }
//! Try acquiring lock (non-blocking) //! Try acquiring lock (non-blocking)
/** Return true if lock acquired; false otherwise. */ /** Return true if lock acquired; false otherwise. */
bool try_acquire( spin_mutex& m ) { bool try_acquire( spin_mutex& m ) {
#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
return internal_try_acquire(m); return internal_try_acquire(m);
#else #else
bool result = __TBB_TryLockByte(m.flag); bool result = __TBB_TryLockByte(m.flag);
if( result ) { if( result )
my_unlock_value = 0;
my_mutex = &m; my_mutex = &m;
}
return result; return result;
#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT*/ #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT*/
} }
//! Release lock //! Release lock
void release() { void release() {
#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
internal_release(); internal_release();
#else #else
__TBB_UnlockByte(my_mutex->flag, my_unlock_value); __TBB_UnlockByte(my_mutex->flag, 0);
my_mutex = NULL; my_mutex = NULL;
#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */ #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
} }
//! Destroy lock. If holding a lock, releases the lock first. //! Destroy lock. If holding a lock, releases the lock first.
~scoped_lock() { ~scoped_lock() {
if( my_mutex ) { if( my_mutex ) {
#if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT #if TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT
internal_release(); internal_release();
#else #else
__TBB_UnlockByte(my_mutex->flag, my_unlock_value); __TBB_UnlockByte(my_mutex->flag, 0);
#endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */ #endif /* TBB_USE_THREADING_TOOLS||TBB_USE_ASSERT */
} }
} }
}; };
void __TBB_EXPORTED_METHOD internal_construct(); void __TBB_EXPORTED_METHOD internal_construct();
// Mutex traits // Mutex traits
static const bool is_rw_mutex = false; static const bool is_rw_mutex = false;
static const bool is_recursive_mutex = false; static const bool is_recursive_mutex = false;
skipping to change at line 178 skipping to change at line 179
return __TBB_TryLockByte(flag); return __TBB_TryLockByte(flag);
#endif /* TBB_USE_THREADING_TOOLS*/ #endif /* TBB_USE_THREADING_TOOLS*/
} }
//! Release lock //! Release lock
void unlock() { void unlock() {
#if TBB_USE_THREADING_TOOLS #if TBB_USE_THREADING_TOOLS
aligned_space<scoped_lock,1> tmp; aligned_space<scoped_lock,1> tmp;
scoped_lock& s = *tmp.begin(); scoped_lock& s = *tmp.begin();
s.my_mutex = this; s.my_mutex = this;
s.my_unlock_value = 0;
s.internal_release(); s.internal_release();
#else #else
__TBB_store_with_release(flag, 0); __TBB_store_with_release(flag, 0);
#endif /* TBB_USE_THREADING_TOOLS */ #endif /* TBB_USE_THREADING_TOOLS */
} }
friend class scoped_lock; friend class scoped_lock;
}; };
__TBB_DEFINE_PROFILING_SET_NAME(spin_mutex) __TBB_DEFINE_PROFILING_SET_NAME(spin_mutex)
 End of changes. 9 change blocks. 
9 lines changed or deleted 10 lines changed or added


 task_scheduler_observer.h   task_scheduler_observer.h 
skipping to change at line 33 skipping to change at line 33
file does not by itself cause the resulting executable to be covered by file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered b y invalidate any other reasons why the executable file might be covered b y
the GNU General Public License. the GNU General Public License.
*/ */
#ifndef __TBB_task_scheduler_observer_H #ifndef __TBB_task_scheduler_observer_H
#define __TBB_task_scheduler_observer_H #define __TBB_task_scheduler_observer_H
#include "atomic.h" #include "atomic.h"
#if __TBB_TASK_ARENA
#include "task_arena.h"
#endif //__TBB_TASK_ARENA
#if __TBB_SCHEDULER_OBSERVER #if __TBB_SCHEDULER_OBSERVER
namespace tbb { namespace tbb {
namespace interface6 {
class task_scheduler_observer;
}
namespace internal { namespace internal {
class observer_proxy; class observer_proxy;
class observer_list;
class task_scheduler_observer_v3 { class task_scheduler_observer_v3 {
friend class observer_proxy; friend class observer_proxy;
friend class observer_list;
friend class interface6::task_scheduler_observer;
//! Pointer to the proxy holding this observer.
/** Observers are proxied by the scheduler to maintain persistent lists
of them. **/
observer_proxy* my_proxy; observer_proxy* my_proxy;
//! Counter preventing the observer from being destroyed while in use b
y the scheduler.
/** Valid only when observation is on. **/
atomic<intptr_t> my_busy_count; atomic<intptr_t> my_busy_count;
public: public:
//! Enable or disable observation //! Enable or disable observation
/** For local observers the method can be used only when the current th
read
has the task scheduler initialized or is attached to an arena.
Repeated calls with the same state are no-ops. **/
void __TBB_EXPORTED_METHOD observe( bool state=true ); void __TBB_EXPORTED_METHOD observe( bool state=true );
//! True if observation is enables; false otherwise. //! Returns true if observation is enabled, false otherwise.
bool is_observing() const {return my_proxy!=NULL;} bool is_observing() const {return my_proxy!=NULL;}
//! Construct observer with observation disabled. //! Construct observer with observation disabled.
task_scheduler_observer_v3() : my_proxy(NULL) {my_busy_count=0;} task_scheduler_observer_v3() : my_proxy(NULL) { my_busy_count.store<rel
axed>(0); }
//! Entry notification
/** Invoked from inside observe(true) call and whenever a worker enters
the arena
this observer is associated with. If a thread is already in the are
na when
the observer is activated, the entry notification is called before
it
executes the first stolen task.
//! Called by thread before first steal since observation became enable Obsolete semantics. For global observers it is called by a thread b
d efore
the first steal since observation became enabled. **/
virtual void on_scheduler_entry( bool /*is_worker*/ ) {} virtual void on_scheduler_entry( bool /*is_worker*/ ) {}
//! Called by thread when it no longer takes part in task stealing. //! Exit notification
/** Invoked from inside observe(false) call and whenever a worker leave
s the
arena this observer is associated with.
Obsolete semantics. For global observers it is called by a thread b
efore
the first steal since observation became enabled. **/
virtual void on_scheduler_exit( bool /*is_worker*/ ) {} virtual void on_scheduler_exit( bool /*is_worker*/ ) {}
//! Destructor //! Destructor automatically switches observation off if it is enabled.
virtual ~task_scheduler_observer_v3() {observe(false);} virtual ~task_scheduler_observer_v3() { if(my_proxy) observe(false);}
}; };
} // namespace internal } // namespace internal
typedef internal::task_scheduler_observer_v3 task_scheduler_observer; #if TBB_PREVIEW_LOCAL_OBSERVER
namespace interface6 {
class task_scheduler_observer : public internal::task_scheduler_observer_v3
{
friend class internal::task_scheduler_observer_v3;
friend class internal::observer_proxy;
friend class internal::observer_list;
/** Negative numbers with the largest absolute value to minimize probab
ility
of coincidence in case of a bug in busy count usage. **/
// TODO: take more high bits for version number
static const intptr_t v6_trait = (intptr_t)((~(uintptr_t)0 >> 1) + 1);
//! contains task_arena pointer or tag indicating local or global seman
tics of the observer
intptr_t my_context_tag;
enum { global_tag = 0, implicit_tag = 1 };
public:
//! Construct local or global observer in inactive state (observation d
isabled).
/** For a local observer entry/exit notifications are invoked whenever
a worker
thread joins/leaves the arena of the observer's owner thread. If a
thread is
already in the arena when the observer is activated, the entry noti
fication is
called before it executes the first stolen task. **/
/** TODO: Obsolete.
Global observer semantics is obsolete as it violates master thread
isolation
guarantees and is not composable. Thus the current default behavior
of the
constructor is obsolete too and will be changed in one of the futur
e versions
of the library. **/
task_scheduler_observer( bool local = false ) {
my_busy_count.store<relaxed>(v6_trait);
my_context_tag = local? implicit_tag : global_tag;
}
#if __TBB_TASK_ARENA
//! Construct local observer for a given arena in inactive state (obser
vation disabled).
/** entry/exit notifications are invoked whenever a thread joins/leaves
arena.
If a thread is already in the arena when the observer is activated,
the entry notification
is called before it executes the first stolen task. **/
task_scheduler_observer( task_arena & a) {
my_busy_count.store<relaxed>(v6_trait);
my_context_tag = (intptr_t)&a;
}
#endif //__TBB_TASK_ARENA
//! The callback can be invoked in a worker thread before it leaves an
arena.
/** If it returns false, the thread remains in the arena. Will not be c
alled for masters
or if the worker leaves arena due to rebalancing or priority change
s, etc.
NOTE: The preview library must be linked for this method to take ef
fect **/
virtual bool on_scheduler_leaving() { return true; }
//! Destructor additionally protects concurrent on_scheduler_leaving no
tification
// It is recommended to disable observation before destructor of a deri
ved class starts,
// otherwise it can lead to concurrent notification callback on partly
destroyed object
virtual ~task_scheduler_observer() { if(my_proxy) observe(false);}
};
} //namespace interface6
using interface6::task_scheduler_observer;
#else /*TBB_PREVIEW_LOCAL_OBSERVER*/
typedef tbb::internal::task_scheduler_observer_v3 task_scheduler_observer;
#endif /*TBB_PREVIEW_LOCAL_OBSERVER*/
} // namespace tbb } // namespace tbb
#endif /* __TBB_SCHEDULER_OBSERVER */ #endif /* __TBB_SCHEDULER_OBSERVER */
#endif /* __TBB_task_scheduler_observer_H */ #endif /* __TBB_task_scheduler_observer_H */
 End of changes. 13 change blocks. 
9 lines changed or deleted 128 lines changed or added


 tbb_config.h   tbb_config.h 
skipping to change at line 42 skipping to change at line 42
/** This header is supposed to contain macro definitions and C style commen ts only. /** This header is supposed to contain macro definitions and C style commen ts only.
The macros defined here are intended to control such aspects of TBB bui ld as The macros defined here are intended to control such aspects of TBB bui ld as
- presence of compiler features - presence of compiler features
- compilation modes - compilation modes
- feature sets - feature sets
- known compiler/platform issues - known compiler/platform issues
**/ **/
#define __TBB_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC _PATCHLEVEL__) #define __TBB_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC _PATCHLEVEL__)
#if __clang__ #if __clang__
#define __TBB_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 10 0 + __clang_patchlevel__) #define __TBB_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
#endif #endif
/** Presence of compiler features **/ /** Presence of compiler features **/
#if __INTEL_COMPILER == 9999 && __INTEL_COMPILER_BUILD_DATE == 20110811
/* Intel Composer XE 2011 Update 6 incorrectly sets __INTEL_COMPILER. Fix i
t. */
#undef __INTEL_COMPILER
#define __INTEL_COMPILER 1210
#endif
#if (__TBB_GCC_VERSION >= 40400) && !defined(__INTEL_COMPILER) #if (__TBB_GCC_VERSION >= 40400) && !defined(__INTEL_COMPILER)
/** warning suppression pragmas available in GCC since 4.4 **/ /** warning suppression pragmas available in GCC since 4.4 **/
#define __TBB_GCC_WARNING_SUPPRESSION_PRESENT 1 #define __TBB_GCC_WARNING_SUPPRESSION_PRESENT 1
#endif #endif
/* Select particular features of C++11 based on compiler version. /* Select particular features of C++11 based on compiler version.
ICC 12.1 (Linux), GCC 4.3 and higher, clang 2.9 and higher ICC 12.1 (Linux), GCC 4.3 and higher, clang 2.9 and higher
set __GXX_EXPERIMENTAL_CXX0X__ in c++11 mode. set __GXX_EXPERIMENTAL_CXX0X__ in c++11 mode.
Compilers that mimics other compilers (ICC, clang) must be processed bef ore Compilers that mimics other compilers (ICC, clang) must be processed bef ore
compilers they mimic. compilers they mimic (GCC, MSVC).
TODO: The following conditions should be extended when new compilers/run times TODO: The following conditions should be extended when new compilers/run times
support added. support added.
*/ */
#if __INTEL_COMPILER #if __INTEL_COMPILER
/** On Windows environment when using Intel C++ compiler with Visual St
udio 2010*,
the C++0x features supported by Visual C++ 2010 are enabled by defa
ult
TODO: find a way to get know if c++0x mode is specified in command
line on windows **/
#define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __GXX_EXPERIMENTAL_CXX0X __ && __VARIADIC_TEMPLATES #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __GXX_EXPERIMENTAL_CXX0X __ && __VARIADIC_TEMPLATES
#define __TBB_CPP11_RVALUE_REF_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ || _ #define __TBB_CPP11_RVALUE_REF_PRESENT (__GXX_EXPERIMENTAL_CXX0
MSC_VER >= 1600) && (__INTEL_COMPILER >= 1200) X__ || _MSC_VER >= 1600) && (__INTEL_COMPILER >= 1200)
#define __TBB_EXCEPTION_PTR_PRESENT 0 #if _MSC_VER >= 1600
#define __TBB_EXCEPTION_PTR_PRESENT __INTEL_COMPILER > 1300
\
/*ICC 12.1 Upd 10 and 13
beta Upd 2 fixed exception_ptr linking issue*/ \
|| (__INTEL_COMPILER ==
1300 && __INTEL_COMPILER_BUILD_DATE >= 20120530) \
|| (__INTEL_COMPILER ==
1210 && __INTEL_COMPILER_BUILD_DATE >= 20120410)
/** libstc++ that comes with GCC 4.6 use C++ features not yet supported
by current ICC (12.1)**/
#elif (__TBB_GCC_VERSION >= 40404) && (__TBB_GCC_VERSION < 40600)
#define __TBB_EXCEPTION_PTR_PRESENT __GXX_EXPERIMENTAL_CXX0X
__ && __INTEL_COMPILER >= 1200
#else
#define __TBB_EXCEPTION_PTR_PRESENT 0
#endif
#define __TBB_MAKE_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1700 || (__
GXX_EXPERIMENTAL_CXX0X__ && __TBB_GCC_VERSION >= 40600))
#define __TBB_CPP11_TUPLE_PRESENT (_MSC_VER >= 1600) || ((
__GXX_EXPERIMENTAL_CXX0X__) && (__TBB_GCC_VERSION >= 40300))
#elif __clang__ #elif __clang__
//TODO: these options need to be rechecked
#define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (__GXX_EXPERIMENTAL_CXX0 X__ && __TBB_CLANG_VERSION >= 20900) #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (__GXX_EXPERIMENTAL_CXX0 X__ && __TBB_CLANG_VERSION >= 20900)
#define __TBB_CPP11_RVALUE_REF_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && _ #define __TBB_CPP11_RVALUE_REF_PRESENT (__GXX_EXPERIMENTAL_CXX0
_TBB_CLANG_VERSION >= 20900) X__ && __TBB_CLANG_VERSION >= 20900)
#define __TBB_EXCEPTION_PTR_PRESENT __GXX_EXPERIMENTAL_CXX0X__ #define __TBB_EXCEPTION_PTR_PRESENT __GXX_EXPERIMENTAL_CXX0X
__
#define __TBB_MAKE_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_CXX0
X__ && __TBB_CLANG_VERSION > 30100)// TODO: check version
#define __TBB_CPP11_TUPLE_PRESENT ((__GXX_EXPERIMENTAL_CXX
0X__) && (__TBB_GCC_VERSION >= 40300))
#elif __GNUC__ #elif __GNUC__
#define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __GXX_EXPERIMENTAL_CXX0X __ #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __GXX_EXPERIMENTAL_CXX0X __
#define __TBB_CPP11_RVALUE_REF_PRESENT __GXX_EXPERIMENTAL_CXX0X__ #define __TBB_CPP11_RVALUE_REF_PRESENT __GXX_EXPERIMENTAL_CXX0X
#define __TBB_EXCEPTION_PTR_PRESENT __GXX_EXPERIMENTAL_CXX0X__ __
/** __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 here is a substitution for _GLIB
CXX_ATOMIC_BUILTINS_4, which is a prerequisite
for exception_ptr but cannot be used in this file because it is def
ined in a header, not by the compiler.
If the compiler has no atomic intrinsics, the C++ library should no
t expect those as well. **/
#define __TBB_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_CXX0
X__ && (__TBB_GCC_VERSION >= 40404) && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
#define __TBB_MAKE_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_CXX0
X__ && __TBB_GCC_VERSION >= 40600)
#define __TBB_CPP11_TUPLE_PRESENT ((__GXX_EXPERIMENTAL_CXX
0X__) && (__TBB_GCC_VERSION >= 40300))
#elif _MSC_VER #elif _MSC_VER
#define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 0 #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 0
#define __TBB_CPP11_RVALUE_REF_PRESENT 0 #define __TBB_CPP11_RVALUE_REF_PRESENT 0
#define __TBB_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1600) #define __TBB_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1600)
#define __TBB_MAKE_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1700)
#define __TBB_CPP11_TUPLE_PRESENT (_MSC_VER >= 1600)
#else #else
#define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 0 #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 0
#define __TBB_CPP11_RVALUE_REF_PRESENT 0 #define __TBB_CPP11_RVALUE_REF_PRESENT 0
#define __TBB_EXCEPTION_PTR_PRESENT 0 #define __TBB_EXCEPTION_PTR_PRESENT 0
#define __TBB_MAKE_EXCEPTION_PTR_PRESENT 0
#define __TBB_CPP11_TUPLE_PRESENT 0
#endif
//TODO: not clear how exactly this macro affects exception_ptr - investigat
e
// On linux ICC fails to find existing std::exception_ptr in libstdc++ with
out this define
#if __INTEL_COMPILER && __GNUC__ && __TBB_EXCEPTION_PTR_PRESENT && !defined
(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
#endif #endif
// Work around a bug in MinGW32 // Work around a bug in MinGW32
#if __MINGW32__ && __TBB_EXCEPTION_PTR_PRESENT && !defined(_GLIBCXX_ATOMIC_ BUILTINS_4) #if __MINGW32__ && __TBB_EXCEPTION_PTR_PRESENT && !defined(_GLIBCXX_ATOMIC_ BUILTINS_4)
#define _GLIBCXX_ATOMIC_BUILTINS_4 #define _GLIBCXX_ATOMIC_BUILTINS_4
#endif #endif
#if __GNUC__ || __SUNPRO_CC || __IBMCPP__ #if __GNUC__ || __SUNPRO_CC || __IBMCPP__
/* ICC defines __GNUC__ and so is covered */ /* ICC defines __GNUC__ and so is covered */
#define __TBB_ATTRIBUTE_ALIGNED_PRESENT 1 #define __TBB_ATTRIBUTE_ALIGNED_PRESENT 1
skipping to change at line 170 skipping to change at line 209
#ifndef TBB_IMPLEMENT_CPP0X #ifndef TBB_IMPLEMENT_CPP0X
/** By default, use C++0x classes if available **/ /** By default, use C++0x classes if available **/
#if __GNUC__==4 && __GNUC_MINOR__>=4 && __GXX_EXPERIMENTAL_CXX0X__ #if __GNUC__==4 && __GNUC_MINOR__>=4 && __GXX_EXPERIMENTAL_CXX0X__
#define TBB_IMPLEMENT_CPP0X 0 #define TBB_IMPLEMENT_CPP0X 0
#else #else
#define TBB_IMPLEMENT_CPP0X 1 #define TBB_IMPLEMENT_CPP0X 1
#endif #endif
#endif /* TBB_IMPLEMENT_CPP0X */ #endif /* TBB_IMPLEMENT_CPP0X */
/* TBB_USE_CAPTURED_EXCEPTION should be explicitly set to either 0 or 1, as it is used as C++ const */
#ifndef TBB_USE_CAPTURED_EXCEPTION #ifndef TBB_USE_CAPTURED_EXCEPTION
#if __TBB_EXCEPTION_PTR_PRESENT /** linux pre-built TBB binary does not support exception_ptr. **/
#if __TBB_EXCEPTION_PTR_PRESENT && !defined(__GNUC__)
#define TBB_USE_CAPTURED_EXCEPTION 0 #define TBB_USE_CAPTURED_EXCEPTION 0
#else #else
#define TBB_USE_CAPTURED_EXCEPTION 1 #define TBB_USE_CAPTURED_EXCEPTION 1
#endif #endif
#else /* defined TBB_USE_CAPTURED_EXCEPTION */ #else /* defined TBB_USE_CAPTURED_EXCEPTION */
#if !TBB_USE_CAPTURED_EXCEPTION && !__TBB_EXCEPTION_PTR_PRESENT #if !TBB_USE_CAPTURED_EXCEPTION && !__TBB_EXCEPTION_PTR_PRESENT
#error Current runtime does not support std::exception_ptr. Set TBB _USE_CAPTURED_EXCEPTION and make sure that your code is ready to catch tbb: :captured_exception. #error Current runtime does not support std::exception_ptr. Set TBB _USE_CAPTURED_EXCEPTION and make sure that your code is ready to catch tbb: :captured_exception.
#endif #endif
#endif /* defined TBB_USE_CAPTURED_EXCEPTION */ #endif /* defined TBB_USE_CAPTURED_EXCEPTION */
skipping to change at line 213 skipping to change at line 254
#endif #endif
#ifndef __TBB_COUNT_TASK_NODES #ifndef __TBB_COUNT_TASK_NODES
#define __TBB_COUNT_TASK_NODES TBB_USE_ASSERT #define __TBB_COUNT_TASK_NODES TBB_USE_ASSERT
#endif #endif
#ifndef __TBB_TASK_GROUP_CONTEXT #ifndef __TBB_TASK_GROUP_CONTEXT
#define __TBB_TASK_GROUP_CONTEXT 1 #define __TBB_TASK_GROUP_CONTEXT 1
#endif /* __TBB_TASK_GROUP_CONTEXT */ #endif /* __TBB_TASK_GROUP_CONTEXT */
#if TBB_USE_EXCEPTIONS && !__TBB_TASK_GROUP_CONTEXT
#error TBB_USE_EXCEPTIONS requires __TBB_TASK_GROUP_CONTEXT to be enabl
ed
#endif
#ifndef __TBB_SCHEDULER_OBSERVER #ifndef __TBB_SCHEDULER_OBSERVER
#define __TBB_SCHEDULER_OBSERVER 1 #define __TBB_SCHEDULER_OBSERVER 1
#endif /* __TBB_SCHEDULER_OBSERVER */ #endif /* __TBB_SCHEDULER_OBSERVER */
#if !defined(TBB_PREVIEW_TASK_ARENA) && __TBB_BUILD
#define TBB_PREVIEW_TASK_ARENA __TBB_CPF_BUILD
#endif /* TBB_PREVIEW_TASK_ARENA */
#define __TBB_TASK_ARENA TBB_PREVIEW_TASK_ARENA
#if TBB_PREVIEW_TASK_ARENA
#define TBB_PREVIEW_LOCAL_OBSERVER 1
#define __TBB_NO_IMPLICIT_LINKAGE 1
#define __TBB_TASK_PRIORITY 0 // TODO: it will be removed in next versi
ons
#if !__TBB_SCHEDULER_OBSERVER
#error TBB_PREVIEW_TASK_ARENA requires __TBB_SCHEDULER_OBSERVER to
be enabled
#endif
#endif /* TBB_PREVIEW_TASK_ARENA */
#if !defined(TBB_PREVIEW_LOCAL_OBSERVER) && __TBB_BUILD && __TBB_SCHEDULER_
OBSERVER
#define TBB_PREVIEW_LOCAL_OBSERVER 1
#endif /* TBB_PREVIEW_LOCAL_OBSERVER */
#if TBB_USE_EXCEPTIONS && !__TBB_TASK_GROUP_CONTEXT
#error TBB_USE_EXCEPTIONS requires __TBB_TASK_GROUP_CONTEXT to be enabl
ed
#endif
#ifndef __TBB_TASK_PRIORITY #ifndef __TBB_TASK_PRIORITY
#define __TBB_TASK_PRIORITY __TBB_TASK_GROUP_CONTEXT #define __TBB_TASK_PRIORITY __TBB_TASK_GROUP_CONTEXT
#endif /* __TBB_TASK_PRIORITY */ #endif /* __TBB_TASK_PRIORITY */
#if __TBB_TASK_PRIORITY && !__TBB_TASK_GROUP_CONTEXT #if __TBB_TASK_PRIORITY && !__TBB_TASK_GROUP_CONTEXT
#error __TBB_TASK_PRIORITY requires __TBB_TASK_GROUP_CONTEXT to be enab led #error __TBB_TASK_PRIORITY requires __TBB_TASK_GROUP_CONTEXT to be enab led
#endif #endif
#if !defined(__TBB_SURVIVE_THREAD_SWITCH) && (_WIN32 || _WIN64 || __linux__ #if !defined(__TBB_SURVIVE_THREAD_SWITCH) && \
) (_WIN32 || _WIN64 || __APPLE__ || __linux__)
#define __TBB_SURVIVE_THREAD_SWITCH 1 #define __TBB_SURVIVE_THREAD_SWITCH 1
#endif /* __TBB_SURVIVE_THREAD_SWITCH */ #endif /* __TBB_SURVIVE_THREAD_SWITCH */
#ifndef __TBB_DEFAULT_PARTITIONER #ifndef __TBB_DEFAULT_PARTITIONER
#if TBB_DEPRECATED #if TBB_DEPRECATED
/** Default partitioner for parallel loop templates in TBB 1.0-2.1 */ /** Default partitioner for parallel loop templates in TBB 1.0-2.1 */
#define __TBB_DEFAULT_PARTITIONER tbb::simple_partitioner #define __TBB_DEFAULT_PARTITIONER tbb::simple_partitioner
#else #else
/** Default partitioner for parallel loop templates since TBB 2.2 */ /** Default partitioner for parallel loop templates since TBB 2.2 */
#define __TBB_DEFAULT_PARTITIONER tbb::auto_partitioner #define __TBB_DEFAULT_PARTITIONER tbb::auto_partitioner
#endif /* TBB_DEPRECATED */ #endif /* TBB_DEPRECATED */
#endif /* !defined(__TBB_DEFAULT_PARTITIONER */ #endif /* !defined(__TBB_DEFAULT_PARTITIONER */
#ifdef _VARIADIC_MAX #ifdef _VARIADIC_MAX
#define __TBB_VARIADIC_MAX _VARIADIC_MAX #define __TBB_VARIADIC_MAX _VARIADIC_MAX
#else #else
#if _MSC_VER >= 1700 #if _MSC_VER >= 1700
#define __TBB_VARIADIC_MAX 5 // current VS11 setting, may change. #define __TBB_VARIADIC_MAX 5 /* current VS11 setting, may change. */
#else #else
#define __TBB_VARIADIC_MAX 10 #define __TBB_VARIADIC_MAX 10
#endif #endif
#endif #endif
/** Macros of the form __TBB_XXX_BROKEN denote known issues that are caused by /** Macros of the form __TBB_XXX_BROKEN denote known issues that are caused by
the bugs in compilers, standard or OS specific libraries. They should b e the bugs in compilers, standard or OS specific libraries. They should b e
removed as soon as the corresponding bugs are fixed or the buggy OS/com piler removed as soon as the corresponding bugs are fixed or the buggy OS/com piler
versions go out of the support list. versions go out of the support list.
**/ **/
skipping to change at line 277 skipping to change at line 336
#define __TBB_DEFAULT_DTOR_THROW_SPEC_BROKEN 1 #define __TBB_DEFAULT_DTOR_THROW_SPEC_BROKEN 1
#endif #endif
#if defined(_MSC_VER) && _MSC_VER < 1500 && !defined(__INTEL_COMPILER) #if defined(_MSC_VER) && _MSC_VER < 1500 && !defined(__INTEL_COMPILER)
/** VS2005 and earlier do not allow declaring template class as a frien d /** VS2005 and earlier do not allow declaring template class as a frien d
of classes defined in other namespaces. **/ of classes defined in other namespaces. **/
#define __TBB_TEMPLATE_FRIENDS_BROKEN 1 #define __TBB_TEMPLATE_FRIENDS_BROKEN 1
#endif #endif
#if __GLIBC__==2 && __GLIBC_MINOR__==3 || __MINGW32__ || (__APPLE__ && __IN TEL_COMPILER==1200 && !TBB_USE_DEBUG) #if __GLIBC__==2 && __GLIBC_MINOR__==3 || __MINGW32__ || (__APPLE__ && __IN TEL_COMPILER==1200 && !TBB_USE_DEBUG)
//! Macro controlling EH usages in TBB tests /** Macro controlling EH usages in TBB tests.
/** Some older versions of glibc crash when exception handling happens Some older versions of glibc crash when exception handling happens
concurrently. **/ concurrently. **/
#define __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN 1 #define __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN 1
#else
#define __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN 0
#endif #endif
#if (_WIN32||_WIN64) && __INTEL_COMPILER == 1110 #if (_WIN32||_WIN64) && __INTEL_COMPILER == 1110
/** That's a bug in Intel compiler 11.1.044/IA-32/Windows, that leads t o a worker thread crash on the thread's startup. **/ /** That's a bug in Intel compiler 11.1.044/IA-32/Windows, that leads t o a worker thread crash on the thread's startup. **/
#define __TBB_ICL_11_1_CODE_GEN_BROKEN 1 #define __TBB_ICL_11_1_CODE_GEN_BROKEN 1
#endif #endif
#if __clang__ || (__GNUC__==3 && __GNUC_MINOR__==3 && !defined(__INTEL_COMP ILER)) #if __clang__ || (__GNUC__==3 && __GNUC_MINOR__==3 && !defined(__INTEL_COMP ILER))
/** Bugs with access to nested classes declared in protected area */ /** Bugs with access to nested classes declared in protected area */
#define __TBB_PROTECTED_NESTED_CLASS_BROKEN 1 #define __TBB_PROTECTED_NESTED_CLASS_BROKEN 1
#endif #endif
#if __MINGW32__ && (__GNUC__<4 || __GNUC__==4 && __GNUC_MINOR__<2) #if __MINGW32__ && (__GNUC__<4 || __GNUC__==4 && __GNUC_MINOR__<2)
/** MinGW has a bug with stack alignment for routines invoked from MS R TLs. /** MinGW has a bug with stack alignment for routines invoked from MS R TLs.
Since GCC 4.2, the bug can be worked around via a special attribute . **/ Since GCC 4.2, the bug can be worked around via a special attribute . **/
#define __TBB_SSE_STACK_ALIGNMENT_BROKEN 1 #define __TBB_SSE_STACK_ALIGNMENT_BROKEN 1
#else
#define __TBB_SSE_STACK_ALIGNMENT_BROKEN 0
#endif #endif
#if __GNUC__==4 && __GNUC_MINOR__==3 && __GNUC_PATCHLEVEL__==0 #if __GNUC__==4 && __GNUC_MINOR__==3 && __GNUC_PATCHLEVEL__==0
// GCC of this version may rashly ignore control dependencies /* GCC of this version may rashly ignore control dependencies */
#define __TBB_GCC_OPTIMIZER_ORDERING_BROKEN 1 #define __TBB_GCC_OPTIMIZER_ORDERING_BROKEN 1
#endif #endif
#if __FreeBSD__ #if __FreeBSD__
/** A bug in FreeBSD 8.0 results in kernel panic when there is contenti on /** A bug in FreeBSD 8.0 results in kernel panic when there is contenti on
on a mutex created with this attribute. **/ on a mutex created with this attribute. **/
#define __TBB_PRIO_INHERIT_BROKEN 1 #define __TBB_PRIO_INHERIT_BROKEN 1
/** A bug in FreeBSD 8.0 results in test hanging when an exception occu rs /** A bug in FreeBSD 8.0 results in test hanging when an exception occu rs
during (concurrent?) object construction by means of placement new operator. **/ during (concurrent?) object construction by means of placement new operator. **/
skipping to change at line 336 skipping to change at line 399
#define __TBB_CPP11_STD_FORWARD_BROKEN 1 #define __TBB_CPP11_STD_FORWARD_BROKEN 1
#else #else
#define __TBB_CPP11_STD_FORWARD_BROKEN 0 #define __TBB_CPP11_STD_FORWARD_BROKEN 0
#endif #endif
#if __TBB_DEFINE_MIC #if __TBB_DEFINE_MIC
/** Main thread and user's thread have different default thread affinit y masks. **/ /** Main thread and user's thread have different default thread affinit y masks. **/
#define __TBB_MAIN_THREAD_AFFINITY_BROKEN 1 #define __TBB_MAIN_THREAD_AFFINITY_BROKEN 1
#endif #endif
#if !defined(__EXCEPTIONS) && __GNUC__==4 && (__GNUC_MINOR__==4 ||__GNUC_MI
NOR__==5) && defined(__GXX_EXPERIMENTAL_CXX0X__)
/* There is an issue for specific GCC toolchain when C++11 is enabled
and exceptions are disabled:
exceprion_ptr.h/nested_exception.h are using throw unconditionally.
*/
#define __TBB_LIBSTDCPP_EXCEPTION_HEADERS_BROKEN 1
#else
#define __TBB_LIBSTDCPP_EXCEPTION_HEADERS_BROKEN 0
#endif
#endif /* __TBB_tbb_config_H */ #endif /* __TBB_tbb_config_H */
 End of changes. 21 change blocks. 
27 lines changed or deleted 128 lines changed or added


 tbb_exception.h   tbb_exception.h 
skipping to change at line 357 skipping to change at line 357
//! Destroys this objects //! Destroys this objects
/** Note that objects of this type can be created only by the allocate( ) method. **/ /** Note that objects of this type can be created only by the allocate( ) method. **/
void destroy () throw(); void destroy () throw();
//! Throws the contained exception . //! Throws the contained exception .
void throw_self () { std::rethrow_exception(my_ptr); } void throw_self () { std::rethrow_exception(my_ptr); }
private: private:
tbb_exception_ptr ( const std::exception_ptr& src ) : my_ptr(src) {} tbb_exception_ptr ( const std::exception_ptr& src ) : my_ptr(src) {}
tbb_exception_ptr ( const captured_exception& src ) : my_ptr(std::copy_ tbb_exception_ptr ( const captured_exception& src ) :
exception(src)) {} #if __TBB_MAKE_EXCEPTION_PTR_PRESENT
my_ptr(std::make_exception_ptr(src)) // the final function nam
e in C++11
#else
my_ptr(std::copy_exception(src)) // early C++0x drafts nam
e
#endif
{}
}; // class tbb::internal::tbb_exception_ptr }; // class tbb::internal::tbb_exception_ptr
} // namespace internal } // namespace internal
#endif /* !TBB_USE_CAPTURED_EXCEPTION */ #endif /* !TBB_USE_CAPTURED_EXCEPTION */
} // namespace tbb } // namespace tbb
#endif /* __TBB_TASK_GROUP_CONTEXT */ #endif /* __TBB_TASK_GROUP_CONTEXT */
#endif /* __TBB_exception_H */ #endif /* __TBB_exception_H */
 End of changes. 1 change blocks. 
2 lines changed or deleted 9 lines changed or added


 tbb_stddef.h   tbb_stddef.h 
skipping to change at line 34 skipping to change at line 34
the GNU General Public License. This exception does not however the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered b y invalidate any other reasons why the executable file might be covered b y
the GNU General Public License. the GNU General Public License.
*/ */
#ifndef __TBB_tbb_stddef_H #ifndef __TBB_tbb_stddef_H
#define __TBB_tbb_stddef_H #define __TBB_tbb_stddef_H
// Marketing-driven product version // Marketing-driven product version
#define TBB_VERSION_MAJOR 4 #define TBB_VERSION_MAJOR 4
#define TBB_VERSION_MINOR 0 #define TBB_VERSION_MINOR 1
// Engineering-focused interface version // Engineering-focused interface version
#define TBB_INTERFACE_VERSION 6005 #define TBB_INTERFACE_VERSION 6100
#define TBB_INTERFACE_VERSION_MAJOR TBB_INTERFACE_VERSION/1000 #define TBB_INTERFACE_VERSION_MAJOR TBB_INTERFACE_VERSION/1000
// The oldest major interface version still supported // The oldest major interface version still supported
// To be used in SONAME, manifests, etc. // To be used in SONAME, manifests, etc.
#define TBB_COMPATIBLE_INTERFACE_VERSION 2 #define TBB_COMPATIBLE_INTERFACE_VERSION 2
#define __TBB_STRING_AUX(x) #x #define __TBB_STRING_AUX(x) #x
#define __TBB_STRING(x) __TBB_STRING_AUX(x) #define __TBB_STRING(x) __TBB_STRING_AUX(x)
// We do not need defines below for resource processing on windows // We do not need defines below for resource processing on windows
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 tuple   tuple 
skipping to change at line 32 skipping to change at line 32
this file and link it with other files to produce an executable, this this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered b y invalidate any other reasons why the executable file might be covered b y
the GNU General Public License. the GNU General Public License.
*/ */
#ifndef __TBB_tuple_H #ifndef __TBB_tuple_H
#define __TBB_tuple_H #define __TBB_tuple_H
#if !TBB_PREVIEW_TUPLE
#error Set TBB_PREVIEW_TUPLE to include compat/tuple
#endif
#include <utility> #include <utility>
#include "../tbb_stddef.h" #include "../tbb_stddef.h"
// build preprocessor variables for varying number of arguments // build preprocessor variables for varying number of arguments
// Need the leading comma so the empty __TBB_T_PACK will not cause a syntax error. // Need the leading comma so the empty __TBB_T_PACK will not cause a syntax error.
#if __TBB_VARIADIC_MAX <= 5 #if __TBB_VARIADIC_MAX <= 5
#define __TBB_T_PACK #define __TBB_T_PACK
#define __TBB_U_PACK #define __TBB_U_PACK
#define __TBB_CLASS_T_PACK #define __TBB_CLASS_T_PACK
#define __TBB_CLASS_U_PACK #define __TBB_CLASS_U_PACK
skipping to change at line 499 skipping to change at line 495
inline static typename tuple_element<N,tuple<T0,T1,T2,T3,T4 __TBB_T_PACK > >::type& inline static typename tuple_element<N,tuple<T0,T1,T2,T3,T4 __TBB_T_PACK > >::type&
get(tuple<T0,T1,T2,T3,T4 __TBB_T_PACK >& t) { return t.get<N>(); } get(tuple<T0,T1,T2,T3,T4 __TBB_T_PACK >& t) { return t.get<N>(); }
template<int N, class T0, class T1, class T2, class T3, class T4 __TBB_CLAS S_T_PACK > template<int N, class T0, class T1, class T2, class T3, class T4 __TBB_CLAS S_T_PACK >
inline static typename tuple_element<N,tuple<T0,T1,T2,T3,T4 __TBB_T_PACK > >::type const& inline static typename tuple_element<N,tuple<T0,T1,T2,T3,T4 __TBB_T_PACK > >::type const&
get(const tuple<T0,T1,T2,T3,T4 __TBB_T_PACK >& t) { return t.get<N>(); } get(const tuple<T0,T1,T2,T3,T4 __TBB_T_PACK >& t) { return t.get<N>(); }
} // interface5 } // interface5
} // tbb } // tbb
#if TBB_IMPLEMENT_CPP0X #if !__TBB_CPP11_TUPLE_PRESENT
namespace std { namespace std {
using tbb::interface5::tuple; using tbb::interface5::tuple;
using tbb::interface5::tuple_size; using tbb::interface5::tuple_size;
using tbb::interface5::tuple_element; using tbb::interface5::tuple_element;
using tbb::interface5::get; using tbb::interface5::get;
} }
#endif #endif
#undef __TBB_T_PACK #undef __TBB_T_PACK
#undef __TBB_U_PACK #undef __TBB_U_PACK
 End of changes. 2 change blocks. 
5 lines changed or deleted 1 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/