_flow_graph_impl.h   _flow_graph_impl.h 
skipping to change at line 42 skipping to change at line 42
#ifndef __TBB_flow_graph_H #ifndef __TBB_flow_graph_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
namespace internal { namespace internal {
namespace graph_policy_namespace { namespace graph_policy_namespace {
enum graph_buffer_policy { rejecting, reserving, queueing, tag_matc hing }; enum graph_buffer_policy { rejecting, reserving, queueing, tag_matc hing };
} }
// -------------- function_body containers ----------------------
//! A functor that takes no input and generates a value of type Output //! A functor that takes no input and generates a value of type Output
template< typename Output > template< typename Output >
class source_body : tbb::internal::no_assign { class source_body : tbb::internal::no_assign {
public: public:
virtual ~source_body() {} virtual ~source_body() {}
virtual bool operator()(Output &output) = 0; virtual bool operator()(Output &output) = 0;
virtual source_body* clone() = 0; virtual source_body* clone() = 0;
}; };
//! The leaf for source_body //! The leaf for source_body
skipping to change at line 158 skipping to change at line 160
virtual void operator()(const Input &/* input*/, OutputSet &/*oset* /) = 0; virtual void operator()(const Input &/* input*/, OutputSet &/*oset* /) = 0;
virtual multifunction_body* clone() = 0; virtual multifunction_body* clone() = 0;
}; };
//! leaf for multifunction. OutputSet can be a std::tuple or a vector. //! leaf for multifunction. OutputSet can be a std::tuple or a vector.
template<typename Input, typename OutputSet, typename B> template<typename Input, typename OutputSet, typename B>
class multifunction_body_leaf : public multifunction_body<Input, Output Set> { class multifunction_body_leaf : public multifunction_body<Input, Output Set> {
public: public:
multifunction_body_leaf(const B &_body) : body(_body), init_body(_b ody) { } multifunction_body_leaf(const B &_body) : body(_body), init_body(_b ody) { }
void operator()(const Input &input, OutputSet &oset) { void operator()(const Input &input, OutputSet &oset) {
body(input, oset); // body should explicitly put() to one or mo re of oset. body(input, oset); // body may explicitly put() to one or more of oset.
} }
B get_body() { return body; } B get_body() { return body; }
/*override*/ multifunction_body_leaf* clone() { /*override*/ multifunction_body_leaf* clone() {
return new multifunction_body_leaf<Input, OutputSet,B>(init_bod y); return new multifunction_body_leaf<Input, OutputSet,B>(init_bod y);
} }
private: private:
B body; B body;
B init_body; B init_body;
}; };
//! A task that calls a node's forward function // --------------------------- end of function_body containers ------------
------------
// --------------------------- node task bodies ---------------------------
------------
//! A task that calls a node's forward_task function
template< typename NodeType > template< typename NodeType >
class forward_task : public task { class forward_task_bypass : public task {
NodeType &my_node; NodeType &my_node;
public: public:
forward_task( NodeType &n ) : my_node(n) {} forward_task_bypass( NodeType &n ) : my_node(n) {}
task *execute() { task *execute() {
my_node.forward(); task * new_task = my_node.forward_task();
return NULL; if (new_task == SUCCESSFULLY_ENQUEUED) new_task = NULL;
return new_task;
} }
}; };
//! A task that calls a node's apply_body function, passing in an input //! A task that calls a node's apply_body_bypass function, passing in a
of type Input n input of type Input
// return the task* unless it is SUCCESSFULLY_ENQUEUED, in which case
return NULL
template< typename NodeType, typename Input > template< typename NodeType, typename Input >
class apply_body_task : public task { class apply_body_task_bypass : public task {
NodeType &my_node; NodeType &my_node;
Input my_input; Input my_input;
public: public:
apply_body_task( NodeType &n, const Input &i ) : my_node(n), my_inp ut(i) {} apply_body_task_bypass( NodeType &n, const Input &i ) : my_node(n), my_input(i) {}
task *execute() { task *execute() {
my_node.apply_body( my_input ); task * next_task = my_node.apply_body_bypass( my_input );
return NULL; if(next_task == SUCCESSFULLY_ENQUEUED) next_task = NULL;
return next_task;
} }
}; };
//! A task that calls a node's apply_body function with no input //! A task that calls a node's apply_body function with no input
template< typename NodeType > template< typename NodeType >
class source_task : public task { class source_task_bypass : public task {
NodeType &my_node; NodeType &my_node;
public: public:
source_task( NodeType &n ) : my_node(n) {} source_task_bypass( NodeType &n ) : my_node(n) {}
task *execute() { task *execute() {
my_node.apply_body( ); task *new_task = my_node.apply_body_bypass( );
return NULL; if(new_task == SUCCESSFULLY_ENQUEUED) return NULL;
return new_task;
} }
}; };
// ------------------------ end of node task bodies -----------------------
------------
//! An empty functor that takes an Input and returns a default construc ted Output //! An empty functor that takes an Input and returns a default construc ted Output
template< typename Input, typename Output > template< typename Input, typename Output >
struct empty_body { struct empty_body {
Output operator()( const Input & ) const { return Output(); } Output operator()( const Input & ) const { return Output(); }
}; };
//! A node_cache maintains a std::queue of elements of type T. Each op eration is protected by a lock. //! A node_cache maintains a std::queue of elements of type T. Each op eration is protected by a lock.
template< typename T, typename M=spin_mutex > template< typename T, typename M=spin_mutex >
class node_cache { class node_cache {
public: public:
skipping to change at line 449 skipping to change at line 461
break; break;
} }
} }
} }
bool empty() { bool empty() {
typename my_mutex_type::scoped_lock l(my_mutex, false); typename my_mutex_type::scoped_lock l(my_mutex, false);
return my_successors.empty(); return my_successors.empty();
} }
virtual bool try_put( const T &t ) = 0; virtual task * try_put_task( const T &t ) = 0;
}; };
//! An abstract cache of succesors, specialized to continue_msg //! An abstract cache of succesors, specialized to continue_msg
template<> template<>
class successor_cache< continue_msg > : tbb::internal::no_copy { class successor_cache< continue_msg > : tbb::internal::no_copy {
protected: protected:
typedef spin_rw_mutex my_mutex_type; typedef spin_rw_mutex my_mutex_type;
my_mutex_type my_mutex; my_mutex_type my_mutex;
skipping to change at line 499 skipping to change at line 511
break; break;
} }
} }
} }
bool empty() { bool empty() {
my_mutex_type::scoped_lock l(my_mutex, false); my_mutex_type::scoped_lock l(my_mutex, false);
return my_successors.empty(); return my_successors.empty();
} }
virtual bool try_put( const continue_msg &t ) = 0; virtual task * try_put_task( const continue_msg &t ) = 0;
}; };
//! A cache of successors that are broadcast to //! A cache of successors that are broadcast to
template<typename T, typename M=spin_rw_mutex> template<typename T, typename M=spin_rw_mutex>
class broadcast_cache : public successor_cache<T, M> { class broadcast_cache : public successor_cache<T, M> {
typedef M my_mutex_type; typedef M my_mutex_type;
typedef std::list< receiver<T> * > my_successors_type; typedef std::list< receiver<T> * > my_successors_type;
public: public:
broadcast_cache( ) {} broadcast_cache( ) {}
bool try_put( const T &t ) { // as above, but call try_put_task instead, and return the last tas
bool msg = false; k we received (if any)
/*override*/ task * try_put_task( const T &t ) {
task * last_task = NULL;
bool upgraded = false; bool upgraded = false;
typename my_mutex_type::scoped_lock l(this->my_mutex, false); typename my_mutex_type::scoped_lock l(this->my_mutex, false);
typename my_successors_type::iterator i = this->my_successors.b egin(); typename my_successors_type::iterator i = this->my_successors.b egin();
while ( i != this->my_successors.end() ) { while ( i != this->my_successors.end() ) {
if ( (*i)->try_put( t ) == true ) { task *new_task = (*i)->try_put_task(t);
++i; last_task = combine_tasks(last_task, new_task); // enqueue
msg = true; if necessary
} else { if(new_task) {
if ( (*i)->register_predecessor(*this->my_owner) ) { ++i;
if (!upgraded) { }
l.upgrade_to_writer(); else { // failed
upgraded = true; if ( (*i)->register_predecessor(*this->my_owner) ) {
} if (!upgraded) {
i = this->my_successors.erase(i); l.upgrade_to_writer();
} upgraded = true;
else { }
++i; i = this->my_successors.erase(i);
} } else {
} ++i;
}
}
} }
return msg; return last_task;
} }
}; };
//! A cache of successors that are put in a round-robin fashion //! A cache of successors that are put in a round-robin fashion
template<typename T, typename M=spin_rw_mutex > template<typename T, typename M=spin_rw_mutex >
class round_robin_cache : public successor_cache<T, M> { class round_robin_cache : public successor_cache<T, M> {
typedef size_t size_type; typedef size_t size_type;
typedef M my_mutex_type; typedef M my_mutex_type;
typedef std::list< receiver<T> * > my_successors_type; typedef std::list< receiver<T> * > my_successors_type;
public: public:
round_robin_cache( ) {} round_robin_cache( ) {}
size_type size() { size_type size() {
typename my_mutex_type::scoped_lock l(this->my_mutex, false); typename my_mutex_type::scoped_lock l(this->my_mutex, false);
return this->my_successors.size(); return this->my_successors.size();
} }
bool try_put( const T &t ) { /*override*/task *try_put_task( const T &t ) {
bool upgraded = false; bool upgraded = false;
typename my_mutex_type::scoped_lock l(this->my_mutex, false); typename my_mutex_type::scoped_lock l(this->my_mutex, false);
typename my_successors_type::iterator i = this->my_successors.b egin(); typename my_successors_type::iterator i = this->my_successors.b egin();
while ( i != this->my_successors.end() ) { while ( i != this->my_successors.end() ) {
if ( (*i)->try_put( t ) ) { task *new_task = (*i)->try_put_task(t);
return true; if ( new_task ) {
} else { return new_task;
if ( (*i)->register_predecessor(*this->my_owner) ) { } else {
if (!upgraded) { if ( (*i)->register_predecessor(*this->my_owner) ) {
l.upgrade_to_writer(); if (!upgraded) {
upgraded = true; l.upgrade_to_writer();
} upgraded = true;
i = this->my_successors.erase(i); }
} i = this->my_successors.erase(i);
else { }
++i; else {
} ++i;
} }
}
} }
return false; return NULL;
} }
}; };
template<typename T> template<typename T>
class decrementer : public continue_receiver, tbb::internal::no_copy { class decrementer : public continue_receiver, tbb::internal::no_copy {
T *my_node; T *my_node;
void execute() { task *execute() {
my_node->decrement_counter(); return my_node->decrement_counter();
} }
public: public:
typedef continue_msg input_type; typedef continue_msg input_type;
typedef continue_msg output_type; typedef continue_msg output_type;
decrementer( int number_of_predecessors = 0 ) : continue_receiver( number_of_predecessors ) { } decrementer( int number_of_predecessors = 0 ) : continue_receiver( number_of_predecessors ) { }
void set_owner( T *node ) { my_node = node; } void set_owner( T *node ) { my_node = node; }
}; };
 End of changes. 23 change blocks. 
54 lines changed or deleted 75 lines changed or added


 _flow_graph_join_impl.h   _flow_graph_join_impl.h 
skipping to change at line 46 skipping to change at line 46
#include "tbb/internal/_flow_graph_types_impl.h" #include "tbb/internal/_flow_graph_types_impl.h"
namespace internal { namespace internal {
typedef size_t tag_value; typedef size_t tag_value;
static const tag_value NO_TAG = tag_value(-1); static const tag_value NO_TAG = tag_value(-1);
struct forwarding_base { struct forwarding_base {
forwarding_base(task *rt) : my_root_task(rt), current_tag(NO_TAG) { } forwarding_base(task *rt) : my_root_task(rt), current_tag(NO_TAG) { }
virtual ~forwarding_base() {} virtual ~forwarding_base() {}
virtual void decrement_port_count() = 0; // decrement_port_count may create a forwarding task. If we cannot
handle the task
// ourselves, ask decrement_port_count to deal with it.
virtual task * decrement_port_count(bool handle_task) = 0;
virtual void increment_port_count() = 0; virtual void increment_port_count() = 0;
virtual void increment_tag_count(tag_value /*t*/) {} virtual task * increment_tag_count(tag_value /*t*/, bool /*handle_t ask*/) {return NULL;}
// moved here so input ports can queue tasks // moved here so input ports can queue tasks
task* my_root_task; task* my_root_task;
tag_value current_tag; // so ports can refer to FE's desired items tag_value current_tag; // so ports can refer to FE's desired items
}; };
template< int N > template< int N >
struct join_helper { struct join_helper {
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<N-1>( my_input ).set_join_node_pointer(port); tbb::flow::get<N-1>( my_input ).set_join_node_pointer(port);
join_helper<N-1>::set_join_node_pointer( my_input, port ); join_helper<N-1>::set_join_node_pointer( my_input, port );
} }
template< typename TupleType > template< typename TupleType >
static inline void consume_reservations( TupleType &my_input ) { static inline void consume_reservations( TupleType &my_input ) {
std::get<N-1>( my_input ).consume(); tbb::flow::get<N-1>( my_input ).consume();
join_helper<N-1>::consume_reservations( my_input ); join_helper<N-1>::consume_reservations( my_input );
} }
template< typename TupleType > template< typename TupleType >
static inline void release_my_reservation( TupleType &my_input ) { static inline void release_my_reservation( TupleType &my_input ) {
std::get<N-1>( my_input ).release(); tbb::flow::get<N-1>( my_input ).release();
} }
template <typename TupleType> template <typename TupleType>
static inline void release_reservations( TupleType &my_input) { static inline void release_reservations( TupleType &my_input) {
join_helper<N-1>::release_reservations(my_input); join_helper<N-1>::release_reservations(my_input);
release_my_reservation(my_input); release_my_reservation(my_input);
} }
template< typename InputTuple, typename OutputTuple > template< typename InputTuple, typename OutputTuple >
static inline bool reserve( InputTuple &my_input, OutputTuple &out) { static inline bool reserve( InputTuple &my_input, OutputTuple &out) {
if ( !std::get<N-1>( my_input ).reserve( std::get<N-1>( out ) ) ) return false; if ( !tbb::flow::get<N-1>( my_input ).reserve( tbb::flow::get<N -1>( out ) ) ) return false;
if ( !join_helper<N-1>::reserve( my_input, out ) ) { if ( !join_helper<N-1>::reserve( my_input, out ) ) {
release_my_reservation( my_input ); release_my_reservation( my_input );
return false; return false;
} }
return true; return true;
} }
template<typename InputTuple, typename OutputTuple> template<typename InputTuple, typename OutputTuple>
static inline bool get_my_item( InputTuple &my_input, OutputTuple & out) { static inline bool get_my_item( InputTuple &my_input, OutputTuple & out) {
bool res = std::get<N-1>(my_input).get_item(std::get<N-1>(out) ); // may fail bool res = tbb::flow::get<N-1>(my_input).get_item(tbb::flow::ge t<N-1>(out) ); // may fail
return join_helper<N-1>::get_my_item(my_input, out) && res; // do get on other inputs before returning return join_helper<N-1>::get_my_item(my_input, out) && res; // do get on other inputs before returning
} }
template<typename InputTuple, typename OutputTuple> template<typename InputTuple, typename OutputTuple>
static inline bool get_items(InputTuple &my_input, OutputTuple &out ) { static inline bool get_items(InputTuple &my_input, OutputTuple &out ) {
return get_my_item(my_input, out); return get_my_item(my_input, out);
} }
template<typename InputTuple> template<typename InputTuple>
static inline void reset_my_port(InputTuple &my_input) { static inline void reset_my_port(InputTuple &my_input) {
join_helper<N-1>::reset_my_port(my_input); join_helper<N-1>::reset_my_port(my_input);
std::get<N-1>(my_input).reset_port(); tbb::flow::get<N-1>(my_input).reset_port();
} }
template<typename InputTuple> template<typename InputTuple>
static inline void reset_ports(InputTuple& my_input) { static inline void reset_ports(InputTuple& my_input) {
reset_my_port(my_input); reset_my_port(my_input);
} }
template<typename InputTuple, typename TagFuncTuple> template<typename InputTuple, typename TagFuncTuple>
static inline void set_tag_func(InputTuple &my_input, TagFuncTuple &my_tag_funcs) { static inline void set_tag_func(InputTuple &my_input, TagFuncTuple &my_tag_funcs) {
std::get<N-1>(my_input).set_my_original_tag_func(std::get<N-1>( tbb::flow::get<N-1>(my_input).set_my_original_tag_func(tbb::flo
my_tag_funcs)); w::get<N-1>(my_tag_funcs));
std::get<N-1>(my_input).set_my_tag_func(std::get<N-1>(my_input) tbb::flow::get<N-1>(my_input).set_my_tag_func(tbb::flow::get<N-
.my_original_func()->clone()); 1>(my_input).my_original_func()->clone());
std::get<N-1>(my_tag_funcs) = NULL; tbb::flow::get<N-1>(my_tag_funcs) = NULL;
join_helper<N-1>::set_tag_func(my_input, my_tag_funcs); join_helper<N-1>::set_tag_func(my_input, my_tag_funcs);
} }
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(tbb::flow::get<N-1>(other_inputs).my_original_func()) {
std::get<N-1>(my_inputs).set_my_tag_func(std::get<N-1>(othe tbb::flow::get<N-1>(my_inputs).set_my_tag_func(tbb::flow::g
r_inputs).my_original_func()->clone()); et<N-1>(other_inputs).my_original_func()->clone());
std::get<N-1>(my_inputs).set_my_original_tag_func(std::get< tbb::flow::get<N-1>(my_inputs).set_my_original_tag_func(tbb
N-1>(other_inputs).my_original_func()->clone()); ::flow::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> template<typename InputTuple>
static inline void reset_inputs(InputTuple &my_input) { static inline void reset_inputs(InputTuple &my_input) {
join_helper<N-1>::reset_inputs(my_input); join_helper<N-1>::reset_inputs(my_input);
std::get<N-1>(my_input).reinitialize_port(); tbb::flow::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); tbb::flow::get<0>( my_input ).set_join_node_pointer(port);
} }
template< typename TupleType > template< typename TupleType >
static inline void consume_reservations( TupleType &my_input ) { static inline void consume_reservations( TupleType &my_input ) {
std::get<0>( my_input ).consume(); tbb::flow::get<0>( my_input ).consume();
} }
template< typename TupleType > template< typename TupleType >
static inline void release_my_reservation( TupleType &my_input ) { static inline void release_my_reservation( TupleType &my_input ) {
std::get<0>( my_input ).release(); tbb::flow::get<0>( my_input ).release();
} }
template<typename TupleType> template<typename TupleType>
static inline void release_reservations( TupleType &my_input) { static inline void release_reservations( TupleType &my_input) {
release_my_reservation(my_input); release_my_reservation(my_input);
} }
template< typename InputTuple, typename OutputTuple > template< typename InputTuple, typename OutputTuple >
static inline bool reserve( InputTuple &my_input, OutputTuple &out) { static inline bool reserve( InputTuple &my_input, OutputTuple &out) {
return std::get<0>( my_input ).reserve( std::get<0>( out ) ); return tbb::flow::get<0>( my_input ).reserve( tbb::flow::get<0> ( out ) );
} }
template<typename InputTuple, typename OutputTuple> template<typename InputTuple, typename OutputTuple>
static inline bool get_my_item( InputTuple &my_input, OutputTuple & out) { static inline bool get_my_item( InputTuple &my_input, OutputTuple & out) {
return std::get<0>(my_input).get_item(std::get<0>(out)); return tbb::flow::get<0>(my_input).get_item(tbb::flow::get<0>(o ut));
} }
template<typename InputTuple, typename OutputTuple> template<typename InputTuple, typename OutputTuple>
static inline bool get_items(InputTuple &my_input, OutputTuple &out ) { static inline bool get_items(InputTuple &my_input, OutputTuple &out ) {
return get_my_item(my_input, out); return get_my_item(my_input, out);
} }
template<typename InputTuple> template<typename InputTuple>
static inline void reset_my_port(InputTuple &my_input) { static inline void reset_my_port(InputTuple &my_input) {
std::get<0>(my_input).reset_port(); tbb::flow::get<0>(my_input).reset_port();
} }
template<typename InputTuple> template<typename InputTuple>
static inline void reset_ports(InputTuple& my_input) { static inline void reset_ports(InputTuple& my_input) {
reset_my_port(my_input); reset_my_port(my_input);
} }
template<typename InputTuple, typename TagFuncTuple> template<typename InputTuple, typename TagFuncTuple>
static inline void set_tag_func(InputTuple &my_input, TagFuncTuple &my_tag_funcs) { static inline void set_tag_func(InputTuple &my_input, TagFuncTuple &my_tag_funcs) {
std::get<0>(my_input).set_my_original_tag_func(std::get<0>(my_t tbb::flow::get<0>(my_input).set_my_original_tag_func(tbb::flow:
ag_funcs)); :get<0>(my_tag_funcs));
std::get<0>(my_input).set_my_tag_func(std::get<0>(my_input).my_ tbb::flow::get<0>(my_input).set_my_tag_func(tbb::flow::get<0>(m
original_func()->clone()); y_input).my_original_func()->clone());
std::get<0>(my_tag_funcs) = NULL; tbb::flow::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(tbb::flow::get<0>(other_inputs).my_original_func()) {
std::get<0>(my_inputs).set_my_tag_func(std::get<0>(other_in tbb::flow::get<0>(my_inputs).set_my_tag_func(tbb::flow::get
puts).my_original_func()->clone()); <0>(other_inputs).my_original_func()->clone());
std::get<0>(my_inputs).set_my_original_tag_func(std::get<0> tbb::flow::get<0>(my_inputs).set_my_original_tag_func(tbb::
(other_inputs).my_original_func()->clone()); flow::get<0>(other_inputs).my_original_func()->clone());
} }
} }
template<typename InputTuple> template<typename InputTuple>
static inline void reset_inputs(InputTuple &my_input) { static inline void reset_inputs(InputTuple &my_input) {
std::get<0>(my_input).reinitialize_port(); tbb::flow::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:
skipping to change at line 244 skipping to change at line 246
reserving_port_operation *current; reserving_port_operation *current;
bool no_predecessors; bool no_predecessors;
while(op_list) { while(op_list) {
current = op_list; current = op_list;
op_list = op_list->next; op_list = op_list->next;
switch(current->type) { switch(current->type) {
case reg_pred: case reg_pred:
no_predecessors = my_predecessors.empty(); no_predecessors = my_predecessors.empty();
my_predecessors.add(*(current->my_pred)); my_predecessors.add(*(current->my_pred));
if ( no_predecessors ) { if ( no_predecessors ) {
my_join->decrement_port_count( ); // may try to for ward (void) my_join->decrement_port_count(true); // may try to forward
} }
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case rem_pred: case rem_pred:
my_predecessors.remove(*(current->my_pred)); my_predecessors.remove(*(current->my_pred));
if(my_predecessors.empty()) my_join->increment_port_cou nt(); if(my_predecessors.empty()) my_join->increment_port_cou nt();
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case res_item: case res_item:
if ( reserved ) { if ( reserved ) {
skipping to change at line 281 skipping to change at line 283
break; break;
case con_res: case con_res:
reserved = false; reserved = false;
my_predecessors.try_consume( ); my_predecessors.try_consume( );
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
} }
} }
} }
protected:
template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_c
ache;
template<typename X, typename Y> friend class internal::round_robin
_cache;
task *try_put_task( const T & ) {
return NULL;
}
public: public:
//! Constructor //! Constructor
reserving_port() : reserved(false) { reserving_port() : reserved(false) {
my_join = NULL; my_join = NULL;
my_predecessors.set_owner( this ); my_predecessors.set_owner( this );
my_aggregator.initialize_handler(my_handler(this)); my_aggregator.initialize_handler(my_handler(this));
} }
// copy constructor // copy constructor
skipping to change at line 302 skipping to change at line 312
reserved = false; reserved = false;
my_join = NULL; my_join = NULL;
my_predecessors.set_owner( this ); my_predecessors.set_owner( this );
my_aggregator.initialize_handler(my_handler(this)); my_aggregator.initialize_handler(my_handler(this));
} }
void set_join_node_pointer(forwarding_base *join) { void set_join_node_pointer(forwarding_base *join) {
my_join = join; my_join = join;
} }
// always rejects, so arc is reversed (and reserves can be done.)
bool try_put( const T & ) {
return false;
}
//! Add a predecessor //! Add a predecessor
bool register_predecessor( sender<T> &src ) { bool register_predecessor( sender<T> &src ) {
reserving_port_operation op_data(src, reg_pred); reserving_port_operation op_data(src, reg_pred);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.status == SUCCEEDED; return op_data.status == SUCCEEDED;
} }
//! Remove a predecessor //! Remove a predecessor
bool remove_predecessor( sender<T> &src ) { bool remove_predecessor( sender<T> &src ) {
reserving_port_operation op_data(src, rem_pred); reserving_port_operation op_data(src, rem_pred);
skipping to change at line 367 skipping to change at line 372
//! 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:
typedef T input_type; typedef T input_type;
typedef sender<T> predecessor_type; typedef sender<T> predecessor_type;
typedef queueing_port<T> my_node_type; typedef queueing_port<T> my_node_type;
// ----------- Aggregator ------------ // ----------- Aggregator ------------
private: private:
enum op_type { try__put, get__item, res_port }; enum op_type { get__item, res_port, try__put_task };
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
typedef queueing_port<T> my_class; typedef queueing_port<T> my_class;
class queueing_port_operation : public aggregated_operation<queuein g_port_operation> { class queueing_port_operation : public aggregated_operation<queuein g_port_operation> {
public: public:
char type; char type;
T my_val; T my_val;
T *my_arg; T *my_arg;
task * bypass_t;
// constructor for value parameter // constructor for value parameter
queueing_port_operation(const T& e, op_type t) : queueing_port_operation(const T& e, op_type t) :
// type(char(t)), my_val(const_cast<T>(e)) {} type(char(t)), my_val(e)
type(char(t)), my_val(e) {} , bypass_t(NULL)
{}
// constructor for pointer parameter // constructor for pointer parameter
queueing_port_operation(const T* p, op_type t) : queueing_port_operation(const T* p, op_type t) :
type(char(t)), my_arg(const_cast<T*>(p)) {} type(char(t)), my_arg(const_cast<T*>(p))
, bypass_t(NULL)
{}
// constructor with no parameter // constructor with no parameter
queueing_port_operation(op_type t) : type(char(t)) {} queueing_port_operation(op_type t) : type(char(t))
, bypass_t(NULL)
{}
}; };
typedef internal::aggregating_functor<my_class, queueing_port_opera tion> my_handler; typedef internal::aggregating_functor<my_class, queueing_port_opera tion> my_handler;
friend class internal::aggregating_functor<my_class, queueing_port_ operation>; friend class internal::aggregating_functor<my_class, queueing_port_ operation>;
aggregator<my_handler, queueing_port_operation> my_aggregator; aggregator<my_handler, queueing_port_operation> my_aggregator;
void handle_operations(queueing_port_operation* op_list) { void handle_operations(queueing_port_operation* op_list) {
queueing_port_operation *current; queueing_port_operation *current;
bool was_empty; bool was_empty;
while(op_list) { while(op_list) {
current = op_list; current = op_list;
op_list = op_list->next; op_list = op_list->next;
switch(current->type) { switch(current->type) {
case try__put: case try__put_task: {
was_empty = this->buffer_empty(); task *rtask = NULL;
this->push_back(current->my_val); was_empty = this->buffer_empty();
if (was_empty) my_join->decrement_port_count(); this->push_back(current->my_val);
__TBB_store_with_release(current->status, SUCCEEDED); if (was_empty) rtask = my_join->decrement_port_coun
t(false);
else
rtask = SUCCESSFULLY_ENQUEUED;
current->bypass_t = rtask;
__TBB_store_with_release(current->status, SUCCEEDED
);
}
break; break;
case get__item: case get__item:
if(!this->buffer_empty()) { if(!this->buffer_empty()) {
this->fetch_front(*(current->my_arg)); this->fetch_front(*(current->my_arg));
__TBB_store_with_release(current->status, SUCCEEDED ); __TBB_store_with_release(current->status, SUCCEEDED );
} }
else { else {
__TBB_store_with_release(current->status, FAILED); __TBB_store_with_release(current->status, FAILED);
} }
break; break;
case res_port: case res_port:
__TBB_ASSERT(this->item_valid(this->my_head), "No item to reset"); __TBB_ASSERT(this->item_valid(this->my_head), "No item to reset");
this->invalidate_front(); ++(this->my_head); this->invalidate_front(); ++(this->my_head);
if(this->item_valid(this->my_head)) { if(this->item_valid(this->my_head)) {
my_join->decrement_port_count(); (void)my_join->decrement_port_count(true);
} }
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
} }
} }
} }
// ------------ End Aggregator --------------- // ------------ End Aggregator ---------------
protected:
template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_c
ache;
template<typename X, typename Y> friend class internal::round_robin
_cache;
/*override*/task *try_put_task(const T &v) {
queueing_port_operation op_data(v, try__put_task);
my_aggregator.execute(&op_data);
__TBB_ASSERT(op_data.status == SUCCEEDED || !op_data.bypass_t,
"inconsistent return from aggregator");
if(!op_data.bypass_t) return SUCCESSFULLY_ENQUEUED;
return op_data.bypass_t;
}
public: public:
//! Constructor //! Constructor
queueing_port() : item_buffer<T>() { queueing_port() : item_buffer<T>() {
my_join = NULL; my_join = NULL;
my_aggregator.initialize_handler(my_handler(this)); my_aggregator.initialize_handler(my_handler(this));
} }
//! copy constructor //! copy constructor
queueing_port(const queueing_port& /* other */) : receiver<T>(), it em_buffer<T>() { queueing_port(const queueing_port& /* other */) : receiver<T>(), it em_buffer<T>() {
my_join = NULL; my_join = NULL;
my_aggregator.initialize_handler(my_handler(this)); my_aggregator.initialize_handler(my_handler(this));
} }
//! record parent for tallying available items //! record parent for tallying available items
void set_join_node_pointer(forwarding_base *join) { void set_join_node_pointer(forwarding_base *join) {
my_join = join; my_join = join;
} }
/*override*/bool try_put(const T &v) {
queueing_port_operation op_data(v, try__put);
my_aggregator.execute(&op_data);
return op_data.status == SUCCEEDED;
}
bool get_item( T &v ) { bool get_item( T &v ) {
queueing_port_operation op_data(&v, get__item); queueing_port_operation op_data(&v, get__item);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.status == SUCCEEDED; return op_data.status == SUCCEEDED;
} }
// 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);
skipping to change at line 503 skipping to change at line 526
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;
T my_val; T my_val;
T *my_arg; T *my_arg;
tag_value my_tag_value; tag_value my_tag_value;
// constructor for value parameter // constructor for value parameter
tag_matching_port_operation(const T& e, op_type t) : tag_matching_port_operation(const T& e, op_type t) :
// type(char(t)), my_val(const_cast<T>(e)) {}
type(char(t)), my_val(e) {} type(char(t)), my_val(e) {}
// constructor for pointer parameter // constructor for pointer parameter
tag_matching_port_operation(const T* p, op_type t) : tag_matching_port_operation(const T* p, op_type t) :
type(char(t)), my_arg(const_cast<T*>(p)) {} type(char(t)), my_arg(const_cast<T*>(p)) {}
// constructor with no parameter // constructor with no parameter
tag_matching_port_operation(op_type t) : type(char(t)) {} tag_matching_port_operation(op_type t) : type(char(t)) {}
}; };
typedef internal::aggregating_functor<my_class, tag_matching_port_o peration> my_handler; typedef internal::aggregating_functor<my_class, tag_matching_port_o peration> my_handler;
friend class internal::aggregating_functor<my_class, tag_matching_p ort_operation>; friend class internal::aggregating_functor<my_class, tag_matching_p ort_operation>;
skipping to change at line 544 skipping to change at line 566
break; break;
case res_port: case res_port:
// use current_tag from FE for item // use current_tag from FE for item
this->tagged_delete(my_join->current_tag); this->tagged_delete(my_join->current_tag);
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
} }
} }
} }
// ------------ End Aggregator --------------- // ------------ End Aggregator ---------------
protected:
template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_c
ache;
template<typename X, typename Y> friend class internal::round_robin
_cache;
/*override*/task *try_put_task(const T& v) {
tag_matching_port_operation op_data(v, try__put);
op_data.my_tag_value = (*my_tag_func)(v);
task *rtask = NULL;
my_aggregator.execute(&op_data);
if(op_data.status == SUCCEEDED) {
rtask = my_join->increment_tag_count(op_data.my_tag_value,
false); // may spawn
// rtask has to reflect the return status of the try_put
if(!rtask) rtask = SUCCESSFULLY_ENQUEUED;
}
return rtask;
}
public: public:
tag_matching_port() : receiver<T>(), tagged_buffer<tag_value, T, NO _TAG>() { tag_matching_port() : receiver<T>(), tagged_buffer<tag_value, T, NO _TAG>() {
my_join = NULL; my_join = NULL;
my_tag_func = NULL; my_tag_func = NULL;
my_original_tag_func = NULL; my_original_tag_func = NULL;
my_aggregator.initialize_handler(my_handler(this)); my_aggregator.initialize_handler(my_handler(this));
} }
// copy constructor // copy constructor
skipping to change at line 579 skipping to change at line 618
} }
void set_my_original_tag_func(my_tag_func_type *f) { void set_my_original_tag_func(my_tag_func_type *f) {
my_original_tag_func = f; my_original_tag_func = f;
} }
void set_my_tag_func(my_tag_func_type *f) { void set_my_tag_func(my_tag_func_type *f) {
my_tag_func = f; my_tag_func = f;
} }
/*override*/bool try_put(const T& v) {
tag_matching_port_operation op_data(v, try__put);
op_data.my_tag_value = (*my_tag_func)(v);
my_aggregator.execute(&op_data);
if(op_data.status == SUCCEEDED) {
// the assertion in the aggregator above will ensure we do
not call with the same
// tag twice. We have to exit the aggregator to keep lock-
ups from happening;
// the increment of the tag hash table in the FE is under a
separate aggregator,
// so that is serialized.
// is a race possible? I do not believe so; the increment
may cause a build of
// an output tuple, but its component is already in the has
h table for the port.
my_join->increment_tag_count(op_data.my_tag_value); // may
spawn
}
return op_data.status == SUCCEEDED;
}
bool get_item( T &v ) { bool get_item( T &v ) {
tag_matching_port_operation op_data(&v, get__item); tag_matching_port_operation op_data(&v, get__item);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.status == SUCCEEDED; return op_data.status == SUCCEEDED;
} }
// 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() {
tag_matching_port_operation op_data(res_port); tag_matching_port_operation op_data(res_port);
skipping to change at line 642 skipping to change at line 664
template<graph_buffer_policy JP, typename InputTuple, typename OutputTu ple> template<graph_buffer_policy JP, typename InputTuple, typename OutputTu ple>
class join_node_base; class join_node_base;
//! join_node_FE : implements input port policy //! join_node_FE : implements input port policy
template<graph_buffer_policy JP, typename InputTuple, typename OutputTu ple> template<graph_buffer_policy JP, typename InputTuple, typename OutputTu ple>
class join_node_FE; class join_node_FE;
template<typename InputTuple, typename OutputTuple> template<typename InputTuple, typename OutputTuple>
class join_node_FE<reserving, InputTuple, OutputTuple> : public forward ing_base { class join_node_FE<reserving, InputTuple, OutputTuple> : public forward ing_base {
public: public:
static const int N = std::tuple_size<OutputTuple>::value; static const int N = tbb::flow::tuple_size<OutputTuple>::value;
typedef OutputTuple output_type; typedef OutputTuple output_type;
typedef InputTuple input_type; typedef InputTuple input_type;
typedef join_node_base<reserving, InputTuple, OutputTuple> my_node_ type; // for forwarding typedef join_node_base<reserving, InputTuple, OutputTuple> my_node_ type; // for forwarding
join_node_FE(graph &g) : forwarding_base(g.root_task()), my_node(NU LL) { join_node_FE(graph &g) : forwarding_base(g.root_task()), my_node(NU LL) {
ports_with_no_inputs = N; ports_with_no_inputs = N;
join_helper<N>::set_join_node_pointer(my_inputs, this); join_helper<N>::set_join_node_pointer(my_inputs, this);
} }
join_node_FE(const join_node_FE& other) : forwarding_base(other.my_ root_task), my_node(NULL) { join_node_FE(const join_node_FE& other) : forwarding_base(other.my_ root_task), my_node(NULL) {
skipping to change at line 664 skipping to change at line 686
join_helper<N>::set_join_node_pointer(my_inputs, this); join_helper<N>::set_join_node_pointer(my_inputs, this);
} }
void set_my_node(my_node_type *new_my_node) { my_node = new_my_node ; } void set_my_node(my_node_type *new_my_node) { my_node = new_my_node ; }
void increment_port_count() { void increment_port_count() {
++ports_with_no_inputs; ++ports_with_no_inputs;
} }
// 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() { task * decrement_port_count(bool handle_task) {
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( task *rtask = new ( task::allocate_additional_child_of( *(t
*(this->my_root_task) ) ) his->my_root_task) ) )
forward_task<my_node_type>(*my_node) ); forward_task_bypass
<my_node_type>(*my_node);
if(!handle_task) return rtask;
task::enqueue(*rtask);
} }
return NULL;
} }
input_type &input_ports() { return my_inputs; } input_type &input_ports() { return my_inputs; }
protected: protected:
void reset() { void reset() {
// called outside of parallel contexts // called outside of parallel contexts
ports_with_no_inputs = N; ports_with_no_inputs = N;
join_helper<N>::reset_inputs(my_inputs); join_helper<N>::reset_inputs(my_inputs);
skipping to change at line 707 skipping to change at line 733
} }
input_type my_inputs; input_type my_inputs;
my_node_type *my_node; my_node_type *my_node;
atomic<size_t> ports_with_no_inputs; atomic<size_t> ports_with_no_inputs;
}; };
template<typename InputTuple, typename OutputTuple> template<typename InputTuple, typename OutputTuple>
class join_node_FE<queueing, InputTuple, OutputTuple> : public forwardi ng_base { class join_node_FE<queueing, InputTuple, OutputTuple> : public forwardi ng_base {
public: public:
static const int N = std::tuple_size<OutputTuple>::value; static const int N = tbb::flow::tuple_size<OutputTuple>::value;
typedef OutputTuple output_type; typedef OutputTuple output_type;
typedef InputTuple input_type; typedef InputTuple input_type;
typedef join_node_base<queueing, InputTuple, OutputTuple> my_node_t ype; // for forwarding typedef join_node_base<queueing, InputTuple, OutputTuple> my_node_t ype; // for forwarding
join_node_FE(graph &g) : forwarding_base(g.root_task()), my_node(NU LL) { join_node_FE(graph &g) : forwarding_base(g.root_task()), my_node(NU LL) {
ports_with_no_items = N; ports_with_no_items = N;
join_helper<N>::set_join_node_pointer(my_inputs, this); join_helper<N>::set_join_node_pointer(my_inputs, this);
} }
join_node_FE(const join_node_FE& other) : forwarding_base(other.my_ root_task), my_node(NULL) { join_node_FE(const join_node_FE& other) : forwarding_base(other.my_ root_task), my_node(NULL) {
skipping to change at line 730 skipping to change at line 756
} }
// needed for forwarding // needed for forwarding
void set_my_node(my_node_type *new_my_node) { my_node = new_my_node ; } void set_my_node(my_node_type *new_my_node) { my_node = new_my_node ; }
void reset_port_count() { void reset_port_count() {
ports_with_no_items = N; ports_with_no_items = N;
} }
// if all input_ports have items, spawn forward to try and consume tuples // if all input_ports have items, spawn forward to try and consume tuples
void decrement_port_count() { task * decrement_port_count(bool handle_task)
{
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( task *rtask = new ( task::allocate_additional_child_of( *(t
*(this->my_root_task) ) ) his->my_root_task) ) )
forward_task<my_node_type>(*my_node) ); forward_task_bypass
<my_node_type>(*my_node);
if(!handle_task) return rtask;
task::enqueue( *rtask);
} }
return 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() { void reset() {
reset_port_count(); reset_port_count();
skipping to change at line 775 skipping to change at line 806
} }
input_type my_inputs; input_type my_inputs;
my_node_type *my_node; my_node_type *my_node;
atomic<size_t> ports_with_no_items; atomic<size_t> ports_with_no_items;
}; };
// tag_matching join input port. // tag_matching join input port.
template<typename InputTuple, typename OutputTuple> template<typename InputTuple, typename OutputTuple>
class join_node_FE<tag_matching, InputTuple, OutputTuple> : public forw arding_base, class join_node_FE<tag_matching, InputTuple, OutputTuple> : public forw arding_base,
// buffer of tag value counts buffer of output items
public tagged_buffer<tag_value, size_t, NO_TAG>, public item_b uffer<OutputTuple> { public tagged_buffer<tag_value, size_t, NO_TAG>, public item_b uffer<OutputTuple> {
public: public:
static const int N = std::tuple_size<OutputTuple>::value; static const int N = tbb::flow::tuple_size<OutputTuple>::value;
typedef OutputTuple output_type; typedef OutputTuple output_type;
typedef InputTuple input_type; typedef InputTuple input_type;
typedef tagged_buffer<tag_value, size_t, NO_TAG> my_tag_buffer; typedef tagged_buffer<tag_value, size_t, NO_TAG> my_tag_buffer;
typedef item_buffer<output_type> output_buffer_type; typedef item_buffer<output_type> output_buffer_type;
typedef join_node_base<tag_matching, InputTuple, OutputTuple> my_no de_type; // for forwarding typedef join_node_base<tag_matching, InputTuple, OutputTuple> my_no de_type; // for forwarding
// ----------- Aggregator ------------ // ----------- Aggregator ------------
// the aggregator is only needed to serialize the access to the has h table. // the aggregator is only needed to serialize the access to the has h table.
// and the output_buffer_type base class // and the output_buffer_type base class
private: private:
skipping to change at line 799 skipping to change at line 831
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
typedef join_node_FE<tag_matching, InputTuple, OutputTuple> my_clas s; typedef join_node_FE<tag_matching, InputTuple, OutputTuple> my_clas s;
class tag_matching_FE_operation : public aggregated_operation<tag_m atching_FE_operation> { class tag_matching_FE_operation : public aggregated_operation<tag_m atching_FE_operation> {
public: public:
char type; char type;
union { union {
tag_value my_val; tag_value my_val;
output_type* my_output; output_type* my_output;
}; };
task *bypass_t;
bool enqueue_task;
// constructor for value parameter // constructor for value parameter
tag_matching_FE_operation(const tag_value& e, op_type t) : tag_matching_FE_operation(const tag_value& e , bool q_task , op
// type(char(t)), my_val(const_cast<T>(e)) {} _type t) : type(char(t)), my_val(e),
type(char(t)), my_val(e) {} bypass_t(NULL), enqueue_task(q_task) {}
tag_matching_FE_operation(output_type *p, op_type t) : tag_matching_FE_operation(output_type *p, op_type t) : type(cha
type(char(t)), my_output(p) {} r(t)), my_output(p), bypass_t(NULL),
enqueue_task(true) {}
// constructor with no parameter // constructor with no parameter
tag_matching_FE_operation(op_type t) : type(char(t)) {} tag_matching_FE_operation(op_type t) : type(char(t)), bypass_t( NULL), enqueue_task(true) {}
}; };
typedef internal::aggregating_functor<my_class, tag_matching_FE_ope ration> my_handler; typedef internal::aggregating_functor<my_class, tag_matching_FE_ope ration> my_handler;
friend class internal::aggregating_functor<my_class, tag_matching_F E_operation>; friend class internal::aggregating_functor<my_class, tag_matching_F E_operation>;
aggregator<my_handler, tag_matching_FE_operation> my_aggregator; aggregator<my_handler, tag_matching_FE_operation> my_aggregator;
// called from aggregator, so serialized // called from aggregator, so serialized
void fill_output_buffer(bool should_enqueue) { // construct as many output objects as possible.
// returns a task pointer if the a task would have been enqueued bu
t we asked that
// it be returned. Otherwise returns NULL.
task * fill_output_buffer(bool should_enqueue, bool handle_task) {
output_type l_out; output_type l_out;
task *rtask = NULL;
bool do_fwd = should_enqueue && this->buffer_empty(); bool do_fwd = should_enqueue && this->buffer_empty();
while(find_value_tag(this->current_tag,N)) { while(find_value_tag(this->current_tag,N)) { // while there ar
this->tagged_delete(this->current_tag); e completed items
this->tagged_delete(this->current_tag); // remove the tag
if(join_helper<N>::get_items(my_inputs, l_out)) { // <== call back if(join_helper<N>::get_items(my_inputs, l_out)) { // <== call back
this->push_back(l_out); this->push_back(l_out);
if(do_fwd) { if(do_fwd) { // we enqueue if receiving an item from p
task::enqueue( * new ( task::allocate_additional_ch redecessor, not if successor asks for item
ild_of( *(this->my_root_task) ) ) rtask = new ( task::allocate_additional_child_of( *
forward_task<my_node_type>(*my_node) ); (this->my_root_task) ) )
forward_task_bypass<my_node_type>(*my_node);
if(handle_task) {
task::enqueue(*rtask);
rtask = NULL;
}
do_fwd = false; do_fwd = false;
} }
// retire the input values // retire the input values
join_helper<N>::reset_ports(my_inputs); // <== call b ack join_helper<N>::reset_ports(my_inputs); // <== call b ack
this->current_tag = NO_TAG; this->current_tag = NO_TAG;
} }
else { else {
__TBB_ASSERT(false, "should have had something to push" ); __TBB_ASSERT(false, "should have had something to push" );
} }
} }
return rtask;
} }
void handle_operations(tag_matching_FE_operation* op_list) { void handle_operations(tag_matching_FE_operation* op_list) {
tag_matching_FE_operation *current; tag_matching_FE_operation *current;
while(op_list) { while(op_list) {
current = op_list; current = op_list;
op_list = op_list->next; op_list = op_list->next;
switch(current->type) { switch(current->type) {
case res_count: // called from BE case res_count: // called from BE
{ {
output_type l_out; output_type l_out;
this->pop_front(l_out); // don't care about return ed value. this->pop_front(l_out); // don't care about return ed value.
// buffer as many tuples as we can make // buffer as many tuples as we can make
fill_output_buffer(true); (void)fill_output_buffer(true, true);
__TBB_store_with_release(current->status, SUCCEEDED ); __TBB_store_with_release(current->status, SUCCEEDED );
} }
break; break;
case inc_count: { // called from input ports case inc_count: { // called from input ports
size_t *p = 0; size_t *p = 0;
tag_value t = current->my_val; tag_value t = current->my_val;
bool do_enqueue = current->enqueue_task;
if(!(this->tagged_find_ref(t,p))) { if(!(this->tagged_find_ref(t,p))) {
this->tagged_insert(t, 0); this->tagged_insert(t, 0);
if(!(this->tagged_find_ref(t,p))) { if(!(this->tagged_find_ref(t,p))) {
__TBB_ASSERT(false, NULL); __TBB_ASSERT(false, "should find tag after inserting it");
} }
} }
if(++(*p) == size_t(N)) { if(++(*p) == size_t(N)) {
task::enqueue( * new ( task::allocate_additiona task *rtask = fill_output_buffer(true, do_enque
l_child_of( *(this->my_root_task) ) ) ue);
forward_task<my_node_type>(*my_node) ); __TBB_ASSERT(!rtask || !do_enqueue, "task shoul
d not be returned");
current->bypass_t = rtask;
} }
} }
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case may_succeed: // called from BE case may_succeed: // called from BE
fill_output_buffer(false); (void)fill_output_buffer(false, /*handle_task*/true); // handle_task not used
__TBB_store_with_release(current->status, this->buffer_ empty() ? FAILED : SUCCEEDED); __TBB_store_with_release(current->status, this->buffer_ empty() ? FAILED : SUCCEEDED);
break; break;
case try_make: // called from BE case try_make: // called from BE
if(this->buffer_empty()) { if(this->buffer_empty()) {
__TBB_store_with_release(current->status, FAILED); __TBB_store_with_release(current->status, FAILED);
} }
else { else {
this->fetch_front(*(current->my_output)); this->fetch_front(*(current->my_output));
__TBB_store_with_release(current->status, SUCCEEDED ); __TBB_store_with_release(current->status, SUCCEEDED );
} }
skipping to change at line 911 skipping to change at line 955
// needed for forwarding // needed for forwarding
void set_my_node(my_node_type *new_my_node) { my_node = new_my_node ; } void set_my_node(my_node_type *new_my_node) { my_node = new_my_node ; }
void reset_port_count() { // called from BE void reset_port_count() { // called from BE
tag_matching_FE_operation op_data(res_count); tag_matching_FE_operation op_data(res_count);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return; return;
} }
// if all input_ports have items, spawn forward to try and consume tuples // if all input_ports have items, spawn forward to try and consume tuples
void increment_tag_count(tag_value t) { // called from input_ports // return a task if we are asked and did create one.
tag_matching_FE_operation op_data(t, inc_count); task *increment_tag_count(tag_value t, bool handle_task) { // call
ed from input_ports
tag_matching_FE_operation op_data(t, handle_task, inc_count);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return; return op_data.bypass_t;
} }
void decrement_port_count() { __TBB_ASSERT(false, NULL); } /*override*/ task *decrement_port_count(bool /*handle_task*/) { __T BB_ASSERT(false, NULL); return 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() { void reset() {
// called outside of parallel contexts // called outside of parallel contexts
join_helper<N>::reset_inputs(my_inputs); join_helper<N>::reset_inputs(my_inputs);
skipping to change at line 966 skipping to change at line 1011
} }
input_type my_inputs; // input ports input_type my_inputs; // input ports
my_node_type *my_node; my_node_type *my_node;
}; // join_node_FE<tag_matching, InputTuple, OutputTuple> }; // join_node_FE<tag_matching, InputTuple, OutputTuple>
//! join_node_base //! join_node_base
template<graph_buffer_policy JP, typename InputTuple, typename OutputTu ple> template<graph_buffer_policy JP, typename InputTuple, typename OutputTu ple>
class join_node_base : public graph_node, public join_node_FE<JP, Input Tuple, OutputTuple>, class join_node_base : public graph_node, public join_node_FE<JP, Input Tuple, OutputTuple>,
public sender<OutputTuple> { public sender<OutputTuple> {
protected:
using graph_node::my_graph; using graph_node::my_graph;
public: public:
typedef OutputTuple output_type; typedef OutputTuple output_type;
typedef receiver<output_type> successor_type; typedef receiver<output_type> successor_type;
typedef join_node_FE<JP, InputTuple, OutputTuple> input_ports_type; typedef join_node_FE<JP, InputTuple, OutputTuple> input_ports_type;
using input_ports_type::tuple_build_may_succeed; using input_ports_type::tuple_build_may_succeed;
using input_ports_type::try_to_make_tuple; using input_ports_type::try_to_make_tuple;
using input_ports_type::tuple_accepted; using input_ports_type::tuple_accepted;
using input_ports_type::tuple_rejected; using input_ports_type::tuple_rejected;
private: private:
// ----------- Aggregator ------------ // ----------- Aggregator ------------
enum op_type { reg_succ, rem_succ, try__get, do_fwrd }; enum op_type { reg_succ, rem_succ, try__get, do_fwrd, do_fwrd_bypas s };
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
typedef join_node_base<JP,InputTuple,OutputTuple> my_class; typedef join_node_base<JP,InputTuple,OutputTuple> my_class;
class join_node_base_operation : public aggregated_operation<join_n ode_base_operation> { class join_node_base_operation : public aggregated_operation<join_n ode_base_operation> {
public: public:
char type; char type;
union { union {
output_type *my_arg; output_type *my_arg;
successor_type *my_succ; successor_type *my_succ;
}; };
join_node_base_operation(const output_type& e, op_type t) : task *bypass_t;
type(char(t)), my_arg(const_cast<output_type*>(&e)) {} join_node_base_operation(const output_type& e, op_type t) : typ
e(char(t)),
my_arg(const_cast<output_type*>(&e)), bypass_t(NULL) {}
join_node_base_operation(const successor_type &s, op_type t) : type(char(t)), join_node_base_operation(const successor_type &s, op_type t) : type(char(t)),
my_succ(const_cast<successor_type *>(&s)) {} my_succ(const_cast<successor_type *>(&s)), bypass_t(NULL) {
join_node_base_operation(op_type t) : type(char(t)) {} }
join_node_base_operation(op_type t) : type(char(t)), bypass_t(N
ULL) {}
}; };
typedef internal::aggregating_functor<my_class, join_node_base_oper ation> my_handler; typedef internal::aggregating_functor<my_class, join_node_base_oper ation> my_handler;
friend class internal::aggregating_functor<my_class, join_node_base _operation>; friend class internal::aggregating_functor<my_class, join_node_base _operation>;
bool forwarder_busy; bool forwarder_busy;
aggregator<my_handler, join_node_base_operation> my_aggregator; aggregator<my_handler, join_node_base_operation> my_aggregator;
void handle_operations(join_node_base_operation* op_list) { void handle_operations(join_node_base_operation* op_list) {
join_node_base_operation *current; join_node_base_operation *current;
while(op_list) { while(op_list) {
current = op_list; current = op_list;
op_list = op_list->next; op_list = op_list->next;
switch(current->type) { switch(current->type) {
case reg_succ: case reg_succ:
my_successors.register_successor(*(current->my_succ)); my_successors.register_successor(*(current->my_succ));
if(tuple_build_may_succeed() && !forwarder_busy) { if(tuple_build_may_succeed() && !forwarder_busy) {
task::enqueue( * new ( task::allocate_additional_ch task *rtask = new ( task::allocate_additional_child
ild_of(*(this->my_root_task)) ) _of(*(this->my_root_task)) )
forward_task<join_node_base<JP,InputTuple,O forward_task_bypass
utputTuple> >(*this)); <join_node_base<JP,InputTuple,OutputTuple>
>(*this);
task::enqueue(*rtask);
forwarder_busy = true; forwarder_busy = true;
} }
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case rem_succ: case rem_succ:
my_successors.remove_successor(*(current->my_succ)); my_successors.remove_successor(*(current->my_succ));
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case try__get: case try__get:
if(tuple_build_may_succeed()) { if(tuple_build_may_succeed()) {
if(try_to_make_tuple(*(current->my_arg))) { if(try_to_make_tuple(*(current->my_arg))) {
tuple_accepted(); tuple_accepted();
__TBB_store_with_release(current->status, SUCCE EDED); __TBB_store_with_release(current->status, SUCCE EDED);
} }
else __TBB_store_with_release(current->status, FAIL ED); else __TBB_store_with_release(current->status, FAIL ED);
} }
else __TBB_store_with_release(current->status, FAILED); else __TBB_store_with_release(current->status, FAILED);
break; break;
case do_fwrd: { case do_fwrd_bypass: {
bool build_succeeded; bool build_succeeded;
task *last_task = NULL;
output_type out; output_type out;
if(tuple_build_may_succeed()) { if(tuple_build_may_succeed()) {
do { do {
build_succeeded = try_to_make_tuple(out); build_succeeded = try_to_make_tuple(out);
if(build_succeeded) { if(build_succeeded) {
if(my_successors.try_put(out)) { task *new_task = my_successors.try_put_
task(out);
last_task = combine_tasks(last_task, ne
w_task);
if(new_task) {
tuple_accepted(); tuple_accepted();
} }
else { else {
tuple_rejected(); tuple_rejected();
build_succeeded = false; build_succeeded = false;
} }
} }
} while(build_succeeded); } while(build_succeeded);
} }
current->bypass_t = last_task;
__TBB_store_with_release(current->status, SUCCEEDED ); __TBB_store_with_release(current->status, SUCCEEDED );
forwarder_busy = false; forwarder_busy = false;
} }
break; break;
} }
} }
} }
// ---------- end aggregator ----------- // ---------- end aggregator -----------
public: public:
join_node_base(graph &g) : graph_node(g), input_ports_type(g), forw arder_busy(false) { join_node_base(graph &g) : graph_node(g), input_ports_type(g), forw arder_busy(false) {
skipping to change at line 1105 skipping to change at line 1158
protected: protected:
/*override*/void reset() { /*override*/void reset() {
input_ports_type::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 friend class forward_task_bypass< join_node_base<JP, InputTuple, Ou
le> >; tputTuple> >;
task *forward_task() {
void forward() { join_node_base_operation op_data(do_fwrd_bypass);
join_node_base_operation op_data(do_fwrd);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.bypass_t;
} }
}; };
// join base class type generator // join base class type generator
template<int N, template<class> class PT, typename OutputTuple, graph_b uffer_policy JP> template<int N, template<class> class PT, typename OutputTuple, graph_b uffer_policy JP>
struct join_base { struct join_base {
typedef typename internal::join_node_base<JP, typename wrap_tuple_e lements<N,PT,OutputTuple>::type, OutputTuple> type; typedef typename internal::join_node_base<JP, typename wrap_tuple_e lements<N,PT,OutputTuple>::type, OutputTuple> type;
}; };
//! unfolded_join_node : passes input_ports_type to join_node_base. We build the input port type //! unfolded_join_node : passes input_ports_type to join_node_base. We build the input port type
// using tuple_element. The class PT is the port type (reserving_port , queueing_port, tag_matching_port) // using tuple_element. The class PT is the port type (reserving_port , queueing_port, tag_matching_port)
skipping to change at line 1141 skipping to change at line 1195
unfolded_join_node(graph &g) : base_type(g) {} unfolded_join_node(graph &g) : base_type(g) {}
unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {} unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {}
}; };
// tag_matching unfolded_join_node. This must be a separate specializa tion because the constructors // tag_matching unfolded_join_node. This must be a separate specializa tion because the constructors
// differ. // differ.
template<typename OutputTuple> template<typename OutputTuple>
class unfolded_join_node<2,tag_matching_port,OutputTuple,tag_matching> : public class unfolded_join_node<2,tag_matching_port,OutputTuple,tag_matching> : public
join_base<2,tag_matching_port,OutputTuple,tag_matching>::type { join_base<2,tag_matching_port,OutputTuple,tag_matching>::type {
typedef typename std::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0;
typedef typename std::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1;
public: public:
typedef typename wrap_tuple_elements<2,tag_matching_port,OutputTupl e>::type input_ports_type; typedef typename wrap_tuple_elements<2,tag_matching_port,OutputTupl e>::type input_ports_type;
typedef OutputTuple output_type; typedef OutputTuple output_type;
private: private:
typedef join_node_base<tag_matching, input_ports_type, output_type > base_type; typedef join_node_base<tag_matching, input_ports_type, output_type > base_type;
typedef typename internal::function_body<T0, tag_value> *f0_p; typedef typename internal::function_body<T0, tag_value> *f0_p;
typedef typename internal::function_body<T1, tag_value> *f1_p; typedef typename internal::function_body<T1, tag_value> *f1_p;
typedef typename std::tuple< f0_p, f1_p > func_initializer_type; typedef typename tbb::flow::tuple< f0_p, f1_p > func_initializer_ty pe;
public: public:
template<typename B0, typename B1> template<typename B0, typename B1>
unfolded_join_node(graph &g, B0 b0, B1 b1) : base_type(g, unfolded_join_node(graph &g, B0 b0, B1 b1) : base_type(g,
func_initializer_type( func_initializer_type(
new internal::function_body_leaf<T0, tag_value, B0>(b0) , new internal::function_body_leaf<T0, tag_value, B0>(b0) ,
new internal::function_body_leaf<T1, tag_value, B1>(b1) new internal::function_body_leaf<T1, tag_value, B1>(b1)
) ) {} ) ) {}
unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {} unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {}
}; };
template<typename OutputTuple> template<typename OutputTuple>
class unfolded_join_node<3,tag_matching_port,OutputTuple,tag_matching> : public class unfolded_join_node<3,tag_matching_port,OutputTuple,tag_matching> : public
join_base<3,tag_matching_port,OutputTuple,tag_matching>::type { join_base<3,tag_matching_port,OutputTuple,tag_matching>::type {
typedef typename std::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0;
typedef typename std::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1;
typedef typename std::tuple_element<2, OutputTuple>::type T2; typedef typename tbb::flow::tuple_element<2, OutputTuple>::type T2;
public: public:
typedef typename wrap_tuple_elements<3, tag_matching_port, OutputTu ple>::type input_ports_type; typedef typename wrap_tuple_elements<3, tag_matching_port, OutputTu ple>::type input_ports_type;
typedef OutputTuple output_type; typedef OutputTuple output_type;
private: private:
typedef join_node_base<tag_matching, input_ports_type, output_type > base_type; typedef join_node_base<tag_matching, input_ports_type, output_type > base_type;
typedef typename internal::function_body<T0, tag_value> *f0_p; typedef typename internal::function_body<T0, tag_value> *f0_p;
typedef typename internal::function_body<T1, tag_value> *f1_p; typedef typename internal::function_body<T1, tag_value> *f1_p;
typedef typename internal::function_body<T2, tag_value> *f2_p; typedef typename internal::function_body<T2, tag_value> *f2_p;
typedef typename std::tuple< f0_p, f1_p, f2_p > func_initializer_ty pe; typedef typename tbb::flow::tuple< f0_p, f1_p, f2_p > func_initiali zer_type;
public: public:
template<typename B0, typename B1, typename B2> template<typename B0, typename B1, typename B2>
unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2) : base_type(g, unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2) : base_type(g,
func_initializer_type( func_initializer_type(
new internal::function_body_leaf<T0, tag_value, B0>(b0) , new internal::function_body_leaf<T0, tag_value, B0>(b0) ,
new internal::function_body_leaf<T1, tag_value, B1>(b1) , new internal::function_body_leaf<T1, tag_value, B1>(b1) ,
new internal::function_body_leaf<T2, tag_value, B2>(b2) new internal::function_body_leaf<T2, tag_value, B2>(b2)
) ) {} ) ) {}
unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {} unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {}
}; };
template<typename OutputTuple> template<typename OutputTuple>
class unfolded_join_node<4,tag_matching_port,OutputTuple,tag_matching> : public class unfolded_join_node<4,tag_matching_port,OutputTuple,tag_matching> : public
join_base<4,tag_matching_port,OutputTuple,tag_matching>::type { join_base<4,tag_matching_port,OutputTuple,tag_matching>::type {
typedef typename std::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0;
typedef typename std::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1;
typedef typename std::tuple_element<2, OutputTuple>::type T2; typedef typename tbb::flow::tuple_element<2, OutputTuple>::type T2;
typedef typename std::tuple_element<3, OutputTuple>::type T3; typedef typename tbb::flow::tuple_element<3, OutputTuple>::type T3;
public: public:
typedef typename wrap_tuple_elements<4, tag_matching_port, OutputTu ple>::type input_ports_type; typedef typename wrap_tuple_elements<4, tag_matching_port, OutputTu ple>::type input_ports_type;
typedef OutputTuple output_type; typedef OutputTuple output_type;
private: private:
typedef join_node_base<tag_matching, input_ports_type, output_type > base_type; typedef join_node_base<tag_matching, input_ports_type, output_type > base_type;
typedef typename internal::function_body<T0, tag_value> *f0_p; typedef typename internal::function_body<T0, tag_value> *f0_p;
typedef typename internal::function_body<T1, tag_value> *f1_p; typedef typename internal::function_body<T1, tag_value> *f1_p;
typedef typename internal::function_body<T2, tag_value> *f2_p; typedef typename internal::function_body<T2, tag_value> *f2_p;
typedef typename internal::function_body<T3, tag_value> *f3_p; typedef typename internal::function_body<T3, tag_value> *f3_p;
typedef typename std::tuple< f0_p, f1_p, f2_p, f3_p > func_initiali zer_type; typedef typename tbb::flow::tuple< f0_p, f1_p, f2_p, f3_p > func_in itializer_type;
public: public:
template<typename B0, typename B1, typename B2, typename B3> template<typename B0, typename B1, typename B2, typename B3>
unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3) : base_typ e(g, unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3) : base_typ e(g,
func_initializer_type( func_initializer_type(
new internal::function_body_leaf<T0, tag_value, B0>(b0) , new internal::function_body_leaf<T0, tag_value, B0>(b0) ,
new internal::function_body_leaf<T1, tag_value, B1>(b1) , new internal::function_body_leaf<T1, tag_value, B1>(b1) ,
new internal::function_body_leaf<T2, tag_value, B2>(b2) , new internal::function_body_leaf<T2, tag_value, B2>(b2) ,
new internal::function_body_leaf<T3, tag_value, B3>(b3) new internal::function_body_leaf<T3, tag_value, B3>(b3)
) ) {} ) ) {}
unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {} unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {}
}; };
template<typename OutputTuple> template<typename OutputTuple>
class unfolded_join_node<5,tag_matching_port,OutputTuple,tag_matching> : public class unfolded_join_node<5,tag_matching_port,OutputTuple,tag_matching> : public
join_base<5,tag_matching_port,OutputTuple,tag_matching>::type { join_base<5,tag_matching_port,OutputTuple,tag_matching>::type {
typedef typename std::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0;
typedef typename std::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1;
typedef typename std::tuple_element<2, OutputTuple>::type T2; typedef typename tbb::flow::tuple_element<2, OutputTuple>::type T2;
typedef typename std::tuple_element<3, OutputTuple>::type T3; typedef typename tbb::flow::tuple_element<3, OutputTuple>::type T3;
typedef typename std::tuple_element<4, OutputTuple>::type T4; typedef typename tbb::flow::tuple_element<4, OutputTuple>::type T4;
public: public:
typedef typename wrap_tuple_elements<5, tag_matching_port, OutputTu ple>::type input_ports_type; typedef typename wrap_tuple_elements<5, tag_matching_port, OutputTu ple>::type input_ports_type;
typedef OutputTuple output_type; typedef OutputTuple output_type;
private: private:
typedef join_node_base<tag_matching, input_ports_type, output_type > base_type; typedef join_node_base<tag_matching, input_ports_type, output_type > base_type;
typedef typename internal::function_body<T0, tag_value> *f0_p; typedef typename internal::function_body<T0, tag_value> *f0_p;
typedef typename internal::function_body<T1, tag_value> *f1_p; typedef typename internal::function_body<T1, tag_value> *f1_p;
typedef typename internal::function_body<T2, tag_value> *f2_p; typedef typename internal::function_body<T2, tag_value> *f2_p;
typedef typename internal::function_body<T3, tag_value> *f3_p; typedef typename internal::function_body<T3, tag_value> *f3_p;
typedef typename internal::function_body<T4, tag_value> *f4_p; typedef typename internal::function_body<T4, tag_value> *f4_p;
typedef typename std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p > func_in itializer_type; typedef typename tbb::flow::tuple< f0_p, f1_p, f2_p, f3_p, f4_p > f unc_initializer_type;
public: public:
template<typename B0, typename B1, typename B2, typename B3, typena me B4> template<typename B0, typename B1, typename B2, typename B3, typena me B4>
unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4) : b ase_type(g, unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4) : b ase_type(g,
func_initializer_type( func_initializer_type(
new internal::function_body_leaf<T0, tag_value, B0>(b0) , new internal::function_body_leaf<T0, tag_value, B0>(b0) ,
new internal::function_body_leaf<T1, tag_value, B1>(b1) , new internal::function_body_leaf<T1, tag_value, B1>(b1) ,
new internal::function_body_leaf<T2, tag_value, B2>(b2) , new internal::function_body_leaf<T2, tag_value, B2>(b2) ,
new internal::function_body_leaf<T3, tag_value, B3>(b3) , new internal::function_body_leaf<T3, tag_value, B3>(b3) ,
new internal::function_body_leaf<T4, tag_value, B4>(b4) new internal::function_body_leaf<T4, tag_value, B4>(b4)
) ) {} ) ) {}
unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {} unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {}
}; };
#if __TBB_VARIADIC_MAX >= 6 #if __TBB_VARIADIC_MAX >= 6
template<typename OutputTuple> template<typename OutputTuple>
class unfolded_join_node<6,tag_matching_port,OutputTuple,tag_matching> : public class unfolded_join_node<6,tag_matching_port,OutputTuple,tag_matching> : public
join_base<6,tag_matching_port,OutputTuple,tag_matching>::type { join_base<6,tag_matching_port,OutputTuple,tag_matching>::type {
typedef typename std::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0;
typedef typename std::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1;
typedef typename std::tuple_element<2, OutputTuple>::type T2; typedef typename tbb::flow::tuple_element<2, OutputTuple>::type T2;
typedef typename std::tuple_element<3, OutputTuple>::type T3; typedef typename tbb::flow::tuple_element<3, OutputTuple>::type T3;
typedef typename std::tuple_element<4, OutputTuple>::type T4; typedef typename tbb::flow::tuple_element<4, OutputTuple>::type T4;
typedef typename std::tuple_element<5, OutputTuple>::type T5; typedef typename tbb::flow::tuple_element<5, OutputTuple>::type T5;
public: public:
typedef typename wrap_tuple_elements<6, tag_matching_port, OutputTu ple>::type input_ports_type; typedef typename wrap_tuple_elements<6, tag_matching_port, OutputTu ple>::type input_ports_type;
typedef OutputTuple output_type; typedef OutputTuple output_type;
private: private:
typedef join_node_base<tag_matching, input_ports_type, output_type > base_type; typedef join_node_base<tag_matching, input_ports_type, output_type > base_type;
typedef typename internal::function_body<T0, tag_value> *f0_p; typedef typename internal::function_body<T0, tag_value> *f0_p;
typedef typename internal::function_body<T1, tag_value> *f1_p; typedef typename internal::function_body<T1, tag_value> *f1_p;
typedef typename internal::function_body<T2, tag_value> *f2_p; typedef typename internal::function_body<T2, tag_value> *f2_p;
typedef typename internal::function_body<T3, tag_value> *f3_p; typedef typename internal::function_body<T3, tag_value> *f3_p;
typedef typename internal::function_body<T4, tag_value> *f4_p; typedef typename internal::function_body<T4, tag_value> *f4_p;
typedef typename internal::function_body<T5, tag_value> *f5_p; typedef typename internal::function_body<T5, tag_value> *f5_p;
typedef typename std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p > f unc_initializer_type; typedef typename tbb::flow::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5 _p > func_initializer_type;
public: public:
template<typename B0, typename B1, typename B2, typename B3, typena me B4, typename B5> template<typename B0, typename B1, typename B2, typename B3, typena me B4, typename B5>
unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5) : base_type(g, unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5) : base_type(g,
func_initializer_type( func_initializer_type(
new internal::function_body_leaf<T0, tag_value, B0>(b0) , new internal::function_body_leaf<T0, tag_value, B0>(b0) ,
new internal::function_body_leaf<T1, tag_value, B1>(b1) , new internal::function_body_leaf<T1, tag_value, B1>(b1) ,
new internal::function_body_leaf<T2, tag_value, B2>(b2) , new internal::function_body_leaf<T2, tag_value, B2>(b2) ,
new internal::function_body_leaf<T3, tag_value, B3>(b3) , new internal::function_body_leaf<T3, tag_value, B3>(b3) ,
new internal::function_body_leaf<T4, tag_value, B4>(b4) , new internal::function_body_leaf<T4, tag_value, B4>(b4) ,
new internal::function_body_leaf<T5, tag_value, B5>(b5) new internal::function_body_leaf<T5, tag_value, B5>(b5)
) ) {} ) ) {}
unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {} unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {}
}; };
#endif #endif
#if __TBB_VARIADIC_MAX >= 7 #if __TBB_VARIADIC_MAX >= 7
template<typename OutputTuple> template<typename OutputTuple>
class unfolded_join_node<7,tag_matching_port,OutputTuple,tag_matching> : public class unfolded_join_node<7,tag_matching_port,OutputTuple,tag_matching> : public
join_base<7,tag_matching_port,OutputTuple,tag_matching>::type { join_base<7,tag_matching_port,OutputTuple,tag_matching>::type {
typedef typename std::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0;
typedef typename std::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1;
typedef typename std::tuple_element<2, OutputTuple>::type T2; typedef typename tbb::flow::tuple_element<2, OutputTuple>::type T2;
typedef typename std::tuple_element<3, OutputTuple>::type T3; typedef typename tbb::flow::tuple_element<3, OutputTuple>::type T3;
typedef typename std::tuple_element<4, OutputTuple>::type T4; typedef typename tbb::flow::tuple_element<4, OutputTuple>::type T4;
typedef typename std::tuple_element<5, OutputTuple>::type T5; typedef typename tbb::flow::tuple_element<5, OutputTuple>::type T5;
typedef typename std::tuple_element<6, OutputTuple>::type T6; typedef typename tbb::flow::tuple_element<6, OutputTuple>::type T6;
public: public:
typedef typename wrap_tuple_elements<7, tag_matching_port, OutputTu ple>::type input_ports_type; typedef typename wrap_tuple_elements<7, tag_matching_port, OutputTu ple>::type input_ports_type;
typedef OutputTuple output_type; typedef OutputTuple output_type;
private: private:
typedef join_node_base<tag_matching, input_ports_type, output_type > base_type; typedef join_node_base<tag_matching, input_ports_type, output_type > base_type;
typedef typename internal::function_body<T0, tag_value> *f0_p; typedef typename internal::function_body<T0, tag_value> *f0_p;
typedef typename internal::function_body<T1, tag_value> *f1_p; typedef typename internal::function_body<T1, tag_value> *f1_p;
typedef typename internal::function_body<T2, tag_value> *f2_p; typedef typename internal::function_body<T2, tag_value> *f2_p;
typedef typename internal::function_body<T3, tag_value> *f3_p; typedef typename internal::function_body<T3, tag_value> *f3_p;
typedef typename internal::function_body<T4, tag_value> *f4_p; typedef typename internal::function_body<T4, tag_value> *f4_p;
typedef typename internal::function_body<T5, tag_value> *f5_p; typedef typename internal::function_body<T5, tag_value> *f5_p;
typedef typename internal::function_body<T6, tag_value> *f6_p; typedef typename internal::function_body<T6, tag_value> *f6_p;
typedef typename std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6 _p > func_initializer_type; typedef typename tbb::flow::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5 _p, f6_p > func_initializer_type;
public: public:
template<typename B0, typename B1, typename B2, typename B3, typena me B4, typename B5, typename B6> template<typename B0, typename B1, typename B2, typename B3, typena me B4, typename B5, typename B6>
unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6) : base_type(g, unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6) : base_type(g,
func_initializer_type( func_initializer_type(
new internal::function_body_leaf<T0, tag_value, B0>(b0) , new internal::function_body_leaf<T0, tag_value, B0>(b0) ,
new internal::function_body_leaf<T1, tag_value, B1>(b1) , new internal::function_body_leaf<T1, tag_value, B1>(b1) ,
new internal::function_body_leaf<T2, tag_value, B2>(b2) , new internal::function_body_leaf<T2, tag_value, B2>(b2) ,
new internal::function_body_leaf<T3, tag_value, B3>(b3) , new internal::function_body_leaf<T3, tag_value, B3>(b3) ,
new internal::function_body_leaf<T4, tag_value, B4>(b4) , new internal::function_body_leaf<T4, tag_value, B4>(b4) ,
new internal::function_body_leaf<T5, tag_value, B5>(b5) , new internal::function_body_leaf<T5, tag_value, B5>(b5) ,
new internal::function_body_leaf<T6, tag_value, B6>(b6) new internal::function_body_leaf<T6, tag_value, B6>(b6)
) ) {} ) ) {}
unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {} unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {}
}; };
#endif #endif
#if __TBB_VARIADIC_MAX >= 8 #if __TBB_VARIADIC_MAX >= 8
template<typename OutputTuple> template<typename OutputTuple>
class unfolded_join_node<8,tag_matching_port,OutputTuple,tag_matching> : public class unfolded_join_node<8,tag_matching_port,OutputTuple,tag_matching> : public
join_base<8,tag_matching_port,OutputTuple,tag_matching>::type { join_base<8,tag_matching_port,OutputTuple,tag_matching>::type {
typedef typename std::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0;
typedef typename std::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1;
typedef typename std::tuple_element<2, OutputTuple>::type T2; typedef typename tbb::flow::tuple_element<2, OutputTuple>::type T2;
typedef typename std::tuple_element<3, OutputTuple>::type T3; typedef typename tbb::flow::tuple_element<3, OutputTuple>::type T3;
typedef typename std::tuple_element<4, OutputTuple>::type T4; typedef typename tbb::flow::tuple_element<4, OutputTuple>::type T4;
typedef typename std::tuple_element<5, OutputTuple>::type T5; typedef typename tbb::flow::tuple_element<5, OutputTuple>::type T5;
typedef typename std::tuple_element<6, OutputTuple>::type T6; typedef typename tbb::flow::tuple_element<6, OutputTuple>::type T6;
typedef typename std::tuple_element<7, OutputTuple>::type T7; typedef typename tbb::flow::tuple_element<7, OutputTuple>::type T7;
public: public:
typedef typename wrap_tuple_elements<8, tag_matching_port, OutputTu ple>::type input_ports_type; typedef typename wrap_tuple_elements<8, tag_matching_port, OutputTu ple>::type input_ports_type;
typedef OutputTuple output_type; typedef OutputTuple output_type;
private: private:
typedef join_node_base<tag_matching, input_ports_type, output_type > base_type; typedef join_node_base<tag_matching, input_ports_type, output_type > base_type;
typedef typename internal::function_body<T0, tag_value> *f0_p; typedef typename internal::function_body<T0, tag_value> *f0_p;
typedef typename internal::function_body<T1, tag_value> *f1_p; typedef typename internal::function_body<T1, tag_value> *f1_p;
typedef typename internal::function_body<T2, tag_value> *f2_p; typedef typename internal::function_body<T2, tag_value> *f2_p;
typedef typename internal::function_body<T3, tag_value> *f3_p; typedef typename internal::function_body<T3, tag_value> *f3_p;
typedef typename internal::function_body<T4, tag_value> *f4_p; typedef typename internal::function_body<T4, tag_value> *f4_p;
typedef typename internal::function_body<T5, tag_value> *f5_p; typedef typename internal::function_body<T5, tag_value> *f5_p;
typedef typename internal::function_body<T6, tag_value> *f6_p; typedef typename internal::function_body<T6, tag_value> *f6_p;
typedef typename internal::function_body<T7, tag_value> *f7_p; typedef typename internal::function_body<T7, tag_value> *f7_p;
typedef typename std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6 _p, f7_p > func_initializer_type; typedef typename tbb::flow::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5 _p, f6_p, f7_p > func_initializer_type;
public: public:
template<typename B0, typename B1, typename B2, typename B3, typena me B4, typename B5, typename B6, typename B7> template<typename B0, typename B1, typename B2, typename B3, typena me B4, typename B5, typename B6, typename B7>
unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6, B7 b7) : base_type(g, unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6, B7 b7) : base_type(g,
func_initializer_type( func_initializer_type(
new internal::function_body_leaf<T0, tag_value, B0>(b0) , new internal::function_body_leaf<T0, tag_value, B0>(b0) ,
new internal::function_body_leaf<T1, tag_value, B1>(b1) , new internal::function_body_leaf<T1, tag_value, B1>(b1) ,
new internal::function_body_leaf<T2, tag_value, B2>(b2) , new internal::function_body_leaf<T2, tag_value, B2>(b2) ,
new internal::function_body_leaf<T3, tag_value, B3>(b3) , new internal::function_body_leaf<T3, tag_value, B3>(b3) ,
new internal::function_body_leaf<T4, tag_value, B4>(b4) , new internal::function_body_leaf<T4, tag_value, B4>(b4) ,
new internal::function_body_leaf<T5, tag_value, B5>(b5) , new internal::function_body_leaf<T5, tag_value, B5>(b5) ,
skipping to change at line 1372 skipping to change at line 1426
new internal::function_body_leaf<T7, tag_value, B7>(b7) new internal::function_body_leaf<T7, tag_value, B7>(b7)
) ) {} ) ) {}
unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {} unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {}
}; };
#endif #endif
#if __TBB_VARIADIC_MAX >= 9 #if __TBB_VARIADIC_MAX >= 9
template<typename OutputTuple> template<typename OutputTuple>
class unfolded_join_node<9,tag_matching_port,OutputTuple,tag_matching> : public class unfolded_join_node<9,tag_matching_port,OutputTuple,tag_matching> : public
join_base<9,tag_matching_port,OutputTuple,tag_matching>::type { join_base<9,tag_matching_port,OutputTuple,tag_matching>::type {
typedef typename std::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0;
typedef typename std::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1;
typedef typename std::tuple_element<2, OutputTuple>::type T2; typedef typename tbb::flow::tuple_element<2, OutputTuple>::type T2;
typedef typename std::tuple_element<3, OutputTuple>::type T3; typedef typename tbb::flow::tuple_element<3, OutputTuple>::type T3;
typedef typename std::tuple_element<4, OutputTuple>::type T4; typedef typename tbb::flow::tuple_element<4, OutputTuple>::type T4;
typedef typename std::tuple_element<5, OutputTuple>::type T5; typedef typename tbb::flow::tuple_element<5, OutputTuple>::type T5;
typedef typename std::tuple_element<6, OutputTuple>::type T6; typedef typename tbb::flow::tuple_element<6, OutputTuple>::type T6;
typedef typename std::tuple_element<7, OutputTuple>::type T7; typedef typename tbb::flow::tuple_element<7, OutputTuple>::type T7;
typedef typename std::tuple_element<8, OutputTuple>::type T8; typedef typename tbb::flow::tuple_element<8, OutputTuple>::type T8;
public: public:
typedef typename wrap_tuple_elements<9, tag_matching_port, OutputTu ple>::type input_ports_type; typedef typename wrap_tuple_elements<9, tag_matching_port, OutputTu ple>::type input_ports_type;
typedef OutputTuple output_type; typedef OutputTuple output_type;
private: private:
typedef join_node_base<tag_matching, input_ports_type, output_type > base_type; typedef join_node_base<tag_matching, input_ports_type, output_type > base_type;
typedef typename internal::function_body<T0, tag_value> *f0_p; typedef typename internal::function_body<T0, tag_value> *f0_p;
typedef typename internal::function_body<T1, tag_value> *f1_p; typedef typename internal::function_body<T1, tag_value> *f1_p;
typedef typename internal::function_body<T2, tag_value> *f2_p; typedef typename internal::function_body<T2, tag_value> *f2_p;
typedef typename internal::function_body<T3, tag_value> *f3_p; typedef typename internal::function_body<T3, tag_value> *f3_p;
typedef typename internal::function_body<T4, tag_value> *f4_p; typedef typename internal::function_body<T4, tag_value> *f4_p;
typedef typename internal::function_body<T5, tag_value> *f5_p; typedef typename internal::function_body<T5, tag_value> *f5_p;
typedef typename internal::function_body<T6, tag_value> *f6_p; typedef typename internal::function_body<T6, tag_value> *f6_p;
typedef typename internal::function_body<T7, tag_value> *f7_p; typedef typename internal::function_body<T7, tag_value> *f7_p;
typedef typename internal::function_body<T8, tag_value> *f8_p; typedef typename internal::function_body<T8, tag_value> *f8_p;
typedef typename std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6 _p, f7_p, f8_p > func_initializer_type; typedef typename tbb::flow::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5 _p, f6_p, f7_p, f8_p > func_initializer_type;
public: public:
template<typename B0, typename B1, typename B2, typename B3, typena me B4, typename B5, typename B6, typename B7, typename B8> template<typename B0, typename B1, typename B2, typename B3, typena me B4, typename B5, typename B6, typename B7, typename B8>
unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6, B7 b7, B8 b8) : base_type(g, unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6, B7 b7, B8 b8) : base_type(g,
func_initializer_type( func_initializer_type(
new internal::function_body_leaf<T0, tag_value, B0>(b0) , new internal::function_body_leaf<T0, tag_value, B0>(b0) ,
new internal::function_body_leaf<T1, tag_value, B1>(b1) , new internal::function_body_leaf<T1, tag_value, B1>(b1) ,
new internal::function_body_leaf<T2, tag_value, B2>(b2) , new internal::function_body_leaf<T2, tag_value, B2>(b2) ,
new internal::function_body_leaf<T3, tag_value, B3>(b3) , new internal::function_body_leaf<T3, tag_value, B3>(b3) ,
new internal::function_body_leaf<T4, tag_value, B4>(b4) , new internal::function_body_leaf<T4, tag_value, B4>(b4) ,
new internal::function_body_leaf<T5, tag_value, B5>(b5) , new internal::function_body_leaf<T5, tag_value, B5>(b5) ,
skipping to change at line 1418 skipping to change at line 1472
new internal::function_body_leaf<T8, tag_value, B8>(b8) new internal::function_body_leaf<T8, tag_value, B8>(b8)
) ) {} ) ) {}
unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {} unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {}
}; };
#endif #endif
#if __TBB_VARIADIC_MAX >= 10 #if __TBB_VARIADIC_MAX >= 10
template<typename OutputTuple> template<typename OutputTuple>
class unfolded_join_node<10,tag_matching_port,OutputTuple,tag_matching> : public class unfolded_join_node<10,tag_matching_port,OutputTuple,tag_matching> : public
join_base<10,tag_matching_port,OutputTuple,tag_matching>::type { join_base<10,tag_matching_port,OutputTuple,tag_matching>::type {
typedef typename std::tuple_element<0, OutputTuple>::type T0; typedef typename tbb::flow::tuple_element<0, OutputTuple>::type T0;
typedef typename std::tuple_element<1, OutputTuple>::type T1; typedef typename tbb::flow::tuple_element<1, OutputTuple>::type T1;
typedef typename std::tuple_element<2, OutputTuple>::type T2; typedef typename tbb::flow::tuple_element<2, OutputTuple>::type T2;
typedef typename std::tuple_element<3, OutputTuple>::type T3; typedef typename tbb::flow::tuple_element<3, OutputTuple>::type T3;
typedef typename std::tuple_element<4, OutputTuple>::type T4; typedef typename tbb::flow::tuple_element<4, OutputTuple>::type T4;
typedef typename std::tuple_element<5, OutputTuple>::type T5; typedef typename tbb::flow::tuple_element<5, OutputTuple>::type T5;
typedef typename std::tuple_element<6, OutputTuple>::type T6; typedef typename tbb::flow::tuple_element<6, OutputTuple>::type T6;
typedef typename std::tuple_element<7, OutputTuple>::type T7; typedef typename tbb::flow::tuple_element<7, OutputTuple>::type T7;
typedef typename std::tuple_element<8, OutputTuple>::type T8; typedef typename tbb::flow::tuple_element<8, OutputTuple>::type T8;
typedef typename std::tuple_element<9, OutputTuple>::type T9; typedef typename tbb::flow::tuple_element<9, OutputTuple>::type T9;
public: public:
typedef typename wrap_tuple_elements<10, tag_matching_port, OutputT uple>::type input_ports_type; typedef typename wrap_tuple_elements<10, tag_matching_port, OutputT uple>::type input_ports_type;
typedef OutputTuple output_type; typedef OutputTuple output_type;
private: private:
typedef join_node_base<tag_matching, input_ports_type, output_type > base_type; typedef join_node_base<tag_matching, input_ports_type, output_type > base_type;
typedef typename internal::function_body<T0, tag_value> *f0_p; typedef typename internal::function_body<T0, tag_value> *f0_p;
typedef typename internal::function_body<T1, tag_value> *f1_p; typedef typename internal::function_body<T1, tag_value> *f1_p;
typedef typename internal::function_body<T2, tag_value> *f2_p; typedef typename internal::function_body<T2, tag_value> *f2_p;
typedef typename internal::function_body<T3, tag_value> *f3_p; typedef typename internal::function_body<T3, tag_value> *f3_p;
typedef typename internal::function_body<T4, tag_value> *f4_p; typedef typename internal::function_body<T4, tag_value> *f4_p;
typedef typename internal::function_body<T5, tag_value> *f5_p; typedef typename internal::function_body<T5, tag_value> *f5_p;
typedef typename internal::function_body<T6, tag_value> *f6_p; typedef typename internal::function_body<T6, tag_value> *f6_p;
typedef typename internal::function_body<T7, tag_value> *f7_p; typedef typename internal::function_body<T7, tag_value> *f7_p;
typedef typename internal::function_body<T8, tag_value> *f8_p; typedef typename internal::function_body<T8, tag_value> *f8_p;
typedef typename internal::function_body<T9, tag_value> *f9_p; typedef typename internal::function_body<T9, tag_value> *f9_p;
typedef typename std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6 _p, f7_p, f8_p, f9_p > func_initializer_type; typedef typename tbb::flow::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5 _p, f6_p, f7_p, f8_p, f9_p > func_initializer_type;
public: public:
template<typename B0, typename B1, typename B2, typename B3, typena me B4, typename B5, typename B6, typename B7, typename B8, typename B9> template<typename B0, typename B1, typename B2, typename B3, typena me B4, typename B5, typename B6, typename B7, typename B8, typename B9>
unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6, B7 b7, B8 b8, B9 b9) : base_type(g, unfolded_join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3, B4 b4, B5 b5, B6 b6, B7 b7, B8 b8, B9 b9) : base_type(g,
func_initializer_type( func_initializer_type(
new internal::function_body_leaf<T0, tag_value, B0>(b0) , new internal::function_body_leaf<T0, tag_value, B0>(b0) ,
new internal::function_body_leaf<T1, tag_value, B1>(b1) , new internal::function_body_leaf<T1, tag_value, B1>(b1) ,
new internal::function_body_leaf<T2, tag_value, B2>(b2) , new internal::function_body_leaf<T2, tag_value, B2>(b2) ,
new internal::function_body_leaf<T3, tag_value, B3>(b3) , new internal::function_body_leaf<T3, tag_value, B3>(b3) ,
new internal::function_body_leaf<T4, tag_value, B4>(b4) , new internal::function_body_leaf<T4, tag_value, B4>(b4) ,
new internal::function_body_leaf<T5, tag_value, B5>(b5) , new internal::function_body_leaf<T5, tag_value, B5>(b5) ,
skipping to change at line 1465 skipping to change at line 1519
new internal::function_body_leaf<T7, tag_value, B7>(b7) , new internal::function_body_leaf<T7, tag_value, B7>(b7) ,
new internal::function_body_leaf<T8, tag_value, B8>(b8) , new internal::function_body_leaf<T8, tag_value, B8>(b8) ,
new internal::function_body_leaf<T9, tag_value, B9>(b9) new internal::function_body_leaf<T9, tag_value, B9>(b9)
) ) {} ) ) {}
unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {} unfolded_join_node(const unfolded_join_node &other) : base_type(oth er) {}
}; };
#endif #endif
//! templated function to refer to input ports of the join node //! templated function to refer to input ports of the join node
template<size_t N, typename JNT> template<size_t N, typename JNT>
typename std::tuple_element<N, typename JNT::input_ports_type>::type &i typename tbb::flow::tuple_element<N, typename JNT::input_ports_type>::t
nput_port(JNT &jn) { ype &input_port(JNT &jn) {
return std::get<N>(jn.input_ports()); return tbb::flow::get<N>(jn.input_ports());
} }
} }
#endif // __TBB__flow_graph_join_impl_H #endif // __TBB__flow_graph_join_impl_H
 End of changes. 92 change blocks. 
199 lines changed or deleted 270 lines changed or added


 _flow_graph_node_impl.h   _flow_graph_node_impl.h 
skipping to change at line 64 skipping to change at line 64
} }
}; };
//! Input and scheduling for a function node that takes a type Input as input //! Input and scheduling for a function node that takes a type Input as input
// The only up-ref is apply_body_impl, which should implement the func tion // The only up-ref is apply_body_impl, which should implement the func tion
// call and any handling of the result. // call and any handling of the result.
template< typename Input, typename A, typename ImplType > template< typename Input, typename A, typename ImplType >
class function_input_base : public receiver<Input>, tbb::internal::no_a ssign { class function_input_base : public receiver<Input>, tbb::internal::no_a ssign {
typedef sender<Input> predecessor_type; typedef sender<Input> predecessor_type;
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
enum op_type {reg_pred, rem_pred, app_body, tryput, try_fwd}; enum op_type {reg_pred, rem_pred, app_body, try_fwd, tryput_bypass, app_body_bypass };
typedef function_input_base<Input, A, ImplType> my_class; typedef function_input_base<Input, A, ImplType> my_class;
public: public:
//! The input type of this receiver //! The input type of this receiver
typedef Input input_type; typedef Input input_type;
//! Constructor for function_input_base //! Constructor for function_input_base
function_input_base( graph &g, size_t max_concurrency, function_inp ut_queue<input_type,A> *q = NULL ) function_input_base( graph &g, size_t max_concurrency, function_inp ut_queue<input_type,A> *q = NULL )
: my_root_task(g.root_task()), my_max_concurrency(max_concurren cy), my_concurrency(0), : my_root_task(g.root_task()), my_max_concurrency(max_concurren cy), my_concurrency(0),
skipping to change at line 95 skipping to change at line 95
{ {
my_predecessors.set_owner(this); my_predecessors.set_owner(this);
my_aggregator.initialize_handler(my_handler(this)); my_aggregator.initialize_handler(my_handler(this));
} }
//! Destructor //! Destructor
virtual ~function_input_base() { virtual ~function_input_base() {
if ( my_queue ) delete my_queue; if ( my_queue ) delete my_queue;
} }
//! Put to the node //! Put to the node, returning a task if available
virtual bool try_put( const input_type &t ) { virtual task * try_put_task( const input_type &t ) {
if ( my_max_concurrency == 0 ) { if ( my_max_concurrency == 0 ) {
spawn_body_task( t ); return create_body_task( t );
return true;
} else { } else {
my_operation op_data(t, tryput); my_operation op_data(t, tryput_bypass);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.status == SUCCEEDED; if(op_data.status == SUCCEEDED ) {
return op_data.bypass_t;
}
return NULL;
} }
} }
//! Adds src to the list of cached predecessors. //! Adds src to the list of cached predecessors.
/* override */ bool register_predecessor( predecessor_type &src ) { /* override */ bool register_predecessor( predecessor_type &src ) {
my_operation op_data(reg_pred); my_operation op_data(reg_pred);
op_data.r = &src; op_data.r = &src;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return true; return true;
} }
skipping to change at line 145 skipping to change at line 147
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() { /*override*/void reset_receiver() {
my_predecessors.reset(); my_predecessors.reset();
} }
private: private:
friend class apply_body_task< my_class, input_type >; friend class apply_body_task_bypass< my_class, input_type >;
friend class forward_task< my_class >; friend class forward_task_bypass< 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;
predecessor_type *r; predecessor_type *r;
}; };
tbb::task *bypass_t;
my_operation(const input_type& e, op_type t) : my_operation(const input_type& e, op_type t) :
type(char(t)), elem(const_cast<input_type*>(&e)) {} type(char(t)), elem(const_cast<input_type*>(&e)) {}
my_operation(op_type t) : type(char(t)), r(NULL) {} my_operation(op_type t) : type(char(t)), r(NULL) {}
}; };
bool forwarder_busy; bool forwarder_busy;
typedef internal::aggregating_functor<my_class, my_operation> my_ha ndler; typedef internal::aggregating_functor<my_class, my_operation> my_ha ndler;
friend class internal::aggregating_functor<my_class, my_operation>; friend class internal::aggregating_functor<my_class, my_operation>;
aggregator< my_handler, my_operation > my_aggregator; aggregator< my_handler, my_operation > my_aggregator;
skipping to change at line 200 skipping to change at line 203
if ( my_queue ) if ( my_queue )
item_was_retrieved = my_queue->pop(i); item_was_retrieved = my_queue->pop(i);
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 app_body_bypass: {
task * new_task = NULL;
__TBB_ASSERT(my_max_concurrency != 0, NULL);
--my_concurrency;
if (my_concurrency<my_max_concurrency) {
input_type i;
bool item_was_retrieved = false;
if ( my_queue )
item_was_retrieved = my_queue->pop(i);
else
item_was_retrieved = my_predecessors.get_it
em(i);
if (item_was_retrieved) {
++my_concurrency;
new_task = create_body_task(i);
}
}
tmp->bypass_t = new_task;
__TBB_store_with_release(tmp->status, SUCCEEDED);
}
break;
case tryput_bypass: internal_try_put_task(tmp); break;
case try_fwd: internal_forward(tmp); break; case try_fwd: internal_forward(tmp); break;
} }
} }
} }
//! Put to the node //! Put to the node, but return the task instead of enqueueing it
void internal_try_put(my_operation *op) { void internal_try_put_task(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)); task * new_task = create_body_task(*(op->elem));
op->bypass_t = new_task;
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} else if ( my_queue && my_queue->push(*(op->elem)) ) { } else if ( my_queue && my_queue->push(*(op->elem)) ) {
op->bypass_t = SUCCESSFULLY_ENQUEUED;
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} else { } else {
op->bypass_t = NULL;
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
} }
} }
//! Tries to spawn bodies if available and if concurrency allows //! Tries to spawn bodies if available and if concurrency allows
void internal_forward(my_operation *op) { void internal_forward(my_operation *op) {
op->bypass_t = NULL;
if (my_concurrency<my_max_concurrency || !my_max_concurrency) { if (my_concurrency<my_max_concurrency || !my_max_concurrency) {
input_type i; input_type i;
bool item_was_retrieved = false; bool item_was_retrieved = false;
if ( my_queue ) if ( my_queue )
item_was_retrieved = my_queue->pop(i); item_was_retrieved = my_queue->pop(i);
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;
op->bypass_t = create_body_task(i);
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
spawn_body_task(i);
return; return;
} }
} }
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
forwarder_busy = false; forwarder_busy = false;
} }
//! Applies the body to the provided input //! Applies the body to the provided input
// then decides if more work is available
void apply_body( input_type &i ) { void apply_body( input_type &i ) {
static_cast<ImplType *>(this)->apply_body_impl(i); task *new_task = apply_body_bypass(i);
if(!new_task) return;
if(new_task == SUCCESSFULLY_ENQUEUED) return;
task::enqueue(*new_task);
return;
}
//! Applies the body to the provided input
// then decides if more work is available
// we should still be able to use app_body, because the task retur
ned should be the successor node
// and not us, so we are reducing my_concurrency. (might be a pro
blem if we are our own successor?)
task * apply_body_bypass( input_type &i ) {
task * new_task = static_cast<ImplType *>(this)->apply_body_imp
l_bypass(i);
if ( my_max_concurrency != 0 ) { if ( my_max_concurrency != 0 ) {
my_operation op_data(app_body); my_operation op_data(app_body_bypass); // tries to pop an item or get_item, enqueues another apply_body
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
tbb::task *ttask = op_data.bypass_t;
new_task = combine_tasks(new_task, ttask);
} }
return new_task;
} }
//! allocates a task to call apply_body( input )
inline task * create_body_task( const input_type &input ) {
return new(task::allocate_additional_child_of(*my_root_task))
apply_body_task_bypass < my_class, input_type >(*this, input
);
}
//! Spawns a task that calls apply_body( input ) //! Spawns a task that calls apply_body( input )
inline void spawn_body_task( const input_type &input ) { inline void spawn_body_task( const input_type &input ) {
task::enqueue(*new(task::allocate_additional_child_of(*my_root_t ask)) apply_body_task< my_class, input_type >(*this, input)); task::enqueue(*create_body_task(input));
} }
//! This is executed by an enqueued task, the "forwarder" //! This is executed by an enqueued task, the "forwarder"
void forward() { task *forward_task() {
my_operation op_data(try_fwd); my_operation op_data(try_fwd);
task *rval = NULL;
do { do {
op_data.status = WAIT; op_data.status = WAIT;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
if(op_data.status == SUCCEEDED) {
tbb::task *ttask = op_data.bypass_t;
rval = combine_tasks(rval, ttask);
}
} while (op_data.status == SUCCEEDED); } while (op_data.status == SUCCEEDED);
return rval;
}
inline task *create_forward_task() {
task *rval = new(task::allocate_additional_child_of(*my_root_tas
k)) forward_task_bypass< my_class >(*this);
return rval;
} }
//! Spawns a task that calls forward() //! Spawns a task that calls forward()
inline void spawn_forward_task() { inline void spawn_forward_task() {
task::enqueue(*new(task::allocate_additional_child_of(*my_root_t ask)) forward_task< my_class >(*this)); task::enqueue(*create_forward_task());
} }
}; // function_input_base }; // function_input_base
//! Implements methods for a function node that takes a type Input as i nput and sends //! Implements methods for a function node that takes a type Input as i nput and sends
// a type Output to its successors. // a type Output to its successors.
template< typename Input, typename Output, typename A> template< typename Input, typename Output, typename A>
class function_input : public function_input_base<Input, A, function_in put<Input,Output,A> > { class function_input : public function_input_base<Input, A, function_in put<Input,Output,A> > {
public: public:
typedef Input input_type; typedef Input input_type;
typedef Output output_type; typedef Output output_type;
skipping to change at line 303 skipping to change at line 363
~function_input() { ~function_input() {
delete my_body; delete my_body;
} }
template< typename Body > template< typename Body >
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) { task * apply_body_impl_bypass( const input_type &i) {
successors().try_put( (*my_body)(i) ); task * new_task = successors().try_put_task( (*my_body)(i) );
return new_task;
} }
protected: protected:
void reset_function_input() { void reset_function_input() {
base_type::reset_function_input_base(); 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;
skipping to change at line 356 skipping to change at line 417
~multifunction_input() { ~multifunction_input() {
delete my_body; delete my_body;
} }
template< typename Body > template< typename Body >
Body copy_function_object() { Body copy_function_object() {
internal::multifunction_body<input_type, output_ports_type> &bo dy_ref = *this->my_body; internal::multifunction_body<input_type, output_ports_type> &bo dy_ref = *this->my_body;
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) { // for multifunction nodes we do not have a single successor as suc
h. So we just tell
// the task we were successful.
task * apply_body_impl_bypass( const input_type &i) {
(*my_body)(i, my_output_ports); (*my_body)(i, my_output_ports);
task * new_task = SUCCESSFULLY_ENQUEUED;
return new_task;
} }
output_ports_type &output_ports(){ return my_output_ports; } output_ports_type &output_ports(){ return my_output_ports; }
protected: protected:
void reset() { void reset() {
base_type::reset_function_input_base(); 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 & typename tbb::flow::tuple_element<N, typename MOP::output_ports_type>::
output_port(MOP &op) { type &output_port(MOP &op) {
return std::get<N>(op.output_ports()); return tbb::flow::get<N>(op.output_ports());
} }
// helper structs for split_node // helper structs for split_node
template<int N> template<int N>
struct emit_element { struct emit_element {
template<typename T, typename P> template<typename T, typename P>
static void emit_this(const T &t, P &p) { static void emit_this(const T &t, P &p) {
(void)std::get<N-1>(p).try_put(std::get<N-1>(t)); (void)tbb::flow::get<N-1>(p).try_put(tbb::flow::get<N-1>(t));
emit_element<N-1>::emit_this(t,p); emit_element<N-1>::emit_this(t,p);
} }
}; };
template<> template<>
struct emit_element<1> { struct emit_element<1> {
template<typename T, typename P> template<typename T, typename P>
static void emit_this(const T &t, P &p) { static void emit_this(const T &t, P &p) {
(void)std::get<0>(p).try_put(std::get<0>(t)); (void)tbb::flow::get<0>(p).try_put(tbb::flow::get<0>(t));
} }
}; };
//! Implements methods for an executable node that takes continue_msg a s input //! Implements methods for an executable node that takes continue_msg a s input
template< typename Output > template< typename Output >
class continue_input : public continue_receiver { class continue_input : public continue_receiver {
public: public:
//! The input type of this receiver //! The input type of this receiver
typedef continue_msg input_type; typedef continue_msg input_type;
skipping to change at line 434 skipping to change at line 499
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();
} }
protected: protected:
task *my_root_task; task *my_root_task;
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;
friend class apply_body_task< continue_input< Output >, continue_ms g >; friend class apply_body_task_bypass< continue_input< Output >, cont inue_msg >;
//! Applies the body to the provided input //! Applies the body to the provided input
/* override */ void apply_body( input_type ) { /* override */ task *apply_body_bypass( input_type ) {
successors().try_put( (*my_body)( continue_msg() ) ); return successors().try_put_task( (*my_body)( continue_msg() )
);
} }
//! Spawns a task that applies the body //! Spawns a task that applies the body
/* override */ void execute( ) { /* override */ task *execute( ) {
task::enqueue( * new ( task::allocate_additional_child_of( *my_ task *res = new ( task::allocate_additional_child_of( *my_root_
root_task ) ) task ) )
apply_body_task< continue_input< Output >, continue_msg >( * apply_body_task_bypass< continue_input< Output >, continue_
this, continue_msg() ) ); msg >( *this, continue_msg() );
return res;
} }
}; };
//! Implements methods for both executable and function nodes that puts Output to its successors //! Implements methods for both executable and function nodes that puts Output to its successors
template< typename Output > template< typename Output >
class function_output : public sender<Output> { class function_output : public sender<Output> {
public: public:
typedef Output output_type; typedef Output output_type;
skipping to change at line 480 skipping to change at line 546
return true; return true;
} }
// for multifunction_node. The function_body that implements // for multifunction_node. The function_body that implements
// the node will have an input and an output tuple of ports. To pu t // the node will have an input and an output tuple of ports. To pu t
// an item to a successor, the body should // an item to a successor, the body should
// //
// get<I>(output_ports).try_put(output_value); // get<I>(output_ports).try_put(output_value);
// //
// return value will be bool returned from successors.try_put. // return value will be bool returned from successors.try_put.
bool try_put(const output_type &i) { return my_successors.try_put(i ); } task *try_put_task(const output_type &i) { return my_successors.try _put_task(i); }
protected: protected:
broadcast_cache<output_type> my_successors; broadcast_cache<output_type> my_successors;
broadcast_cache<output_type > &successors() { return my_successors; } broadcast_cache<output_type > &successors() { return my_successors; }
}; };
template< typename Output >
class multifunction_output : public function_output<Output> {
public:
typedef Output output_type;
typedef function_output<output_type> base_type;
using base_type::my_successors;
multifunction_output() : base_type() {my_successors.set_owner(this)
;}
multifunction_output( const multifunction_output &/*other*/) : base
_type() { my_successors.set_owner(this); }
bool try_put(const output_type &i) {
task *res = my_successors.try_put_task(i);
if(!res) return false;
if(res != SUCCESSFULLY_ENQUEUED) task::enqueue(*res);
return true;
}
};
} // internal } // internal
#endif // __TBB__flow_graph_node_impl_H #endif // __TBB__flow_graph_node_impl_H
 End of changes. 38 change blocks. 
36 lines changed or deleted 130 lines changed or added


 _flow_graph_or_impl.h   _flow_graph_or_impl.h 
skipping to change at line 41 skipping to change at line 41
#ifndef __TBB_flow_graph_H #ifndef __TBB_flow_graph_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#if TBB_PREVIEW_GRAPH_NODES #if TBB_PREVIEW_GRAPH_NODES
#include "tbb/internal/_flow_graph_types_impl.h" #include "tbb/internal/_flow_graph_types_impl.h"
namespace internal { namespace internal {
// Output of the or_node is a struct containing a std::tuple, and will be of // Output of the or_node is a struct containing a tbb::flow::tuple, and will be of
// the form // the form
// //
// struct { // struct {
// size_t indx; // size_t indx;
// tuple_types result; // tuple_types result;
// }; // };
// //
// where the value of indx will indicate which result was put to the // where the value of indx will indicate which result was put to the
// successor. So if oval is the output to the successor, indx == 0 // successor. So if oval is the output to the successor, indx == 0
// means std::get<0>(oval.result) is the output, and so on. // means tbb::flow::get<0>(oval.result) is the output, and so on.
// //
// tuple_types is the tuple that specified the possible outputs (and // tuple_types is the tuple that specified the possible outputs (and
// the corresponding inputs to the or_node.) // the corresponding inputs to the or_node.)
// //
// the types of each element are represented by tuple_types, a typedef // the types of each element are represented by tuple_types, a typedef
// in the or_node. So the 2nd type in the union that is the // in the or_node. So the 2nd type in the union that is the
// output type for an or_node OrType is // output type for an or_node OrType is
// //
// std::tuple_element<1,OrType::tuple_types>::type // tbb::flow::tuple_element<1,OrType::tuple_types>::type
// the struct has an OutputTuple default constructed, with element inde x assigned // the struct has an OutputTuple default constructed, with element inde x assigned
// the actual output value. // the actual output value.
template<typename OutputTuple> template<typename OutputTuple>
struct or_output_type { struct or_output_type {
typedef OutputTuple tuple_types; typedef OutputTuple tuple_types;
typedef struct { typedef struct {
size_t indx; size_t indx;
OutputTuple result; OutputTuple result;
} type; } type;
}; };
template<typename TupleTypes,int N> template<typename TupleTypes,int N>
struct or_item_helper { struct or_item_helper {
template<typename OutputType> template<typename OutputType>
static inline void create_output_value(OutputType &o, void *v) { static inline void create_output_value(OutputType &o, void *v) {
o.indx = N; o.indx = N;
std::get<N>(o.result) = *(reinterpret_cast<typename std::tuple_ element<N, TupleTypes>::type *>(v)); tbb::flow::get<N>(o.result) = *(reinterpret_cast<typename tbb:: flow::tuple_element<N, TupleTypes>::type *>(v));
} }
}; };
template<typename TupleTypes,int N> template<typename TupleTypes,int N>
struct or_helper { struct or_helper {
template<typename OutputType> template<typename OutputType>
static inline void create_output(OutputType &o, size_t i, void* v) { static inline void create_output(OutputType &o, size_t i, void* v) {
if(i == N-1) { if(i == N-1) {
or_item_helper<TupleTypes,N-1>::create_output_value(o,v); or_item_helper<TupleTypes,N-1>::create_output_value(o,v);
} }
else else
or_helper<TupleTypes,N-1>::create_output(o,i,v); or_helper<TupleTypes,N-1>::create_output(o,i,v);
} }
template<typename PortTuple, typename PutBase> template<typename PortTuple, typename PutBase>
static inline void set_or_node_pointer(PortTuple &my_input, PutBase *p) { static inline void set_or_node_pointer(PortTuple &my_input, PutBase *p) {
std::get<N-1>(my_input).set_up(p, N-1); tbb::flow::get<N-1>(my_input).set_up(p, N-1);
or_helper<TupleTypes,N-1>::set_or_node_pointer(my_input, p); or_helper<TupleTypes,N-1>::set_or_node_pointer(my_input, p);
} }
}; };
template<typename TupleTypes> template<typename TupleTypes>
struct or_helper<TupleTypes,1> { struct or_helper<TupleTypes,1> {
template<typename OutputType> template<typename OutputType>
static inline void create_output(OutputType &o, size_t i, void* v) { static inline void create_output(OutputType &o, size_t i, void* v) {
if(i == 0) { if(i == 0) {
or_item_helper<TupleTypes,0>::create_output_value(o,v); or_item_helper<TupleTypes,0>::create_output_value(o,v);
} }
} }
template<typename PortTuple, typename PutBase> template<typename PortTuple, typename PutBase>
static inline void set_or_node_pointer(PortTuple &my_input, PutBase *p) { static inline void set_or_node_pointer(PortTuple &my_input, PutBase *p) {
std::get<0>(my_input).set_up(p, 0); tbb::flow::get<0>(my_input).set_up(p, 0);
} }
}; };
struct put_base { struct put_base {
virtual bool try_put_with_index(size_t index, void *v) = 0; // virtual bool try_put_with_index(size_t index, void *v) = 0;
virtual task * try_put_task_with_index(size_t index, void *v) = 0;
virtual ~put_base() { } virtual ~put_base() { }
}; };
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) {
return my_or_node->try_put_with_index(my_index, reinterpret_cas
t<void *>(const_cast<T*>(&v)));
}
protected: protected:
template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_c
ache;
template<typename X, typename Y> friend class internal::round_robin
_cache;
task *try_put_task(const T &v) {
return my_or_node->try_put_task_with_index(my_index, reinterpre
t_cast<void *>(const_cast<T*>(&v)));
}
/*override*/void reset_receiver() {} /*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 = tbb::flow::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( ) {
or_helper<StructTypes,N>::set_or_node_pointer(my_inputs, this); or_helper<StructTypes,N>::set_or_node_pointer(my_inputs, this);
} }
input_type &input_ports() { return my_inputs; } input_type &input_ports() { return my_inputs; }
protected: protected:
input_type my_inputs; input_type my_inputs;
}; };
//! or_node_base //! or_node_base
template<typename InputTuple, typename OutputType, typename StructTypes > template<typename InputTuple, typename OutputType, typename StructTypes >
class or_node_base : public graph_node, public or_node_FE<InputTuple, O utputType,StructTypes>, class or_node_base : public graph_node, public or_node_FE<InputTuple, O utputType,StructTypes>,
public sender<OutputType> { public sender<OutputType> {
protected:
using graph_node::my_graph; using graph_node::my_graph;
public: public:
static const size_t N = std::tuple_size<InputTuple>::value; static const size_t N = tbb::flow::tuple_size<InputTuple>::value;
typedef OutputType output_type; typedef OutputType output_type;
typedef StructTypes tuple_types; typedef StructTypes tuple_types;
typedef receiver<output_type> successor_type; typedef receiver<output_type> successor_type;
typedef or_node_FE<InputTuple, output_type,StructTypes> input_ports _type; typedef or_node_FE<InputTuple, output_type,StructTypes> input_ports _type;
private: private:
// ----------- Aggregator ------------ // ----------- Aggregator ------------
enum op_type { reg_succ, rem_succ, try__put }; enum op_type { reg_succ, rem_succ, try__put_task };
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
typedef or_node_base<InputTuple,output_type,StructTypes> my_class; typedef or_node_base<InputTuple,output_type,StructTypes> my_class;
class or_node_base_operation : public aggregated_operation<or_node_ base_operation> { class or_node_base_operation : public aggregated_operation<or_node_ base_operation> {
public: public:
char type; char type;
size_t indx; size_t indx;
union { union {
void *my_arg; void *my_arg;
successor_type *my_succ; successor_type *my_succ;
task *bypass_t;
}; };
or_node_base_operation(size_t i, const void* e, op_type t) : or_node_base_operation(size_t i, const void* e, op_type t) :
type(char(t)), indx(i), my_arg(const_cast<void *>(e)) {} type(char(t)), indx(i), my_arg(const_cast<void *>(e)) {}
or_node_base_operation(const successor_type &s, op_type t) : ty pe(char(t)), or_node_base_operation(const successor_type &s, op_type t) : ty pe(char(t)),
my_succ(const_cast<successor_type *>(&s)) {} my_succ(const_cast<successor_type *>(&s)) {}
or_node_base_operation(op_type t) : type(char(t)) {} or_node_base_operation(op_type t) : type(char(t)) {}
}; };
typedef internal::aggregating_functor<my_class, or_node_base_operat ion> my_handler; typedef internal::aggregating_functor<my_class, or_node_base_operat ion> my_handler;
friend class internal::aggregating_functor<my_class, or_node_base_o peration>; friend class internal::aggregating_functor<my_class, or_node_base_o peration>;
skipping to change at line 201 skipping to change at line 207
case reg_succ: case reg_succ:
my_successors.register_successor(*(current->my_succ)); my_successors.register_successor(*(current->my_succ));
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case rem_succ: case rem_succ:
my_successors.remove_successor(*(current->my_succ)); my_successors.remove_successor(*(current->my_succ));
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case try__put_task: {
case try__put: output_type oo;
output_type oval; or_helper<tuple_types,N>::create_output(oo, current
or_helper<tuple_types,N>::create_output(oval,current->i ->indx, current->my_arg);
ndx,current->my_arg); current->bypass_t = my_successors.try_put_task(oo);
bool res = my_successors.try_put(oval); __TBB_store_with_release(current->status, SUCCEEDED
__TBB_store_with_release(current->status, res ? SUCCEED ); // return of try_put_task actual return value
ED : FAILED); }
break; break;
} }
} }
} }
// ---------- end aggregator ----------- // ---------- end aggregator -----------
public: public:
or_node_base(graph& g) : graph_node(g), input_ports_type() { or_node_base(graph& g) : graph_node(g), input_ports_type() {
my_successors.set_owner(this); my_successors.set_owner(this);
my_aggregator.initialize_handler(my_handler(this)); my_aggregator.initialize_handler(my_handler(this));
} }
skipping to change at line 235 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 remove_successor( successor_type &r) { bool remove_successor( successor_type &r) {
or_node_base_operation op_data(r, rem_succ); or_node_base_operation op_data(r, rem_succ);
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) { task * try_put_task_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_task);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.status == SUCCEEDED; return op_data.bypass_t;
} }
protected: protected:
/*override*/void reset() {} /*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 = tbb::flow::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;
typedef internal::or_node_FE<input_ports_type,output_type,OutputTup le> or_FE_type; typedef internal::or_node_FE<input_ports_type,output_type,OutputTup le> or_FE_type;
typedef internal::or_node_base<input_ports_type, output_type, Outpu tTuple> or_base_type; typedef internal::or_node_base<input_ports_type, output_type, Outpu tTuple> or_base_type;
}; };
template<class OutputTuple> template<class OutputTuple>
class unfolded_or_node : public or_types<OutputTuple>::or_base_type { class unfolded_or_node : public or_types<OutputTuple>::or_base_type {
public: public:
typedef typename or_types<OutputTuple>::input_ports_type input_port s_type; typedef typename or_types<OutputTuple>::input_ports_type input_port s_type;
 End of changes. 18 change blocks. 
26 lines changed or deleted 34 lines changed or added


 _flow_graph_types_impl.h   _flow_graph_types_impl.h 
skipping to change at line 44 skipping to change at line 44
#endif #endif
namespace internal { namespace internal {
// wrap each element of a tuple in a template, and make a tuple of the resu lt. // wrap each element of a tuple in a template, and make a tuple of the resu lt.
template<int N, template<class> class PT, typename TypeTuple> template<int N, template<class> class PT, typename TypeTuple>
struct wrap_tuple_elements; struct wrap_tuple_elements;
template<template<class> class PT, typename TypeTuple> template<template<class> class PT, typename TypeTuple>
struct wrap_tuple_elements<1, PT, TypeTuple> { struct wrap_tuple_elements<1, PT, TypeTuple> {
typedef typename std::tuple< typedef typename tbb::flow::tuple<
PT<typename std::tuple_element<0,TypeTuple>::type> > PT<typename tbb::flow::tuple_element<0,TypeTuple>::type> >
type; type;
}; };
template<template<class> class PT, typename TypeTuple> template<template<class> class PT, typename TypeTuple>
struct wrap_tuple_elements<2, PT, TypeTuple> { struct wrap_tuple_elements<2, PT, TypeTuple> {
typedef typename std::tuple< typedef typename tbb::flow::tuple<
PT<typename std::tuple_element<0,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<0,TypeTuple>::type>,
PT<typename std::tuple_element<1,TypeTuple>::type> > PT<typename tbb::flow::tuple_element<1,TypeTuple>::type> >
type; type;
}; };
template<template<class> class PT, typename TypeTuple> template<template<class> class PT, typename TypeTuple>
struct wrap_tuple_elements<3, PT, TypeTuple> { struct wrap_tuple_elements<3, PT, TypeTuple> {
typedef typename std::tuple< typedef typename tbb::flow::tuple<
PT<typename std::tuple_element<0,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<0,TypeTuple>::type>,
PT<typename std::tuple_element<1,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<1,TypeTuple>::type>,
PT<typename std::tuple_element<2,TypeTuple>::type> > PT<typename tbb::flow::tuple_element<2,TypeTuple>::type> >
type; type;
}; };
template<template<class> class PT, typename TypeTuple> template<template<class> class PT, typename TypeTuple>
struct wrap_tuple_elements<4, PT, TypeTuple> { struct wrap_tuple_elements<4, PT, TypeTuple> {
typedef typename std::tuple< typedef typename tbb::flow::tuple<
PT<typename std::tuple_element<0,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<0,TypeTuple>::type>,
PT<typename std::tuple_element<1,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<1,TypeTuple>::type>,
PT<typename std::tuple_element<2,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<2,TypeTuple>::type>,
PT<typename std::tuple_element<3,TypeTuple>::type> > PT<typename tbb::flow::tuple_element<3,TypeTuple>::type> >
type; type;
}; };
template<template<class> class PT, typename TypeTuple> template<template<class> class PT, typename TypeTuple>
struct wrap_tuple_elements<5, PT, TypeTuple> { struct wrap_tuple_elements<5, PT, TypeTuple> {
typedef typename std::tuple< typedef typename tbb::flow::tuple<
PT<typename std::tuple_element<0,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<0,TypeTuple>::type>,
PT<typename std::tuple_element<1,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<1,TypeTuple>::type>,
PT<typename std::tuple_element<2,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<2,TypeTuple>::type>,
PT<typename std::tuple_element<3,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<3,TypeTuple>::type>,
PT<typename std::tuple_element<4,TypeTuple>::type> > PT<typename tbb::flow::tuple_element<4,TypeTuple>::type> >
type; type;
}; };
#if __TBB_VARIADIC_MAX >= 6 #if __TBB_VARIADIC_MAX >= 6
template<template<class> class PT, typename TypeTuple> template<template<class> class PT, typename TypeTuple>
struct wrap_tuple_elements<6, PT, TypeTuple> { struct wrap_tuple_elements<6, PT, TypeTuple> {
typedef typename std::tuple< typedef typename tbb::flow::tuple<
PT<typename std::tuple_element<0,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<0,TypeTuple>::type>,
PT<typename std::tuple_element<1,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<1,TypeTuple>::type>,
PT<typename std::tuple_element<2,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<2,TypeTuple>::type>,
PT<typename std::tuple_element<3,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<3,TypeTuple>::type>,
PT<typename std::tuple_element<4,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<4,TypeTuple>::type>,
PT<typename std::tuple_element<5,TypeTuple>::type> > PT<typename tbb::flow::tuple_element<5,TypeTuple>::type> >
type; type;
}; };
#endif #endif
#if __TBB_VARIADIC_MAX >= 7 #if __TBB_VARIADIC_MAX >= 7
template<template<class> class PT, typename TypeTuple> template<template<class> class PT, typename TypeTuple>
struct wrap_tuple_elements<7, PT, TypeTuple> { struct wrap_tuple_elements<7, PT, TypeTuple> {
typedef typename std::tuple< typedef typename tbb::flow::tuple<
PT<typename std::tuple_element<0,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<0,TypeTuple>::type>,
PT<typename std::tuple_element<1,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<1,TypeTuple>::type>,
PT<typename std::tuple_element<2,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<2,TypeTuple>::type>,
PT<typename std::tuple_element<3,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<3,TypeTuple>::type>,
PT<typename std::tuple_element<4,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<4,TypeTuple>::type>,
PT<typename std::tuple_element<5,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<5,TypeTuple>::type>,
PT<typename std::tuple_element<6,TypeTuple>::type> > PT<typename tbb::flow::tuple_element<6,TypeTuple>::type> >
type; type;
}; };
#endif #endif
#if __TBB_VARIADIC_MAX >= 8 #if __TBB_VARIADIC_MAX >= 8
template<template<class> class PT, typename TypeTuple> template<template<class> class PT, typename TypeTuple>
struct wrap_tuple_elements<8, PT, TypeTuple> { struct wrap_tuple_elements<8, PT, TypeTuple> {
typedef typename std::tuple< typedef typename tbb::flow::tuple<
PT<typename std::tuple_element<0,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<0,TypeTuple>::type>,
PT<typename std::tuple_element<1,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<1,TypeTuple>::type>,
PT<typename std::tuple_element<2,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<2,TypeTuple>::type>,
PT<typename std::tuple_element<3,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<3,TypeTuple>::type>,
PT<typename std::tuple_element<4,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<4,TypeTuple>::type>,
PT<typename std::tuple_element<5,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<5,TypeTuple>::type>,
PT<typename std::tuple_element<6,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<6,TypeTuple>::type>,
PT<typename std::tuple_element<7,TypeTuple>::type> > PT<typename tbb::flow::tuple_element<7,TypeTuple>::type> >
type; type;
}; };
#endif #endif
#if __TBB_VARIADIC_MAX >= 9 #if __TBB_VARIADIC_MAX >= 9
template<template<class> class PT, typename TypeTuple> template<template<class> class PT, typename TypeTuple>
struct wrap_tuple_elements<9, PT, TypeTuple> { struct wrap_tuple_elements<9, PT, TypeTuple> {
typedef typename std::tuple< typedef typename tbb::flow::tuple<
PT<typename std::tuple_element<0,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<0,TypeTuple>::type>,
PT<typename std::tuple_element<1,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<1,TypeTuple>::type>,
PT<typename std::tuple_element<2,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<2,TypeTuple>::type>,
PT<typename std::tuple_element<3,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<3,TypeTuple>::type>,
PT<typename std::tuple_element<4,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<4,TypeTuple>::type>,
PT<typename std::tuple_element<5,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<5,TypeTuple>::type>,
PT<typename std::tuple_element<6,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<6,TypeTuple>::type>,
PT<typename std::tuple_element<7,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<7,TypeTuple>::type>,
PT<typename std::tuple_element<8,TypeTuple>::type> > PT<typename tbb::flow::tuple_element<8,TypeTuple>::type> >
type; type;
}; };
#endif #endif
#if __TBB_VARIADIC_MAX >= 10 #if __TBB_VARIADIC_MAX >= 10
template<template<class> class PT, typename TypeTuple> template<template<class> class PT, typename TypeTuple>
struct wrap_tuple_elements<10, PT, TypeTuple> { struct wrap_tuple_elements<10, PT, TypeTuple> {
typedef typename std::tuple< typedef typename tbb::flow::tuple<
PT<typename std::tuple_element<0,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<0,TypeTuple>::type>,
PT<typename std::tuple_element<1,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<1,TypeTuple>::type>,
PT<typename std::tuple_element<2,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<2,TypeTuple>::type>,
PT<typename std::tuple_element<3,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<3,TypeTuple>::type>,
PT<typename std::tuple_element<4,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<4,TypeTuple>::type>,
PT<typename std::tuple_element<5,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<5,TypeTuple>::type>,
PT<typename std::tuple_element<6,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<6,TypeTuple>::type>,
PT<typename std::tuple_element<7,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<7,TypeTuple>::type>,
PT<typename std::tuple_element<8,TypeTuple>::type>, PT<typename tbb::flow::tuple_element<8,TypeTuple>::type>,
PT<typename std::tuple_element<9,TypeTuple>::type> > PT<typename tbb::flow::tuple_element<9,TypeTuple>::type> >
type; type;
}; };
#endif #endif
} // namespace internal } // namespace internal
#endif /* __TBB__flow_graph_types_impl_H */ #endif /* __TBB__flow_graph_types_impl_H */
 End of changes. 10 change blocks. 
65 lines changed or deleted 65 lines changed or added


 _tbb_windef.h   _tbb_windef.h 
skipping to change at line 35 skipping to change at line 35
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_windef_H #ifndef __TBB_tbb_windef_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif /* __TBB_tbb_windef_H */ #endif /* __TBB_tbb_windef_H */
// Check that the target Windows version has all API calls requried for TBB . // Check that the target Windows version has all API calls requried for TBB .
// Do not increase the version in condition beyond 0x0500 without prior dis cussion! // Do not increase the version in condition beyond 0x0500 without prior dis cussion!
#if defined(_WIN32_WINNT) && _WIN32_WINNT<0x0400 #if defined(_WIN32_WINNT) && _WIN32_WINNT<0x0501
#error TBB is unable to run on old Windows versions; _WIN32_WINNT must be 0 #error TBB is unable to run on old Windows versions; _WIN32_WINNT must be 0
x0400 or greater. x0501 or greater.
#endif #endif
#if !defined(_MT) #if !defined(_MT)
#error TBB requires linkage with multithreaded C/C++ runtime library. \ #error TBB requires linkage with multithreaded C/C++ runtime library. \
Choose multithreaded DLL runtime in project settings, or use /MD[d] compiler switch. Choose multithreaded DLL runtime in project settings, or use /MD[d] compiler switch.
#endif #endif
// Workaround for the problem with MVSC headers failing to define namespace std // Workaround for the problem with MVSC headers failing to define namespace std
namespace std { namespace std {
using ::size_t; using ::ptrdiff_t; using ::size_t; using ::ptrdiff_t;
 End of changes. 1 change blocks. 
3 lines changed or deleted 3 lines changed or added


 concurrent_vector.h   concurrent_vector.h 
skipping to change at line 65 skipping to change at line 65
#if _MSC_VER==1500 && !__INTEL_COMPILER #if _MSC_VER==1500 && !__INTEL_COMPILER
// VS2008/VC9 seems to have an issue; limits pull in math.h // VS2008/VC9 seems to have an issue; limits pull in math.h
#pragma warning( push ) #pragma warning( push )
#pragma warning( disable: 4985 ) #pragma warning( disable: 4985 )
#endif #endif
#include <limits> /* std::numeric_limits */ #include <limits> /* std::numeric_limits */
#if _MSC_VER==1500 && !__INTEL_COMPILER #if _MSC_VER==1500 && !__INTEL_COMPILER
#pragma warning( pop ) #pragma warning( pop )
#endif #endif
#if __TBB_INITIALIZER_LISTS_PRESENT
#include <initializer_list>
#endif
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_Wp64) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_Wp64)
// Workaround for overzealous compiler warnings in /Wp64 mode // Workaround for overzealous compiler warnings in /Wp64 mode
#pragma warning (push) #pragma warning (push)
#pragma warning (disable: 4267) #pragma warning (disable: 4267)
#endif #endif
namespace tbb { namespace tbb {
template<typename T, class A = cache_aligned_allocator<T> > template<typename T, class A = cache_aligned_allocator<T> >
class concurrent_vector; class concurrent_vector;
skipping to change at line 512 skipping to change at line 516
// STL compatible constructors & destructors // STL compatible constructors & destructors
//--------------------------------------------------------------------- --- //--------------------------------------------------------------------- ---
//! Construct empty vector. //! Construct empty vector.
explicit concurrent_vector(const allocator_type &a = allocator_type()) explicit concurrent_vector(const allocator_type &a = allocator_type())
: internal::allocator_base<T, A>(a), internal::concurrent_vector_ba se() : internal::allocator_base<T, A>(a), internal::concurrent_vector_ba se()
{ {
vector_allocator_ptr = &internal_allocator; vector_allocator_ptr = &internal_allocator;
} }
#if __TBB_INITIALIZER_LISTS_PRESENT
//! Constructor from initializer_list
concurrent_vector(std::initializer_list<T> init_list, const allocator_t
ype &a = allocator_type())
: internal::allocator_base<T, A>(a), internal::concurrent_vector_ba
se()
{
vector_allocator_ptr = &internal_allocator;
__TBB_TRY {
internal_assign_iterators(init_list.begin(), init_list.end());
} __TBB_CATCH(...) {
segment_t *table = my_segment;
internal_free_segments( reinterpret_cast<void**>(table), intern
al_clear(&destroy_array), my_first_block );
__TBB_RETHROW();
}
}
#endif //# __TBB_INITIALIZER_LISTS_PRESENT
//! Copying constructor //! Copying constructor
concurrent_vector( const concurrent_vector& vector, const allocator_typ e& a = allocator_type() ) concurrent_vector( const concurrent_vector& vector, const allocator_typ e& a = allocator_type() )
: internal::allocator_base<T, A>(a), internal::concurrent_vector_ba se() : internal::allocator_base<T, A>(a), internal::concurrent_vector_ba se()
{ {
vector_allocator_ptr = &internal_allocator; vector_allocator_ptr = &internal_allocator;
__TBB_TRY { __TBB_TRY {
internal_copy(vector, sizeof(T), &copy_array); internal_copy(vector, sizeof(T), &copy_array);
} __TBB_CATCH(...) { } __TBB_CATCH(...) {
segment_t *table = my_segment; segment_t *table = my_segment;
internal_free_segments( reinterpret_cast<void**>(table), intern al_clear(&destroy_array), my_first_block ); internal_free_segments( reinterpret_cast<void**>(table), intern al_clear(&destroy_array), my_first_block );
skipping to change at line 590 skipping to change at line 611
} }
} }
//! Assignment //! Assignment
concurrent_vector& operator=( const concurrent_vector& vector ) { concurrent_vector& operator=( const concurrent_vector& vector ) {
if( this != &vector ) if( this != &vector )
internal_assign(vector, sizeof(T), &destroy_array, &assign_arra y, &copy_array); internal_assign(vector, sizeof(T), &destroy_array, &assign_arra y, &copy_array);
return *this; return *this;
} }
//TODO: add an template assignment operator? (i.e. with different eleme
nt type)
//! Assignment for vector with different allocator type //! Assignment for vector with different allocator type
template<class M> template<class M>
concurrent_vector& operator=( const concurrent_vector<T, M>& vector ) { concurrent_vector& operator=( const concurrent_vector<T, M>& vector ) {
if( static_cast<void*>( this ) != static_cast<const void*>( &vector ) ) if( static_cast<void*>( this ) != static_cast<const void*>( &vector ) )
internal_assign(vector.internal_vector_base(), internal_assign(vector.internal_vector_base(),
sizeof(T), &destroy_array, &assign_array, &copy_array); sizeof(T), &destroy_array, &assign_array, &copy_array);
return *this; return *this;
} }
#if __TBB_INITIALIZER_LISTS_PRESENT
//! Assignment for initializer_list
concurrent_vector& operator=( const std::initializer_list<T> & init_lis
t) {
internal_clear(&destroy_array);
internal_assign_iterators(init_list.begin(), init_list.end());
return *this;
}
#endif //#if __TBB_INITIALIZER_LISTS_PRESENT
//--------------------------------------------------------------------- --- //--------------------------------------------------------------------- ---
// Concurrent operations // Concurrent operations
//--------------------------------------------------------------------- --- //--------------------------------------------------------------------- ---
//TODO: consider adding overload of grow_by accepting range of iterator
s: grow_by(iterator,iterator)
//TODO: consider adding overload of grow_by accepting initializer_list:
grow_by(std::initializer_list<T>), as a analogy to std::vector::insert(in
itializer_list)
//! Grow by "delta" elements. //! Grow by "delta" elements.
#if TBB_DEPRECATED #if TBB_DEPRECATED
/** Returns old size. */ /** Returns old size. */
size_type grow_by( size_type delta ) { size_type grow_by( size_type delta ) {
return delta ? internal_grow_by( delta, sizeof(T), &initialize_arra y, NULL ) : my_early_size; return delta ? internal_grow_by( delta, sizeof(T), &initialize_arra y, NULL ) : my_early_size;
} }
#else #else
/** Returns iterator pointing to the first new element. */ /** Returns iterator pointing to the first new element. */
iterator grow_by( size_type delta ) { iterator grow_by( size_type delta ) {
return iterator(*this, delta ? internal_grow_by( delta, sizeof(T), &initialize_array, NULL ) : my_early_size); return iterator(*this, delta ? internal_grow_by( delta, sizeof(T), &initialize_array, NULL ) : my_early_size);
skipping to change at line 808 skipping to change at line 842
clear(); clear();
internal_resize( n, sizeof(T), max_size(), static_cast<const void*> (&t), &destroy_array, &initialize_array_by ); internal_resize( n, sizeof(T), max_size(), static_cast<const void*> (&t), &destroy_array, &initialize_array_by );
} }
//! assign range [first, last) //! assign range [first, last)
template<class I> template<class I>
void assign(I first, I last) { void assign(I first, I last) {
clear(); internal_assign_range( first, last, static_cast<is_integer _tag<std::numeric_limits<I>::is_integer> *>(0) ); clear(); internal_assign_range( first, last, static_cast<is_integer _tag<std::numeric_limits<I>::is_integer> *>(0) );
} }
#if __TBB_INITIALIZER_LISTS_PRESENT
//! assigns an initializer list
void assign(std::initializer_list<T> init_list) {
clear(); internal_assign_iterators( init_list.begin(), init_list.en
d());
}
#endif //# __TBB_INITIALIZER_LISTS_PRESENT
//! swap two instances //! swap two instances
void swap(concurrent_vector &vector) { void swap(concurrent_vector &vector) {
if( this != &vector ) { if( this != &vector ) {
concurrent_vector_base_v3::internal_swap(static_cast<concurrent _vector_base_v3&>(vector)); concurrent_vector_base_v3::internal_swap(static_cast<concurrent _vector_base_v3&>(vector));
std::swap(this->my_allocator, vector.my_allocator); std::swap(this->my_allocator, vector.my_allocator);
} }
} }
//! Clear container while keeping memory allocated. //! Clear container while keeping memory allocated.
/** To free up the memory, use in conjunction with method compact(). No t thread safe **/ /** To free up the memory, use in conjunction with method compact(). No t thread safe **/
skipping to change at line 893 skipping to change at line 934
public: public:
const pointer array; const pointer array;
const size_type n; const size_type n;
size_type i; size_type i;
internal_loop_guide(size_type ntrials, void *ptr) internal_loop_guide(size_type ntrials, void *ptr)
: array(static_cast<pointer>(ptr)), n(ntrials), i(0) {} : array(static_cast<pointer>(ptr)), n(ntrials), i(0) {}
void init() { for(; i < n; ++i) new( &array[i] ) T(); } void init() { for(; i < n; ++i) new( &array[i] ) T(); }
void init(const void *src) { for(; i < n; ++i) new( &array[i] ) T(* static_cast<const T*>(src)); } void init(const void *src) { for(; i < n; ++i) new( &array[i] ) T(* static_cast<const T*>(src)); }
void copy(const void *src) { for(; i < n; ++i) new( &array[i] ) T(s tatic_cast<const T*>(src)[i]); } void copy(const void *src) { for(; i < n; ++i) new( &array[i] ) T(s tatic_cast<const T*>(src)[i]); }
void assign(const void *src) { for(; i < n; ++i) array[i] = static_ cast<const T*>(src)[i]; } void assign(const void *src) { for(; i < n; ++i) array[i] = static_ cast<const T*>(src)[i]; }
//TODO: rename to construct_range
template<class I> void iterate(I &src) { for(; i < n; ++i, ++src) n ew( &array[i] ) T( *src ); } template<class I> void iterate(I &src) { for(; i < n; ++i, ++src) n ew( &array[i] ) T( *src ); }
~internal_loop_guide() { ~internal_loop_guide() {
if(i < n) // if exception raised, do zeroing on the rest of ite ms if(i < n) // if exception raised, do zeroing on the rest of ite ms
std::memset(array+i, 0, (n-i)*sizeof(value_type)); std::memset(array+i, 0, (n-i)*sizeof(value_type));
} }
}; };
}; };
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#pragma warning (push) #pragma warning (push)
 End of changes. 7 change blocks. 
0 lines changed or deleted 51 lines changed or added


 critical_section.h   critical_section.h 
skipping to change at line 61 skipping to change at line 61
#else #else
pthread_mutex_t my_impl; pthread_mutex_t my_impl;
#endif #endif
tbb_thread::id my_tid; tbb_thread::id my_tid;
public: public:
void __TBB_EXPORTED_METHOD internal_construct(); void __TBB_EXPORTED_METHOD internal_construct();
critical_section_v4() { critical_section_v4() {
#if _WIN32||_WIN64 #if _WIN32||_WIN64
InitializeCriticalSection(&my_impl); InitializeCriticalSectionEx( &my_impl, 4000, 0 );
#else #else
pthread_mutex_init(&my_impl, NULL); pthread_mutex_init(&my_impl, NULL);
#endif #endif
internal_construct(); internal_construct();
} }
~critical_section_v4() { ~critical_section_v4() {
__TBB_ASSERT(my_tid == tbb_thread::id(), "Destroying a still-held c ritical section"); __TBB_ASSERT(my_tid == tbb_thread::id(), "Destroying a still-held c ritical section");
#if _WIN32||_WIN64 #if _WIN32||_WIN64
DeleteCriticalSection(&my_impl); DeleteCriticalSection(&my_impl);
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 enumerable_thread_specific.h   enumerable_thread_specific.h 
skipping to change at line 235 skipping to change at line 235
} }
} }
} }
} }
//! Specialization that exploits native TLS //! Specialization that exploits native TLS
template <> template <>
class ets_base<ets_key_per_instance>: protected ets_base<ets_no_key > { class ets_base<ets_key_per_instance>: protected ets_base<ets_no_key > {
typedef ets_base<ets_no_key> super; typedef ets_base<ets_no_key> super;
#if _WIN32||_WIN64 #if _WIN32||_WIN64
#if __TBB_WIN8UI_SUPPORT
typedef DWORD tls_key_t;
void create_key() { my_key = FlsAlloc(NULL); }
void destroy_key() { FlsFree(my_key); }
void set_tls(void * value) { FlsSetValue(my_key, (LPVOID)value)
; }
void* get_tls() { return (void *)FlsGetValue(my_key); }
#else
typedef DWORD tls_key_t; typedef DWORD tls_key_t;
void create_key() { my_key = TlsAlloc(); } void create_key() { my_key = TlsAlloc(); }
void destroy_key() { TlsFree(my_key); } void destroy_key() { TlsFree(my_key); }
void set_tls(void * value) { TlsSetValue(my_key, (LPVOID)value) ; } void set_tls(void * value) { TlsSetValue(my_key, (LPVOID)value) ; }
void* get_tls() { return (void *)TlsGetValue(my_key); } void* get_tls() { return (void *)TlsGetValue(my_key); }
#endif
#else #else
typedef pthread_key_t tls_key_t; typedef pthread_key_t tls_key_t;
void create_key() { pthread_key_create(&my_key, NULL); } void create_key() { pthread_key_create(&my_key, NULL); }
void destroy_key() { pthread_key_delete(my_key); } void destroy_key() { pthread_key_delete(my_key); }
void set_tls( void * value ) const { pthread_setspecific(my_key , value); } void set_tls( void * value ) const { pthread_setspecific(my_key , value); }
void* get_tls() const { return pthread_getspecific(my_key); } void* get_tls() const { return pthread_getspecific(my_key); }
#endif #endif
tls_key_t my_key; tls_key_t my_key;
virtual void* create_local() = 0; virtual void* create_local() = 0;
virtual void* create_array(size_t _size) = 0; // _size in byte s virtual void* create_array(size_t _size) = 0; // _size in byte s
 End of changes. 2 change blocks. 
0 lines changed or deleted 9 lines changed or added


 flow_graph.h   flow_graph.h 
skipping to change at line 45 skipping to change at line 45
#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_CPP11_TUPLE_PRESENT #if __TBB_CPP11_TUPLE_PRESENT
#include <tuple> #include <tuple>
namespace tbb {
namespace flow {
using std::tuple;
using std::tuple_size;
using std::tuple_element;
using std::get;
}
}
#else #else
#include "compat/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
skipping to change at line 71 skipping to change at line 79
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 { namespace internal {
template<typename T, typename M> template<typename T, typename M> class successor_cache;
class successor_cache; template<typename T, typename M> class broadcast_cache;
template<typename T, typename M> class round_robin_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
skipping to change at line 114 skipping to change at line 123
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 template< typename T > class limiter_node; // needed for resetting decreme nter
template< typename R, typename B > class run_and_put_task;
static tbb::task * const SUCCESSFULLY_ENQUEUED = (task *)-1;
// enqueue left task if necessary. Returns the non-enqueued task if there
is one.
static inline tbb::task *combine_tasks( tbb::task * left, tbb::task * right
) {
// if no RHS task, don't change left.
if(right == NULL) return left;
// right != NULL
if(left == NULL) return right;
if(left == SUCCESSFULLY_ENQUEUED) return right;
// left contains a task
if(right != SUCCESSFULLY_ENQUEUED) {
// both are valid tasks
tbb::task::enqueue(*left);
return right;
}
return left;
}
//! 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;
//! Destructor //! Destructor
virtual ~receiver() {} virtual ~receiver() {}
//! Put an item to the receiver //! Put an item to the receiver
virtual bool try_put( const T& t ) = 0; bool try_put( const T& t ) {
task *res = try_put_task(t);
if(!res) return false;
if (res != SUCCESSFULLY_ENQUEUED) task::enqueue(*res);
return true;
}
//! put item to successor; return task to run the successor if possible
.
protected:
template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache
;
template<typename X, typename Y> friend class internal::round_robin_cac
he;
virtual task *try_put_task(const T& t) = 0;
public:
//! 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: protected:
//! put receiver back in initial state //! put receiver back in initial state
template<typename U> friend class limiter_node; template<typename U> friend class limiter_node;
virtual void reset_receiver() = 0; virtual void reset_receiver() = 0;
template<typename TT, typename M> template<typename TT, typename M>
friend class internal::successor_cache; friend class internal::successor_cache;
virtual bool is_continue_receiver() { return false; } 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 189 skipping to change at line 231
//! Decrements the trigger threshold //! Decrements the trigger threshold
/** Does not check to see if the removal of the predecessor now makes t he current count /** Does not check to see if the removal of the predecessor now makes t he current count
exceed the new threshold. So removing a predecessor while the grap h is active can cause exceed the new threshold. So removing a predecessor while the grap h is active can cause
unexpected results. */ unexpected results. */
/* override */ bool remove_predecessor( predecessor_type & ) { /* override */ bool remove_predecessor( predecessor_type & ) {
spin_mutex::scoped_lock l(my_mutex); spin_mutex::scoped_lock l(my_mutex);
--my_predecessor_count; --my_predecessor_count;
return true; return true;
} }
//! Puts a continue_msg to the receiver protected:
/** If the message causes the message count to reach the predecessor co template< typename R, typename B > friend class run_and_put_task;
unt, execute() is called and template<typename X, typename Y> friend class internal::broadcast_cache
the message count is reset to 0. Otherwise the message count is in ;
cremented. */ template<typename X, typename Y> friend class internal::round_robin_cac
/* override */ bool try_put( const input_type & ) { he;
// execute body is supposed to be too small to create a task for.
/* override */ task *try_put_task( const input_type & ) {
{ {
spin_mutex::scoped_lock l(my_mutex); spin_mutex::scoped_lock l(my_mutex);
if ( ++my_current_count < my_predecessor_count ) if ( ++my_current_count < my_predecessor_count )
return true; return SUCCESSFULLY_ENQUEUED;
else else
my_current_count = 0; my_current_count = 0;
} }
execute(); task * res = execute();
return true; return res;
} }
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" // the friend declaration in the base class did not eliminate the "prot ected class"
// error in gcc 4.1.2 // error in gcc 4.1.2
template<typename U> friend class limiter_node; template<typename U> friend class limiter_node;
/*override*/void reset_receiver() { /*override*/void reset_receiver() {
my_current_count = 0; 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 task * execute() = 0;
template<typename TT, typename M> template<typename TT, typename M>
friend class internal::successor_cache; friend class internal::successor_cache;
/*override*/ bool is_continue_receiver() { return true; } /*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>
skipping to change at line 320 skipping to change at line 363
} }
private: private:
Body my_body; Body my_body;
}; };
template< typename Receiver, typename Body > template< typename Receiver, typename Body >
class run_and_put_task : public task { class run_and_put_task : public task {
public: public:
run_and_put_task( Receiver &r, Body& body ) : my_receiver(r), my_bo dy(body) {} run_and_put_task( Receiver &r, Body& body ) : my_receiver(r), my_bo dy(body) {}
task *execute() { task *execute() {
my_receiver.try_put( my_body() ); task *res = my_receiver.try_put_task( my_body() );
return NULL; if(res == SUCCESSFULLY_ENQUEUED) res = NULL;
return res;
} }
private: private:
Receiver &my_receiver; Receiver &my_receiver;
Body my_body; Body my_body;
}; };
public: public:
//! Constructs a graph with isolated task_group_context //! Constructs a graph with isolated task_group_context
explicit graph() : my_nodes(NULL), my_nodes_last(NULL) explicit graph() : my_nodes(NULL), my_nodes_last(NULL)
{ {
skipping to change at line 550 skipping to change at line 594
graph_node *my_p = &(*ii); graph_node *my_p = &(*ii);
my_p->reset(); 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 > {
protected:
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;
//! The type of successors of this node //! The type of successors of this node
typedef receiver< Output > successor_type; typedef receiver< Output > successor_type;
//! Constructor for a node with a successor //! Constructor for a node with a successor
template< typename Body > template< typename Body >
skipping to change at line 658 skipping to change at line 703
} }
//! 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> template<typename Body>
Body copy_function_object() { Body copy_function_object() {
internal::source_body<output_type> &body_ref = *this->my_body; internal::source_body<output_type> &body_ref = *this->my_body;
return dynamic_cast< internal::source_body_leaf<output_type, Body> & >(body_ref).get_body(); return dynamic_cast< internal::source_body_leaf<output_type, Body> & >(body_ref).get_body();
} }
protected: protected:
//! resets the node to its initial state //! resets the node to its initial state
void reset() { void reset() {
my_active = init_my_active; my_active = init_my_active;
skipping to change at line 686 skipping to change at line 731
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 > >;
// used by apply_body, can invoke body of node. // used by apply_body, can invoke body of node.
bool try_reserve_apply_body(output_type &v) { bool try_reserve_apply_body(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) ) if ( !my_has_cached_item && (*my_body)(my_cached_item) )
my_has_cached_item = true; 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;
} }
} }
//! Applies the body //! Spawns a task that applies the body
/* override */ void apply_body( ) { /* override */ void spawn_put( ) {
task::enqueue( * new ( task::allocate_additional_child_of( *my_root
_task ) )
internal:: source_task_bypass < source_node< output_type > >( *t
his ) );
}
friend class internal::source_task_bypass< source_node< output_type > >
;
//! Applies the body. Returning SUCCESSFULLY_ENQUEUED okay; forward_ta
sk_bypass will handle it.
/* override */ task * apply_body_bypass( ) {
output_type v; output_type v;
if ( !try_reserve_apply_body(v) ) if ( !try_reserve_apply_body(v) )
return; return NULL;
if ( my_successors.try_put( v ) ) task *last_task = my_successors.try_put_task(v);
if ( last_task )
try_consume(); try_consume();
else else
try_release(); try_release();
} return last_task;
//! Spawns a task that applies the body
/* override */ void spawn_put( ) {
task::enqueue( * new ( task::allocate_additional_child_of( *my_root
_task ) )
internal::source_task< source_node< output_type > >( *this ) );
} }
}; // source_node }; // 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> {
protected:
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;
typedef internal::function_input<input_type,output_type,Allocator> fInp ut_type; typedef internal::function_input<input_type,output_type,Allocator> fInp ut_type;
typedef internal::function_output<output_type> fOutput_type; typedef internal::function_output<output_type> fOutput_type;
//! Constructor //! Constructor
skipping to change at line 751 skipping to change at line 795
function_node( graph &g, size_t concurrency, Body body ) : function_node( graph &g, size_t concurrency, Body body ) :
graph_node(g), internal::function_input<input_type,output_type,Allo cator>(g, concurrency, body) graph_node(g), internal::function_input<input_type,output_type,Allo cator>(g, concurrency, body)
{} {}
//! 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); }
protected: protected:
template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache
;
template<typename X, typename Y> friend class internal::round_robin_cac
he;
using fInput_type::try_put_task;
// override of graph_node's reset. // override of graph_node's reset.
/*override*/void reset() {fInput_type::reset_function_input(); } /*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> {
protected:
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;
typedef internal::function_input<input_type,output_type,Allocator> fInp ut_type; typedef internal::function_input<input_type,output_type,Allocator> fInp ut_type;
typedef internal::function_input_queue<input_type, Allocator> queue_typ e; typedef internal::function_input_queue<input_type, Allocator> queue_typ e;
typedef internal::function_output<output_type> fOutput_type; typedef internal::function_output<output_type> fOutput_type;
skipping to change at line 785 skipping to change at line 832
template< typename Body > template< typename Body >
function_node( graph &g, size_t concurrency, Body body ) : function_node( graph &g, size_t concurrency, Body body ) :
graph_node(g), fInput_type( g, concurrency, body, new queue_type() ) graph_node(g), fInput_type( g, concurrency, body, new queue_type() )
{} {}
//! 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); }
protected: protected:
template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache
;
template<typename X, typename Y> friend class internal::round_robin_cac
he;
using fInput_type::try_put_task;
/*override*/void reset() { fInput_type::reset_function_input(); } /*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,
public internal::multifunction_input public internal::multifunction_input
< <
Input, Input,
typename internal::wrap_tuple_elements< typename internal::wrap_tuple_elements<
std::tuple_size<Output>::value, // #elements in tuple tbb::flow::tuple_size<Output>::value, // #elements in tuple
internal::function_output, // wrap this around each element internal::multifunction_output, // wrap this around each eleme
nt
Output // the tuple providing the types Output // the tuple providing the types
>::type, >::type,
Allocator Allocator
> { > {
protected:
using graph_node::my_graph; using graph_node::my_graph;
private: private:
static const int N = std::tuple_size<Output>::value; static const int N = tbb::flow::tuple_size<Output>::value;
public: public:
typedef Input input_type; typedef Input input_type;
typedef typename internal::wrap_tuple_elements<N,internal::function_out put, Output>::type output_ports_type; typedef typename internal::wrap_tuple_elements<N,internal::multifunctio n_output, Output>::type output_ports_type;
private: private:
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) 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: protected:
/*override*/void reset() { base_type::reset(); } /*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, typename internal::wrap_tuple_elements<tbb::flow::tuple_size<Output>::v
internal::function_output, Output>::type, Allocator> { alue, internal::multifunction_output, Output>::type, Allocator> {
protected:
using graph_node::my_graph; using graph_node::my_graph;
static const int N = std::tuple_size<Output>::value; static const int N = tbb::flow::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::multifuncti on_output, Output>::type output_ports_type;
private: private:
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())
skipping to change at line 862 skipping to change at line 913
// all the guts are in multifunction_input... // all the guts are in multifunction_input...
protected: protected:
/*override*/void reset() { base_type::reset(); } /*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 = tbb::flow::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:
typedef typename base_type::output_ports_type output_ports_type; typedef typename base_type::output_ports_type output_ports_type;
private: private:
struct splitting_body { struct splitting_body {
void operator()(const TupleType& t, output_ports_type &p) { void operator()(const TupleType& t, output_ports_type &p) {
internal::emit_element<N>::emit_this(t, p); internal::emit_element<N>::emit_this(t, p);
} }
}; };
public: public:
typedef TupleType input_type; typedef TupleType input_type;
typedef Allocator allocator_type; typedef Allocator allocator_type;
split_node(graph &g) : base_type(g, unlimited, splitting_body()) {} split_node(graph &g) : base_type(g, unlimited, splitting_body()) {}
split_node( const split_node & other) : base_type(other) {} split_node( const split_node & other) : base_type(other) {}
}; };
//! Implements an executable node that supports continue_msg -> Output //! Implements an executable node that supports continue_msg -> Output
template <typename Output> template <typename Output>
class continue_node : public graph_node, public internal::continue_input<Ou tput>, public internal::function_output<Output> { class continue_node : public graph_node, public internal::continue_input<Ou tput>, public internal::function_output<Output> {
protected:
using graph_node::my_graph; using graph_node::my_graph;
public: public:
typedef continue_msg input_type; typedef continue_msg 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;
typedef internal::continue_input<Output> fInput_type;
typedef internal::function_output<output_type> fOutput_type; typedef internal::function_output<output_type> fOutput_type;
//! Constructor for executable node with continue_msg -> Output //! Constructor for executable node with continue_msg -> Output
template <typename Body > template <typename Body >
continue_node( graph &g, Body body ) : continue_node( graph &g, Body body ) :
graph_node(g), internal::continue_input<output_type>( g, body ) graph_node(g), internal::continue_input<output_type>( g, body )
{} {}
//! Constructor for executable node with continue_msg -> Output //! Constructor for executable node with continue_msg -> Output
template <typename Body > template <typename Body >
continue_node( graph &g, int number_of_predecessors, Body body ) : continue_node( graph &g, int number_of_predecessors, Body body ) :
graph_node(g), internal::continue_input<output_type>( g, number_of_ predecessors, body ) graph_node(g), internal::continue_input<output_type>( g, number_of_ predecessors, body )
{} {}
//! 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); }
protected: protected:
template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache
;
template<typename X, typename Y> friend class internal::round_robin_cac
he;
using fInput_type::try_put_task;
/*override*/void reset() { internal::continue_input<Output>::reset_rece iver(); } /*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> {
protected:
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;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
overwrite_node(graph &g) : graph_node(g), my_buffer_is_valid(false) { overwrite_node(graph &g) : graph_node(g), my_buffer_is_valid(false) {
my_successors.set_owner( this ); my_successors.set_owner( this );
} }
skipping to change at line 943 skipping to change at line 1000
my_successors.set_owner( this ); my_successors.set_owner( this );
} }
~overwrite_node() {} ~overwrite_node() {}
/* override */ bool register_successor( successor_type &s ) { /* override */ bool register_successor( successor_type &s ) {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
if ( my_buffer_is_valid ) { if ( my_buffer_is_valid ) {
// We have a valid value that must be forwarded immediately. // We have a valid value that must be forwarded immediately.
if ( s.try_put( my_buffer ) || !s.register_predecessor( *this ) ) { if ( s.try_put( my_buffer ) || !s.register_predecessor( *this ) ) {
// We add the successor: it accepted our put or it rejected it but won't let use become a predecessor // We add the successor: it accepted our put or it rejected it but won't let us become a predecessor
my_successors.register_successor( s ); my_successors.register_successor( s );
return true; return true;
} else { } else {
// We don't add the successor: it rejected our put and we b ecame its predecessor instead // We don't add the successor: it rejected our put and we b ecame its predecessor instead
return false; return false;
} }
} else { } else {
// No valid value yet, just add as successor // No valid value yet, just add as successor
my_successors.register_successor( s ); my_successors.register_successor( s );
return true; return true;
} }
} }
/* override */ bool remove_successor( successor_type &s ) { /* override */ bool remove_successor( successor_type &s ) {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
my_successors.remove_successor(s); my_successors.remove_successor(s);
return true; return true;
} }
/* override */ bool try_put( const T &v ) {
spin_mutex::scoped_lock l( my_mutex );
my_buffer = v;
my_buffer_is_valid = true;
my_successors.try_put(v);
return true;
}
/* override */ bool try_get( T &v ) { /* override */ bool try_get( T &v ) {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
if ( my_buffer_is_valid ) { if ( my_buffer_is_valid ) {
v = my_buffer; v = my_buffer;
return true; return true;
} else { } else {
return false; return false;
} }
} }
skipping to change at line 992 skipping to change at line 1041
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:
template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache
;
template<typename X, typename Y> friend class internal::round_robin_cac
he;
/* override */ task * try_put_task( const T &v ) {
spin_mutex::scoped_lock l( my_mutex );
my_buffer = v;
my_buffer_is_valid = true;
task * rtask = my_successors.try_put_task(v);
if(!rtask) rtask = SUCCESSFULLY_ENQUEUED;
return rtask;
}
/*override*/void reset() { my_buffer_is_valid = false; } /*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() {} /*override*/void reset_receiver() {}
}; };
skipping to change at line 1016 skipping to change at line 1076
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;
//! Constructor //! Constructor
write_once_node(graph& g) : overwrite_node<T>(g) {} write_once_node(graph& g) : overwrite_node<T>(g) {}
//! Copy constructor: call base class copy constructor //! Copy constructor: call base class copy constructor
write_once_node( const write_once_node& src ) : overwrite_node<T>(src) {} write_once_node( const write_once_node& src ) : overwrite_node<T>(src) {}
/* override */ bool try_put( const T &v ) { protected:
template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache
;
template<typename X, typename Y> friend class internal::round_robin_cac
he;
/* override */ task *try_put_task( const T &v ) {
spin_mutex::scoped_lock l( this->my_mutex ); spin_mutex::scoped_lock l( this->my_mutex );
if ( this->my_buffer_is_valid ) { if ( this->my_buffer_is_valid ) {
return false; return NULL;
} else { } else {
this->my_buffer = v; this->my_buffer = v;
this->my_buffer_is_valid = true; this->my_buffer_is_valid = true;
this->my_successors.try_put(v); task *res = this->my_successors.try_put_task(v);
return true; if(!res) res = SUCCESSFULLY_ENQUEUED;
return res;
} }
} }
}; };
//! Forwards messages of type T to all successors //! Forwards messages of type T to all successors
template <typename T> template <typename T>
class broadcast_node : public graph_node, public receiver<T>, public sender <T> { class broadcast_node : public graph_node, public receiver<T>, public sender <T> {
protected:
using graph_node::my_graph; using graph_node::my_graph;
private:
internal::broadcast_cache<T> my_successors; internal::broadcast_cache<T> my_successors;
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;
broadcast_node(graph& g) : graph_node(g) { broadcast_node(graph& g) : graph_node(g) {
my_successors.set_owner( this ); my_successors.set_owner( this );
} }
skipping to change at line 1063 skipping to change at line 1130
my_successors.register_successor( r ); my_successors.register_successor( r );
return true; return true;
} }
//! 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 ) {
my_successors.try_put(t);
return true;
}
protected: protected:
template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache
;
template<typename X, typename Y> friend class internal::round_robin_cac
he;
//! build a task to run the successor if possible. Default is old beha
vior.
/*override*/ task *try_put_task(const T& t) {
task *new_task = my_successors.try_put_task(t);
if(!new_task) new_task = SUCCESSFULLY_ENQUEUED;
return new_task;
}
/*override*/void reset() {} /*override*/void reset() {}
/*override*/void reset_receiver() {} /*override*/void reset_receiver() {}
}; }; // broadcast_node
#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> {
protected:
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;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
typedef buffer_node<T, A> my_class; typedef buffer_node<T, A> my_class;
protected: protected:
typedef size_t size_type; typedef size_t size_type;
internal::round_robin_cache< T, null_rw_mutex > my_successors; internal::round_robin_cache< T, null_rw_mutex > my_successors;
task *my_parent; task *my_parent;
friend class internal::forward_task< buffer_node< T, A > >; friend class internal::forward_task_bypass< buffer_node< T, A > >;
enum op_type {reg_succ, rem_succ, req_item, res_item, rel_res, con_res, put_item, try_fwd}; enum op_type {reg_succ, rem_succ, req_item, res_item, rel_res, con_res, put_item, try_fwd_task };
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
// implements the aggregator_operation concept // implements the aggregator_operation concept
class buffer_operation : public internal::aggregated_operation< buffer_ operation > { class buffer_operation : public internal::aggregated_operation< buffer_ operation > {
public: public:
char type; char type;
T *elem; T *elem;
task * ltask;
successor_type *r; successor_type *r;
buffer_operation(const T& e, op_type t) : buffer_operation(const T& e, op_type t) : type(char(t)), elem(const
type(char(t)), elem(const_cast<T*>(&e)), r(NULL) {} _cast<T*>(&e)) , ltask(NULL) , r(NULL) {}
buffer_operation(op_type t) : type(char(t)), r(NULL) {} buffer_operation(op_type t) : type(char(t)) , ltask(NULL) , r(NULL)
{}
}; };
bool forwarder_busy; bool forwarder_busy;
typedef internal::aggregating_functor<my_class, buffer_operation> my_ha ndler; typedef internal::aggregating_functor<my_class, buffer_operation> my_ha ndler;
friend class internal::aggregating_functor<my_class, buffer_operation>; friend class internal::aggregating_functor<my_class, buffer_operation>;
internal::aggregator< my_handler, buffer_operation> my_aggregator; internal::aggregator< my_handler, buffer_operation> my_aggregator;
virtual void handle_operations(buffer_operation *op_list) { virtual void handle_operations(buffer_operation *op_list) {
buffer_operation *tmp; buffer_operation *tmp = NULL;
bool try_forwarding=false; bool try_forwarding=false;
while (op_list) { while (op_list) {
tmp = op_list; tmp = op_list;
op_list = op_list->next; op_list = op_list->next;
switch (tmp->type) { switch (tmp->type) {
case reg_succ: internal_reg_succ(tmp); try_forwarding = true; break; case reg_succ: internal_reg_succ(tmp); try_forwarding = true; break;
case rem_succ: internal_rem_succ(tmp); break; case rem_succ: internal_rem_succ(tmp); break;
case req_item: internal_pop(tmp); break; case req_item: internal_pop(tmp); break;
case res_item: internal_reserve(tmp); break; case res_item: internal_reserve(tmp); break;
case rel_res: internal_release(tmp); try_forwarding = true; b reak; case rel_res: internal_release(tmp); try_forwarding = true; b reak;
case con_res: internal_consume(tmp); try_forwarding = true; b reak; case con_res: internal_consume(tmp); try_forwarding = true; b reak;
case put_item: internal_push(tmp); try_forwarding = true; brea k; case put_item: internal_push(tmp); try_forwarding = true; brea k;
case try_fwd: internal_forward(tmp); break; case try_fwd_task: internal_forward_task(tmp); break;
} }
} }
if (try_forwarding && !forwarder_busy) { if (try_forwarding && !forwarder_busy) {
forwarder_busy = true; forwarder_busy = true;
task::enqueue(*new(task::allocate_additional_child_of(*my_paren task *new_task = new(task::allocate_additional_child_of(*my_par
t)) internal::forward_task< buffer_node<input_type, A> >(*this)); ent)) internal::
forward_task_bypass
< buffer_node<input_type, A> >(*this);
// tmp should point to the last item handled by the aggregator.
This is the operation
// the handling thread enqueued. So modifying that record will
be okay.
tbb::task *z = tmp->ltask;
tmp->ltask = combine_tasks(z, new_task); // in case the op gen
erated a task
} }
} }
inline task *grab_forwarding_task( buffer_operation &op_data) {
return op_data.ltask;
}
inline bool enqueue_forwarding_task(buffer_operation &op_data) {
task *ft = grab_forwarding_task(op_data);
if(ft) {
task::enqueue(*ft);
return true;
}
return false;
}
//! This is executed by an enqueued task, the "forwarder" //! This is executed by an enqueued task, the "forwarder"
virtual void forward() { virtual task *forward_task() {
buffer_operation op_data(try_fwd); buffer_operation op_data(try_fwd_task);
task *last_task = NULL;
do { do {
op_data.status = WAIT; op_data.status = WAIT;
op_data.ltask = NULL;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
tbb::task *xtask = op_data.ltask;
last_task = combine_tasks(last_task, xtask);
} while (op_data.status == SUCCEEDED); } while (op_data.status == SUCCEEDED);
return last_task;
} }
//! Register successor //! Register successor
virtual void internal_reg_succ(buffer_operation *op) { virtual void internal_reg_succ(buffer_operation *op) {
my_successors.register_successor(*(op->r)); my_successors.register_successor(*(op->r));
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
//! Remove successor //! Remove successor
virtual void internal_rem_succ(buffer_operation *op) { virtual void internal_rem_succ(buffer_operation *op) {
my_successors.remove_successor(*(op->r)); my_successors.remove_successor(*(op->r));
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
//! Tries to forward valid items to successors //! Tries to forward valid items to successors
virtual void internal_forward(buffer_operation *op) { virtual void internal_forward_task(buffer_operation *op) {
if (this->my_reserved || !this->item_valid(this->my_tail-1)) {
__TBB_store_with_release(op->status, FAILED);
this->forwarder_busy = false;
return;
}
T i_copy; T i_copy;
bool success = false; // flagged when a successor accepts task * last_task = NULL;
size_type counter = my_successors.size(); size_type counter = my_successors.size();
// Try forwarding, giving each successor a chance // Try forwarding, giving each successor a chance
while (counter>0 && !this->buffer_empty() && this->item_valid(this- >my_tail-1)) { while (counter>0 && !this->buffer_empty() && this->item_valid(this- >my_tail-1)) {
this->fetch_back(i_copy); this->fetch_back(i_copy);
if( my_successors.try_put(i_copy) ) { task *new_task = my_successors.try_put_task(i_copy);
last_task = combine_tasks(last_task, new_task);
if(new_task) {
this->invalidate_back(); this->invalidate_back();
--(this->my_tail); --(this->my_tail);
success = true; // found an accepting successor
} }
--counter; --counter;
} }
if (success && !counter) op->ltask = last_task; // return task
if (last_task && !counter) {
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
}
else { else {
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
forwarder_busy = false; forwarder_busy = false;
} }
} }
virtual void internal_push(buffer_operation *op) { virtual void internal_push(buffer_operation *op) {
this->push_back(*(op->elem)); this->push_back(*(op->elem));
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
skipping to change at line 1240 skipping to change at line 1346
// //
// message sender implementation // message sender implementation
// //
//! Adds a new successor. //! Adds a new successor.
/** Adds successor r to the list of successors; may forward tasks. */ /** Adds successor r to the list of successors; may forward tasks. */
/* override */ bool register_successor( receiver<output_type> &r ) { /* override */ bool register_successor( receiver<output_type> &r ) {
buffer_operation op_data(reg_succ); buffer_operation op_data(reg_succ);
op_data.r = &r; op_data.r = &r;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
(void)enqueue_forwarding_task(op_data);
return true; return true;
} }
//! Removes a successor. //! Removes a successor.
/** Removes successor r from the list of successors. /** Removes successor r from the list of successors.
It also calls r.remove_predecessor(*this) to remove this node as a predecessor. */ It also calls r.remove_predecessor(*this) to remove this node as a predecessor. */
/* override */ bool remove_successor( receiver<output_type> &r ) { /* override */ bool remove_successor( receiver<output_type> &r ) {
r.remove_predecessor(*this); r.remove_predecessor(*this);
buffer_operation op_data(rem_succ); buffer_operation op_data(rem_succ);
op_data.r = &r; op_data.r = &r;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
// even though this operation does not cause a forward, if we are t
he handler, and
// a forward is scheduled, we may be the first to reach this point
after the aggregator,
// and so should check for the task.
(void)enqueue_forwarding_task(op_data);
return true; return true;
} }
//! Request an item from the buffer_node //! Request an item from the buffer_node
/** true = v contains the returned item<BR> /** true = v contains the returned item<BR>
false = no item has been returned */ false = no item has been returned */
/* override */ bool try_get( T &v ) { /* override */ bool try_get( T &v ) {
buffer_operation op_data(req_item); buffer_operation op_data(req_item);
op_data.elem = &v; op_data.elem = &v;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
(void)enqueue_forwarding_task(op_data);
return (op_data.status==SUCCEEDED); return (op_data.status==SUCCEEDED);
} }
//! Reserves an item. //! Reserves an item.
/** false = no item can be reserved<BR> /** false = no item can be reserved<BR>
true = an item is reserved */ true = an item is reserved */
/* override */ bool try_reserve( T &v ) { /* override */ bool try_reserve( T &v ) {
buffer_operation op_data(res_item); buffer_operation op_data(res_item);
op_data.elem = &v; op_data.elem = &v;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
(void)enqueue_forwarding_task(op_data);
return (op_data.status==SUCCEEDED); return (op_data.status==SUCCEEDED);
} }
//! Release a reserved item. //! Release a reserved item.
/** true = item has been released and so remains in sender */ /** true = item has been released and so remains in sender */
/* override */ bool try_release() { /* override */ bool try_release() {
buffer_operation op_data(rel_res); buffer_operation op_data(rel_res);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
(void)enqueue_forwarding_task(op_data);
return true; return true;
} }
//! Consumes a reserved item. //! Consumes a reserved item.
/** true = item is removed from sender and reservation removed */ /** true = item is removed from sender and reservation removed */
/* override */ bool try_consume() { /* override */ bool try_consume() {
buffer_operation op_data(con_res); buffer_operation op_data(con_res);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
(void)enqueue_forwarding_task(op_data);
return true; return true;
} }
//! Receive an item protected:
/** true is always returned */
/* override */ bool try_put(const T &t) { template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache
;
template<typename X, typename Y> friend class internal::round_robin_cac
he;
//! receive an item, return a task *if possible
/* override */ task *try_put_task(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; task *ft = grab_forwarding_task(op_data);
if(!ft) {
ft = SUCCESSFULLY_ENQUEUED;
}
return ft;
} }
protected:
/*override*/void reset() { /*override*/void reset() {
reservable_item_buffer<T, A>::reset(); reservable_item_buffer<T, A>::reset();
forwarder_busy = false; forwarder_busy = false;
} }
/*override*/void reset_receiver() { /*override*/void reset_receiver() {
// nothing to do; no predecesor_cache // nothing to do; no predecesor_cache
} }
}; }; // buffer_node
//! 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};
//! Tries to forward valid items to successors /* override */ void internal_forward_task(queue_operation *op) {
/* override */ void internal_forward(queue_operation *op) {
T i_copy;
bool success = false; // flagged when a successor accepts
size_type counter = this->my_successors.size();
if (this->my_reserved || !this->item_valid(this->my_head)) { if (this->my_reserved || !this->item_valid(this->my_head)) {
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
this->forwarder_busy = false; this->forwarder_busy = false;
return; return;
} }
T i_copy;
task *last_task = NULL;
size_type counter = this->my_successors.size();
// Keep trying to send items while there is at least one accepting successor // Keep trying to send items while there is at least one accepting successor
while (counter>0 && this->item_valid(this->my_head)) { while (counter>0 && this->item_valid(this->my_head)) {
this->fetch_front(i_copy); this->fetch_front(i_copy);
if(this->my_successors.try_put(i_copy)) { task *new_task = this->my_successors.try_put_task(i_copy);
this->invalidate_front(); if(new_task) {
++(this->my_head); this->invalidate_front();
success = true; // found an accepting successor ++(this->my_head);
last_task = combine_tasks(last_task, new_task);
} }
--counter; --counter;
} }
if (success && !counter) op->ltask = last_task;
if (last_task && !counter)
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
else { else {
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
this->forwarder_busy = false; this->forwarder_busy = false;
} }
} }
/* override */ void internal_pop(queue_operation *op) { /* override */ void internal_pop(queue_operation *op) {
if ( this->my_reserved || !this->item_valid(this->my_head)){ if ( this->my_reserved || !this->item_valid(this->my_head)){
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
skipping to change at line 1456 skipping to change at line 1578
base_type::reset(); 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 = op_list /*, *pop_list*/ ;
bool try_forwarding=false; bool try_forwarding=false;
while (op_list) { while (op_list) {
tmp = op_list; tmp = op_list;
op_list = op_list->next; op_list = op_list->next;
switch (tmp->type) { switch (tmp->type) {
case buffer_node<T, A>::reg_succ: this->internal_reg_succ(tmp); try_forwarding = true; break; case buffer_node<T, A>::reg_succ: this->internal_reg_succ(tmp); try_forwarding = true; break;
case buffer_node<T, A>::rem_succ: this->internal_rem_succ(tmp); break; case buffer_node<T, A>::rem_succ: this->internal_rem_succ(tmp); break;
case buffer_node<T, A>::put_item: internal_push(tmp); try_forwa rding = true; break; case buffer_node<T, A>::put_item: internal_push(tmp); try_forwa rding = true; break;
case buffer_node<T, A>::try_fwd: internal_forward(tmp); break; case buffer_node<T, A>::try_fwd_task: internal_forward_task(tmp ); break;
case buffer_node<T, A>::rel_res: internal_release(tmp); try_for warding = true; break; case buffer_node<T, A>::rel_res: internal_release(tmp); try_for warding = true; break;
case buffer_node<T, A>::con_res: internal_consume(tmp); try_for warding = true; break; case buffer_node<T, A>::con_res: internal_consume(tmp); try_for warding = true; break;
case buffer_node<T, A>::req_item: internal_pop(tmp); break; case buffer_node<T, A>::req_item: internal_pop(tmp); break;
case buffer_node<T, A>::res_item: internal_reserve(tmp); break; case buffer_node<T, A>::res_item: internal_reserve(tmp); break;
} }
} }
// process pops! for now, no special pop processing // process pops! for now, no special pop processing
if (mark<this->my_tail) heapify(); if (mark<this->my_tail) heapify();
if (try_forwarding && !this->forwarder_busy) { if (try_forwarding && !this->forwarder_busy) {
this->forwarder_busy = true; this->forwarder_busy = true;
task::enqueue(*new(task::allocate_additional_child_of(*(this->m task *new_task = new(task::allocate_additional_child_of(*(this-
y_parent))) internal::forward_task< buffer_node<input_type, A> >(*this)); >my_parent))) internal::
forward_task_bypass
< buffer_node<input_type, A> >(*this);
// tmp should point to the last item handled by the aggregator.
This is the operation
// the handling thread enqueued. So modifying that record will
be okay.
tbb::task *tmp1 = tmp->ltask;
tmp->ltask = combine_tasks(tmp1, new_task);
} }
} }
//! Tries to forward valid items to successors //! Tries to forward valid items to successors
/* override */ void internal_forward(prio_operation *op) { /* override */ void internal_forward_task(prio_operation *op) {
T i_copy; T i_copy;
bool success = false; // flagged when a successor accepts task * last_task = NULL; // flagged when a successor accepts
size_type counter = this->my_successors.size(); size_type counter = this->my_successors.size();
if (this->my_reserved || this->my_tail == 0) { if (this->my_reserved || this->my_tail == 0) {
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
this->forwarder_busy = false; this->forwarder_busy = false;
return; return;
} }
// Keep trying to send while there exists an accepting successor // Keep trying to send while there exists an accepting successor
while (counter>0 && this->my_tail > 0) { while (counter>0 && this->my_tail > 0) {
i_copy = this->my_array[0].first; i_copy = this->my_array[0].first;
bool msg = this->my_successors.try_put(i_copy); task * new_task = this->my_successors.try_put_task(i_copy);
if ( msg == true ) { last_task = combine_tasks(last_task, new_task);
if ( new_task ) {
if (mark == this->my_tail) --mark; if (mark == this->my_tail) --mark;
--(this->my_tail); --(this->my_tail);
this->my_array[0].first=this->my_array[this->my_tail].first ; this->my_array[0].first=this->my_array[this->my_tail].first ;
if (this->my_tail > 1) // don't reheap for heap of size 1 if (this->my_tail > 1) // don't reheap for heap of size 1
reheap(); reheap();
success = true; // found an accepting successor
} }
--counter; --counter;
} }
if (success && !counter) op->ltask = last_task;
if (last_task && !counter)
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
else { else {
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
this->forwarder_busy = false; this->forwarder_busy = false;
} }
} }
/* override */ void internal_push(prio_operation *op) { /* override */ void internal_push(prio_operation *op) {
if ( this->my_tail >= this->my_array_size ) if ( this->my_tail >= this->my_array_size )
this->grow_my_array( this->my_tail + 1 ); this->grow_my_array( this->my_tail + 1 );
this->my_array[this->my_tail] = std::make_pair( *(op->elem), true ) ; this->my_array[this->my_tail] = std::make_pair( *(op->elem), true ) ;
++(this->my_tail); ++(this->my_tail);
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
/* override */ void internal_pop(prio_operation *op) { /* override */ void internal_pop(prio_operation *op) {
if ( this->my_reserved == true || this->my_tail == 0 ) { if ( this->my_reserved == true || this->my_tail == 0 ) {
__TBB_store_with_release(op->status, FAILED); __TBB_store_with_release(op->status, FAILED);
} }
else { else {
if (mark<this->my_tail && if (mark<this->my_tail &&
compare(this->my_array[0].first, compare(this->my_array[0].first,
this->my_array[this->my_tail-1].first)) { this->my_array[this->my_tail-1].first)) {
// there are newly pushed elems; last one higher than top // there are newly pushed elems; last one higher than top
// copy the data // copy the data
skipping to change at line 1620 skipping to change at line 1750
this->my_array[cur_pos].first = this->my_array[this->my_tail].first ; this->my_array[cur_pos].first = this->my_array[this->my_tail].first ;
} }
}; };
//! Forwards messages only if the threshold has not been reached //! Forwards messages only if the threshold has not been reached
/** This node forwards items until its threshold is reached. /** This node forwards items until its threshold is reached.
It contains no buffering. If the downstream node rejects, the It contains no buffering. If the downstream node rejects, the
message is dropped. */ message is dropped. */
template< typename T > template< typename T >
class limiter_node : public graph_node, public receiver< T >, public sender < T > { class limiter_node : public graph_node, public receiver< T >, public sender < T > {
protected:
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;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
private: private:
task *my_root_task; task *my_root_task;
size_t my_threshold; size_t my_threshold;
size_t my_count; size_t my_count;
internal::predecessor_cache< T > my_predecessors; internal::predecessor_cache< T > my_predecessors;
spin_mutex my_mutex; spin_mutex my_mutex;
internal::broadcast_cache< T > my_successors; internal::broadcast_cache< T > my_successors;
int init_decrement_predecessors; int init_decrement_predecessors;
friend class internal::forward_task< limiter_node<T> >; friend class internal::forward_task_bypass< limiter_node<T> >;
// Let decrementer call decrement_counter() // Let decrementer call decrement_counter()
friend class internal::decrementer< limiter_node<T> >; friend class internal::decrementer< limiter_node<T> >;
void decrement_counter() { // only returns a valid task pointer or NULL, never SUCCESSFULLY_ENQUEU
ED
task * decrement_counter() {
input_type v; input_type v;
task *rval = NULL;
// If we can't get / put an item immediately then drop the count // If we can't get / put an item immediately then drop the count
if ( my_predecessors.get_item( v ) == false if ( my_predecessors.get_item( v ) == false
|| my_successors.try_put(v) == false ) { || (rval = my_successors.try_put_task(v)) == NULL ) {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
--my_count; --my_count;
if ( !my_predecessors.empty() ) if ( !my_predecessors.empty() ) {
task::enqueue( * new ( task::allocate_additional_child_of( task *rtask = new ( task::allocate_additional_child_of( *my
*my_root_task ) ) _root_task ) )
internal::forward_task< limiter_node<T> >( *thi internal::forward_task_bypass< limiter_node<T> >( *this
s ) ); );
__TBB_ASSERT(!rval, "Have two tasks to handle");
return rtask;
}
} }
return rval;
} }
void forward() { void forward() {
{ {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
if ( my_count < my_threshold ) if ( my_count < my_threshold )
++my_count; ++my_count;
else else
return; return;
} }
decrement_counter(); task * rtask = decrement_counter();
if(rtask) task::enqueue(*rtask);
}
task *forward_task() {
spin_mutex::scoped_lock lock(my_mutex);
if ( my_count >= my_threshold )
return NULL;
++my_count;
task * rtask = decrement_counter();
return rtask;
} }
public: public:
//! The internal receiver< continue_msg > that decrements the count //! The internal receiver< continue_msg > that decrements the count
internal::decrementer< limiter_node<T> > decrement; internal::decrementer< limiter_node<T> > decrement;
//! Constructor //! Constructor
limiter_node(graph &g, size_t threshold, int num_decrement_predecessors =0) : limiter_node(graph &g, size_t threshold, int num_decrement_predecessors =0) :
graph_node(g), my_root_task(g.root_task()), my_threshold(threshold) , my_count(0), graph_node(g), my_root_task(g.root_task()), my_threshold(threshold) , my_count(0),
init_decrement_predecessors(num_decrement_predecessors), init_decrement_predecessors(num_decrement_predecessors),
skipping to change at line 1707 skipping to change at line 1854
} }
//! Removes a successor from this node //! Removes a successor from this node
/** r.remove_predecessor(*this) is also called. */ /** r.remove_predecessor(*this) is also called. */
/* override */ bool remove_successor( receiver<output_type> &r ) { /* override */ bool remove_successor( receiver<output_type> &r ) {
r.remove_predecessor(*this); r.remove_predecessor(*this);
my_successors.remove_successor(r); my_successors.remove_successor(r);
return true; return true;
} }
//! Puts an item to this receiver
/* override */ bool try_put( const T &t ) {
{
spin_mutex::scoped_lock lock(my_mutex);
if ( my_count >= my_threshold )
return false;
else
++my_count;
}
bool msg = my_successors.try_put(t);
if ( msg != true ) {
spin_mutex::scoped_lock lock(my_mutex);
--my_count;
if ( !my_predecessors.empty() )
task::enqueue( * new ( task::allocate_additional_child_of(
*my_root_task ) )
internal::forward_task< limiter_node<T> >( *thi
s ) );
}
return msg;
}
//! Removes src from the list of cached predecessors. //! Removes src from the list of cached predecessors.
/* override */ bool register_predecessor( predecessor_type &src ) { /* override */ bool register_predecessor( predecessor_type &src ) {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
my_predecessors.add( src ); my_predecessors.add( src );
if ( my_count < my_threshold && !my_successors.empty() ) if ( my_count < my_threshold && !my_successors.empty() ) {
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_bypass
< 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: protected:
template< typename R, typename B > friend class run_and_put_task;
template<typename X, typename Y> friend class internal::broadcast_cache
;
template<typename X, typename Y> friend class internal::round_robin_cac
he;
//! Puts an item to this receiver
/* override */ task *try_put_task( const T &t ) {
{
spin_mutex::scoped_lock lock(my_mutex);
if ( my_count >= my_threshold )
return NULL;
else
++my_count;
}
task * rtask = my_successors.try_put_task(t);
if ( !rtask ) { // try_put_task failed.
spin_mutex::scoped_lock lock(my_mutex);
--my_count;
if ( !my_predecessors.empty() ) {
rtask = new ( task::allocate_additional_child_of( *my_root_
task ) )
internal::forward_task_bypass< limiter_node<T> >( *this
);
}
}
return rtask;
}
/*override*/void reset() { /*override*/void reset() {
my_count = 0; my_count = 0;
my_predecessors.reset(); my_predecessors.reset();
decrement.reset_receiver(); decrement.reset_receiver();
} }
/*override*/void reset_receiver() { my_predecessors.reset(); } /*override*/void reset_receiver() { my_predecessors.reset(); }
}; }; // limiter_node
#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;
template<typename OutputTuple, graph_buffer_policy JP=queueing> class join_ node; template<typename OutputTuple, graph_buffer_policy JP=queueing> class join_ node;
template<typename OutputTuple> template<typename OutputTuple>
class join_node<OutputTuple,reserving>: public internal::unfolded_join_node <std::tuple_size<OutputTuple>::value, reserving_port, OutputTuple, reservin g> { class join_node<OutputTuple,reserving>: public internal::unfolded_join_node <tbb::flow::tuple_size<OutputTuple>::value, reserving_port, OutputTuple, re serving> {
private: private:
static const int N = std::tuple_size<OutputTuple>::value; static const int N = tbb::flow::tuple_size<OutputTuple>::value;
typedef typename internal::unfolded_join_node<N, reserving_port, Output Tuple, reserving> unfolded_type; typedef typename internal::unfolded_join_node<N, reserving_port, Output Tuple, reserving> unfolded_type;
public: public:
typedef OutputTuple output_type; typedef OutputTuple output_type;
typedef typename unfolded_type::input_ports_type input_ports_type; typedef typename unfolded_type::input_ports_type input_ports_type;
join_node(graph &g) : unfolded_type(g) { } join_node(graph &g) : unfolded_type(g) { }
join_node(const join_node &other) : unfolded_type(other) {} join_node(const join_node &other) : unfolded_type(other) {}
}; };
template<typename OutputTuple> template<typename OutputTuple>
class join_node<OutputTuple,queueing>: public internal::unfolded_join_node< std::tuple_size<OutputTuple>::value, queueing_port, OutputTuple, queueing> { class join_node<OutputTuple,queueing>: public internal::unfolded_join_node< tbb::flow::tuple_size<OutputTuple>::value, queueing_port, OutputTuple, queu eing> {
private: private:
static const int N = std::tuple_size<OutputTuple>::value; static const int N = tbb::flow::tuple_size<OutputTuple>::value;
typedef typename internal::unfolded_join_node<N, queueing_port, OutputT uple, queueing> unfolded_type; typedef typename internal::unfolded_join_node<N, queueing_port, OutputT uple, queueing> unfolded_type;
public: public:
typedef OutputTuple output_type; typedef OutputTuple output_type;
typedef typename unfolded_type::input_ports_type input_ports_type; typedef typename unfolded_type::input_ports_type input_ports_type;
join_node(graph &g) : unfolded_type(g) { } join_node(graph &g) : unfolded_type(g) { }
join_node(const join_node &other) : unfolded_type(other) {} join_node(const join_node &other) : unfolded_type(other) {}
}; };
// template for tag_matching join_node // template for tag_matching join_node
template<typename OutputTuple> template<typename OutputTuple>
class join_node<OutputTuple, tag_matching> : public internal::unfolded_join _node<std::tuple_size<OutputTuple>::value, class join_node<OutputTuple, tag_matching> : public internal::unfolded_join _node<tbb::flow::tuple_size<OutputTuple>::value,
tag_matching_port, OutputTuple, tag_matching> { tag_matching_port, OutputTuple, tag_matching> {
private: private:
static const int N = std::tuple_size<OutputTuple>::value; static const int N = tbb::flow::tuple_size<OutputTuple>::value;
typedef typename internal::unfolded_join_node<N, tag_matching_port, Out putTuple, tag_matching> unfolded_type; typedef typename internal::unfolded_join_node<N, tag_matching_port, Out putTuple, tag_matching> unfolded_type;
public: public:
typedef OutputTuple output_type; typedef OutputTuple output_type;
typedef typename unfolded_type::input_ports_type input_ports_type; typedef typename unfolded_type::input_ports_type input_ports_type;
template<typename B0, typename B1> template<typename B0, typename B1>
join_node(graph &g, B0 b0, B1 b1) : unfolded_type(g, b0, b1) { } join_node(graph &g, B0 b0, B1 b1) : unfolded_type(g, b0, b1) { }
template<typename B0, typename B1, typename B2> template<typename B0, typename B1, typename B2>
join_node(graph &g, B0 b0, B1 b1, B2 b2) : unfolded_type(g, b0, b1, b2) { } join_node(graph &g, B0 b0, B1 b1, B2 b2) : unfolded_type(g, b0, b1, b2) { }
template<typename B0, typename B1, typename B2, typename B3> template<typename B0, typename B1, typename B2, typename B3>
join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3) : unfolded_type(g, b0, b1, b2, b3) { } join_node(graph &g, B0 b0, B1 b1, B2 b2, B3 b3) : unfolded_type(g, b0, b1, b2, b3) { }
skipping to change at line 1840 skipping to change at line 1993
join_node(const join_node &other) : unfolded_type(other) {} join_node(const join_node &other) : unfolded_type(other) {}
}; };
#if TBB_PREVIEW_GRAPH_NODES #if TBB_PREVIEW_GRAPH_NODES
// or node // or node
#include "internal/_flow_graph_or_impl.h" #include "internal/_flow_graph_or_impl.h"
template<typename InputTuple> template<typename InputTuple>
class or_node : public internal::unfolded_or_node<InputTuple> { class or_node : public internal::unfolded_or_node<InputTuple> {
private: private:
static const int N = std::tuple_size<InputTuple>::value; static const int N = tbb::flow::tuple_size<InputTuple>::value;
public: public:
typedef typename internal::or_output_type<InputTuple>::type output_type ; typedef typename internal::or_output_type<InputTuple>::type output_type ;
typedef typename internal::unfolded_or_node<InputTuple> unfolded_type; typedef typename internal::unfolded_or_node<InputTuple> unfolded_type;
or_node(graph& g) : unfolded_type(g) { } or_node(graph& g) : unfolded_type(g) { }
// Copy constructor // Copy constructor
or_node( const or_node& other ) : unfolded_type(other) { } or_node( const or_node& other ) : unfolded_type(other) { }
}; };
#endif // TBB_PREVIEW_GRAPH_NODES #endif // TBB_PREVIEW_GRAPH_NODES
//! Makes an edge between a single predecessor and a single successor //! Makes an edge between a single predecessor and a single successor
 End of changes. 115 change blocks. 
157 lines changed or deleted 344 lines changed or added


 gcc_generic.h   gcc_generic.h 
skipping to change at line 40 skipping to change at line 40
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_gcc_generic_H #define __TBB_machine_gcc_generic_H
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
#define __TBB_WORDSIZE __SIZEOF_POINTER__ #define __TBB_WORDSIZE __SIZEOF_POINTER__
#if __TBB_GCC_64BIT_ATOMIC_BUILTINS_BROKEN
#define __TBB_64BIT_ATOMICS 0
#endif
/** FPU control setting not available for non-Intel architectures on Androi
d **/
#if __ANDROID__ && __TBB_generic_arch
#define __TBB_CPU_CTL_ENV_PRESENT 0
#endif
#ifdef __BYTE_ORDER__ #ifdef __BYTE_ORDER__
#if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__ #if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__
#define __TBB_BIG_ENDIAN 1 #define __TBB_BIG_ENDIAN 1
#elif __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ #elif __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
#define __TBB_BIG_ENDIAN 0 #define __TBB_BIG_ENDIAN 0
#elif __BYTE_ORDER__==__ORDER_PDP_ENDIAN__ #elif __BYTE_ORDER__==__ORDER_PDP_ENDIAN__
#define __TBB_BIG_ENDIAN -1 // not currently supported #define __TBB_BIG_ENDIAN -1 // not currently supported
#endif #endif
#endif #endif
 End of changes. 1 change blocks. 
0 lines changed or deleted 10 lines changed or added


 linux_common.h   linux_common.h 
skipping to change at line 36 skipping to change at line 36
the GNU General Public License. the GNU General Public License.
*/ */
#ifndef __TBB_machine_H #ifndef __TBB_machine_H
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#include <sched.h> #include <sched.h>
#define __TBB_Yield() sched_yield() #define __TBB_Yield() sched_yield()
#include <unistd.h>
/* Futex definitions */ /* Futex definitions */
#include <sys/syscall.h> #include <sys/syscall.h>
#if defined(SYS_futex) #if defined(SYS_futex)
#define __TBB_USE_FUTEX 1 #define __TBB_USE_FUTEX 1
#include <limits.h> #include <limits.h>
#include <errno.h> #include <errno.h>
// Unfortunately, some versions of Linux do not have a header that defines FUTEX_WAIT and FUTEX_WAKE. // Unfortunately, some versions of Linux do not have a header that defines FUTEX_WAIT and FUTEX_WAKE.
skipping to change at line 67 skipping to change at line 68
#ifndef __TBB_ASSERT #ifndef __TBB_ASSERT
#error machine specific headers must be included after tbb_stddef.h #error machine specific headers must be included after tbb_stddef.h
#endif #endif
namespace tbb { namespace tbb {
namespace internal { namespace internal {
inline int futex_wait( void *futex, int comparand ) { inline int futex_wait( void *futex, int comparand ) {
int r = ::syscall( SYS_futex,futex,__TBB_FUTEX_WAIT,comparand,NULL,NULL ,0 ); int r = syscall( SYS_futex,futex,__TBB_FUTEX_WAIT,comparand,NULL,NULL,0 );
#if TBB_USE_ASSERT #if TBB_USE_ASSERT
int e = errno; int e = errno;
__TBB_ASSERT( r==0||r==EWOULDBLOCK||(r==-1&&(e==EAGAIN||e==EINTR)), "fu tex_wait failed." ); __TBB_ASSERT( r==0||r==EWOULDBLOCK||(r==-1&&(e==EAGAIN||e==EINTR)), "fu tex_wait failed." );
#endif /* TBB_USE_ASSERT */ #endif /* TBB_USE_ASSERT */
return r; return r;
} }
inline int futex_wakeup_one( void *futex ) { inline int futex_wakeup_one( void *futex ) {
int r = ::syscall( SYS_futex,futex,__TBB_FUTEX_WAKE,1,NULL,NULL,0 ); int r = ::syscall( SYS_futex,futex,__TBB_FUTEX_WAKE,1,NULL,NULL,0 );
__TBB_ASSERT( r==0||r==1, "futex_wakeup_one: more than one thread woken up?" ); __TBB_ASSERT( r==0||r==1, "futex_wakeup_one: more than one thread woken up?" );
 End of changes. 2 change blocks. 
1 lines changed or deleted 2 lines changed or added


 linux_ia32.h   linux_ia32.h 
skipping to change at line 36 skipping to change at line 36
the GNU General Public License. the GNU General Public License.
*/ */
#if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_ia32_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_ia32_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_linux_ia32_H #define __TBB_machine_linux_ia32_H
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include "gcc_ia32_common.h"
#define __TBB_WORDSIZE 4 #define __TBB_WORDSIZE 4
#define __TBB_BIG_ENDIAN 0 #define __TBB_BIG_ENDIAN 0
#define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") #define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory")
#define __TBB_control_consistency_helper() __TBB_compiler_fence() #define __TBB_control_consistency_helper() __TBB_compiler_fence()
#define __TBB_acquire_consistency_helper() __TBB_compiler_fence() #define __TBB_acquire_consistency_helper() __TBB_compiler_fence()
#define __TBB_release_consistency_helper() __TBB_compiler_fence() #define __TBB_release_consistency_helper() __TBB_compiler_fence()
#define __TBB_full_memory_fence() __asm__ __volatile__("mfence": : :"memory") #define __TBB_full_memory_fence() __asm__ __volatile__("mfence": : :"memory")
skipping to change at line 99 skipping to change at line 99
#if __INTEL_COMPILER #if __INTEL_COMPILER
#pragma warning( push ) #pragma warning( push )
// reference to EBX in a function requiring stack alignment // reference to EBX in a function requiring stack alignment
#pragma warning( disable: 998 ) #pragma warning( disable: 998 )
#endif #endif
static inline int64_t __TBB_machine_cmpswp8 (volatile void *ptr, int64_t va lue, int64_t comparand ) { static inline int64_t __TBB_machine_cmpswp8 (volatile void *ptr, int64_t va lue, int64_t comparand ) {
#if __TBB_GCC_BUILTIN_ATOMICS_PRESENT #if __TBB_GCC_BUILTIN_ATOMICS_PRESENT
return __sync_val_compare_and_swap( reinterpret_cast<volatile int64_t*> (ptr), comparand, value ); return __sync_val_compare_and_swap( reinterpret_cast<volatile int64_t*> (ptr), comparand, value );
#else /* !__TBB_GCC_BUILTIN_ATOMICS_PRESENT */ #else /* !__TBB_GCC_BUILTIN_ATOMICS_PRESENT */
//TODO: look like ICC 13.0 has some issues with this code, investigate it more deeply
int64_t result; int64_t result;
union { union {
int64_t i64; int64_t i64;
int32_t i32[2]; int32_t i32[2];
}; };
i64 = value; i64 = value;
#if __PIC__ #if __PIC__
/* compiling position-independent code */ /* compiling position-independent code */
// EBX register preserved for compliance with position-independent code rules on IA32 // EBX register preserved for compliance with position-independent code rules on IA32
int32_t tmp; int32_t tmp;
skipping to change at line 151 skipping to change at line 152
); );
#endif /* __PIC__ */ #endif /* __PIC__ */
return result; return result;
#endif /* !__TBB_GCC_BUILTIN_ATOMICS_PRESENT */ #endif /* !__TBB_GCC_BUILTIN_ATOMICS_PRESENT */
} }
#if __INTEL_COMPILER #if __INTEL_COMPILER
#pragma warning( pop ) #pragma warning( pop )
#endif // warning 998 is back #endif // warning 998 is back
static inline int32_t __TBB_machine_lg( uint32_t x ) {
int32_t j;
__asm__ ("bsr %1,%0" : "=r"(j) : "r"(x));
return j;
}
static inline void __TBB_machine_or( volatile void *ptr, uint32_t addend ) { static inline void __TBB_machine_or( volatile void *ptr, uint32_t addend ) {
__asm__ __volatile__("lock\norl %1,%0" : "=m"(*(__TBB_VOLATILE uint32_t *)ptr) : "r"(addend), "m"(*(__TBB_VOLATILE uint32_t *)ptr) : "memory"); __asm__ __volatile__("lock\norl %1,%0" : "=m"(*(__TBB_VOLATILE uint32_t *)ptr) : "r"(addend), "m"(*(__TBB_VOLATILE uint32_t *)ptr) : "memory");
} }
static inline void __TBB_machine_and( volatile void *ptr, uint32_t addend ) { static inline void __TBB_machine_and( volatile void *ptr, uint32_t addend ) {
__asm__ __volatile__("lock\nandl %1,%0" : "=m"(*(__TBB_VOLATILE uint32_ t *)ptr) : "r"(addend), "m"(*(__TBB_VOLATILE uint32_t *)ptr) : "memory"); __asm__ __volatile__("lock\nandl %1,%0" : "=m"(*(__TBB_VOLATILE uint32_ t *)ptr) : "r"(addend), "m"(*(__TBB_VOLATILE uint32_t *)ptr) : "memory");
} }
static inline void __TBB_machine_pause( int32_t delay ) {
for (int32_t i = 0; i < delay; i++) {
__asm__ __volatile__("pause;");
}
return;
}
//TODO: Check if it possible and profitable for IA-32 on (Linux and Windows ) //TODO: Check if it possible and profitable for IA-32 on (Linux and Windows )
//to use of 64-bit load/store via floating point registers together with fu ll fence //to use of 64-bit load/store via floating point registers together with fu ll fence
//for sequentially consistent load/store, instead of CAS. //for sequentially consistent load/store, instead of CAS.
#if __clang__ #if __clang__
#define __TBB_fildq "fildll" #define __TBB_fildq "fildll"
#define __TBB_fistpq "fistpll" #define __TBB_fistpq "fistpll"
#else #else
#define __TBB_fildq "fildq" #define __TBB_fildq "fildq"
#define __TBB_fistpq "fistpq" #define __TBB_fistpq "fistpq"
skipping to change at line 220 skipping to change at line 208
__TBB_machine_store8_slow_perf_warning(ptr); __TBB_machine_store8_slow_perf_warning(ptr);
#endif /* TBB_USE_PERFORMANCE_WARNINGS */ #endif /* TBB_USE_PERFORMANCE_WARNINGS */
__TBB_machine_store8_slow(ptr,value); __TBB_machine_store8_slow(ptr,value);
} }
} }
// Machine specific atomic operations // Machine specific atomic operations
#define __TBB_AtomicOR(P,V) __TBB_machine_or(P,V) #define __TBB_AtomicOR(P,V) __TBB_machine_or(P,V)
#define __TBB_AtomicAND(P,V) __TBB_machine_and(P,V) #define __TBB_AtomicAND(P,V) __TBB_machine_and(P,V)
// Definition of other functions
#define __TBB_Pause(V) __TBB_machine_pause(V)
#define __TBB_Log2(V) __TBB_machine_lg(V)
#define __TBB_USE_GENERIC_DWORD_FETCH_ADD 1 #define __TBB_USE_GENERIC_DWORD_FETCH_ADD 1
#define __TBB_USE_GENERIC_DWORD_FETCH_STORE 1 #define __TBB_USE_GENERIC_DWORD_FETCH_STORE 1
#define __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE 1 #define __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE 1
#define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 #define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1
#define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1 #define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1
#define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 #define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1
// API to retrieve/update FPU control setting
#define __TBB_CPU_CTL_ENV_PRESENT 1
struct __TBB_cpu_ctl_env_t {
int mxcsr;
short x87cw;
};
inline void __TBB_get_cpu_ctl_env ( __TBB_cpu_ctl_env_t* ctl ) {
__asm__ __volatile__ (
"stmxcsr %0\n\t"
"fstcw %1"
: "=m"(ctl->mxcsr), "=m"(ctl->x87cw)
);
}
inline void __TBB_set_cpu_ctl_env ( const __TBB_cpu_ctl_env_t* ctl ) {
__asm__ __volatile__ (
"ldmxcsr %0\n\t"
"fldcw %1"
: : "m"(ctl->mxcsr), "m"(ctl->x87cw)
);
}
 End of changes. 6 change blocks. 
18 lines changed or deleted 2 lines changed or added


 linux_ia64.h   linux_ia64.h 
skipping to change at line 36 skipping to change at line 36
the GNU General Public License. the GNU General Public License.
*/ */
#if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_ia64_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_ia64_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_linux_ia64_H #define __TBB_machine_linux_ia64_H
#include <stdint.h> #include <stdint.h>
#include <unistd.h>
#include <ia64intrin.h> #include <ia64intrin.h>
#define __TBB_WORDSIZE 8 #define __TBB_WORDSIZE 8
#define __TBB_BIG_ENDIAN 0 #define __TBB_BIG_ENDIAN 0
#if __INTEL_COMPILER #if __INTEL_COMPILER
#define __TBB_compiler_fence() #define __TBB_compiler_fence()
#define __TBB_control_consistency_helper() __TBB_compiler_fence() #define __TBB_control_consistency_helper() __TBB_compiler_fence()
#define __TBB_acquire_consistency_helper() #define __TBB_acquire_consistency_helper()
#define __TBB_release_consistency_helper() #define __TBB_release_consistency_helper()
 End of changes. 1 change blocks. 
1 lines changed or deleted 0 lines changed or added


 linux_intel64.h   linux_intel64.h 
skipping to change at line 36 skipping to change at line 36
the GNU General Public License. the GNU General Public License.
*/ */
#if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_intel64_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_linux_intel64_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_linux_intel64_H #define __TBB_machine_linux_intel64_H
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include "gcc_ia32_common.h"
#define __TBB_WORDSIZE 8 #define __TBB_WORDSIZE 8
#define __TBB_BIG_ENDIAN 0 #define __TBB_BIG_ENDIAN 0
#define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory") #define __TBB_compiler_fence() __asm__ __volatile__("": : :"memory")
#define __TBB_control_consistency_helper() __TBB_compiler_fence() #define __TBB_control_consistency_helper() __TBB_compiler_fence()
#define __TBB_acquire_consistency_helper() __TBB_compiler_fence() #define __TBB_acquire_consistency_helper() __TBB_compiler_fence()
#define __TBB_release_consistency_helper() __TBB_compiler_fence() #define __TBB_release_consistency_helper() __TBB_compiler_fence()
#ifndef __TBB_full_memory_fence #ifndef __TBB_full_memory_fence
skipping to change at line 89 skipping to change at line 89
return result; \ return result; \
} \ } \
__TBB_MACHINE_DEFINE_ATOMICS(1,int8_t,"") __TBB_MACHINE_DEFINE_ATOMICS(1,int8_t,"")
__TBB_MACHINE_DEFINE_ATOMICS(2,int16_t,"") __TBB_MACHINE_DEFINE_ATOMICS(2,int16_t,"")
__TBB_MACHINE_DEFINE_ATOMICS(4,int32_t,"") __TBB_MACHINE_DEFINE_ATOMICS(4,int32_t,"")
__TBB_MACHINE_DEFINE_ATOMICS(8,int64_t,"q") __TBB_MACHINE_DEFINE_ATOMICS(8,int64_t,"q")
#undef __TBB_MACHINE_DEFINE_ATOMICS #undef __TBB_MACHINE_DEFINE_ATOMICS
static inline int64_t __TBB_machine_lg( uint64_t x ) {
__TBB_ASSERT(x, "__TBB_Log2(0) undefined");
int64_t j;
__asm__ ("bsr %1,%0" : "=r"(j) : "r"(x));
return j;
}
static inline void __TBB_machine_or( volatile void *ptr, uint64_t value ) { static inline void __TBB_machine_or( volatile void *ptr, uint64_t value ) {
__asm__ __volatile__("lock\norq %1,%0" : "=m"(*(volatile uint64_t*)ptr) : "r"(value), "m"(*(volatile uint64_t*)ptr) : "memory"); __asm__ __volatile__("lock\norq %1,%0" : "=m"(*(volatile uint64_t*)ptr) : "r"(value), "m"(*(volatile uint64_t*)ptr) : "memory");
} }
static inline void __TBB_machine_and( volatile void *ptr, uint64_t value ) { static inline void __TBB_machine_and( volatile void *ptr, uint64_t value ) {
__asm__ __volatile__("lock\nandq %1,%0" : "=m"(*(volatile uint64_t*)ptr ) : "r"(value), "m"(*(volatile uint64_t*)ptr) : "memory"); __asm__ __volatile__("lock\nandq %1,%0" : "=m"(*(volatile uint64_t*)ptr ) : "r"(value), "m"(*(volatile uint64_t*)ptr) : "memory");
} }
#define __TBB_AtomicOR(P,V) __TBB_machine_or(P,V) #define __TBB_AtomicOR(P,V) __TBB_machine_or(P,V)
#define __TBB_AtomicAND(P,V) __TBB_machine_and(P,V) #define __TBB_AtomicAND(P,V) __TBB_machine_and(P,V)
// Definition of other functions
#ifndef __TBB_Pause
static inline void __TBB_machine_pause( int32_t delay ) {
for (int32_t i = 0; i < delay; i++) {
__asm__ __volatile__("pause;");
}
return;
}
#define __TBB_Pause(V) __TBB_machine_pause(V)
#endif /* !__TBB_Pause */
#define __TBB_Log2(V) __TBB_machine_lg(V)
#define __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE 1 #define __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE 1
#define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 #define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1
#define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1 #define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1
#define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 #define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1
// API to retrieve/update FPU control setting
#ifndef __TBB_CPU_CTL_ENV_PRESENT
#define __TBB_CPU_CTL_ENV_PRESENT 1
struct __TBB_cpu_ctl_env_t {
int mxcsr;
short x87cw;
};
inline void __TBB_get_cpu_ctl_env ( __TBB_cpu_ctl_env_t* ctl ) {
#if __TBB_ICC_12_0_INL_ASM_FSTCW_BROKEN
__TBB_cpu_ctl_env_t loc_ctl;
__asm__ __volatile__ (
"stmxcsr %0\n\t"
"fstcw %1"
: "=m"(loc_ctl.mxcsr), "=m"(loc_ctl.x87cw)
);
*ctl = loc_ctl;
#else
__asm__ __volatile__ (
"stmxcsr %0\n\t"
"fstcw %1"
: "=m"(ctl->mxcsr), "=m"(ctl->x87cw)
);
#endif
}
inline void __TBB_set_cpu_ctl_env ( const __TBB_cpu_ctl_env_t* ctl ) {
__asm__ __volatile__ (
"ldmxcsr %0\n\t"
"fldcw %1"
: : "m"(ctl->mxcsr), "m"(ctl->x87cw)
);
}
#endif /* !__TBB_CPU_CTL_ENV_PRESENT */
 End of changes. 4 change blocks. 
21 lines changed or deleted 1 lines changed or added


 macos_common.h   macos_common.h 
skipping to change at line 59 skipping to change at line 59
} }
#define __TBB_HardwareConcurrency() __TBB_macos_available_cpu() #define __TBB_HardwareConcurrency() __TBB_macos_available_cpu()
#ifndef __TBB_full_memory_fence #ifndef __TBB_full_memory_fence
// TBB has not recognized the architecture (none of the architecture ab straction // TBB has not recognized the architecture (none of the architecture ab straction
// headers was included). // headers was included).
#define __TBB_UnknownArchitecture 1 #define __TBB_UnknownArchitecture 1
#endif #endif
#if __TBB_UnknownArchitecture || __TBB_WORDSIZE==4 #if __TBB_UnknownArchitecture || (__TBB_WORDSIZE==4 && !TBB_USE_ICC_BUILTIN S)
// In case of IA32 this is a workaround for compiler bugs triggered by inli ne // In case of IA32 this is a workaround for compiler bugs triggered by inli ne
// assembly implementation of __TBB_machine_cmpswp8 in linux_ia32.h, which may // assembly implementation of __TBB_machine_cmpswp8 in linux_ia32.h, which may
// lead to incorrect codegen (gcc) or compilation failures (any icc includi ng 12.0.4). // lead to incorrect codegen (gcc) or compilation failures (any icc includi ng 12.0.4).
// Implementation of atomic operations based on OS provided primitives // Implementation of atomic operations based on OS provided primitives
#include <libkern/OSAtomic.h> #include <libkern/OSAtomic.h>
static inline int64_t __TBB_machine_cmpswp8_OsX(volatile void *ptr, int64_t value, int64_t comparand) static inline int64_t __TBB_machine_cmpswp8_OsX(volatile void *ptr, int64_t value, int64_t comparand)
{ {
__TBB_ASSERT( !((uintptr_t)ptr&0x7), "address not properly aligned for Mac OS atomics"); __TBB_ASSERT( !((uintptr_t)ptr&0x7), "address not properly aligned for Mac OS atomics");
skipping to change at line 84 skipping to change at line 84
#else #else
int64_t snapshot = OSAtomicAdd64( 0, address ); int64_t snapshot = OSAtomicAdd64( 0, address );
#endif #endif
if( snapshot!=comparand ) return snapshot; if( snapshot!=comparand ) return snapshot;
} }
return comparand; return comparand;
} }
#define __TBB_machine_cmpswp8 __TBB_machine_cmpswp8_OsX #define __TBB_machine_cmpswp8 __TBB_machine_cmpswp8_OsX
#endif /* __TBB_UnknownArchitecture || __TBB_WORDSIZE==4 */ #endif /* __TBB_UnknownArchitecture || (__TBB_WORDSIZE==4 && !TBB_USE_ICC_B UILTINS) */
#if __TBB_UnknownArchitecture #if __TBB_UnknownArchitecture
#ifndef __TBB_WORDSIZE #ifndef __TBB_WORDSIZE
#define __TBB_WORDSIZE 4 #define __TBB_WORDSIZE 4
#endif #endif
#ifdef __TBB_BIG_ENDIAN #ifdef __TBB_BIG_ENDIAN
// Already determined based on hardware architecture. // Already determined based on hardware architecture.
#elif __BIG_ENDIAN__ #elif __BIG_ENDIAN__
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 mutex.h   mutex.h 
skipping to change at line 56 skipping to change at line 56
/** For testing purposes only. /** For testing purposes only.
@ingroup synchronization */ @ingroup synchronization */
class mutex { class mutex {
public: public:
//! Construct unacquired mutex. //! Construct unacquired mutex.
mutex() { mutex() {
#if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
internal_construct(); internal_construct();
#else #else
#if _WIN32||_WIN64 #if _WIN32||_WIN64
InitializeCriticalSection(&impl); InitializeCriticalSectionEx(&impl, 4000, 0);
#else #else
int error_code = pthread_mutex_init(&impl,NULL); int error_code = pthread_mutex_init(&impl,NULL);
if( error_code ) if( error_code )
tbb::internal::handle_perror(error_code,"mutex: pthread_mutex_i nit failed"); tbb::internal::handle_perror(error_code,"mutex: pthread_mutex_i nit failed");
#endif /* _WIN32||_WIN64*/ #endif /* _WIN32||_WIN64*/
#endif /* TBB_USE_ASSERT */ #endif /* TBB_USE_ASSERT */
}; };
~mutex() { ~mutex() {
#if TBB_USE_ASSERT #if TBB_USE_ASSERT
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 parallel_for.h   parallel_for.h 
skipping to change at line 84 skipping to change at line 84
my_body(parent_.my_body), my_body(parent_.my_body),
my_partition(parent_.my_partition,split()) my_partition(parent_.my_partition,split())
{ {
my_partition.set_affinity(*this); my_partition.set_affinity(*this);
my_partition.align_depth( d ); my_partition.align_depth( d );
} }
//! Update affinity info, if any. //! Update affinity info, if any.
/*override*/ void note_affinity( affinity_id id ) { /*override*/ void note_affinity( affinity_id id ) {
my_partition.note_affinity( id ); my_partition.note_affinity( id );
} }
static void run( const Range& range, const Body& body, const Parti tioner& partitioner ) { static void run( const Range& range, const Body& body, Partitioner & partitioner ) {
if( !range.empty() ) { if( !range.empty() ) {
#if !__TBB_TASK_GROUP_CONTEXT || TBB_JOIN_OUTER_TASK_GROUP #if !__TBB_TASK_GROUP_CONTEXT || TBB_JOIN_OUTER_TASK_GROUP
start_for& a = *new(task::allocate_root()) start_for(range, body,const_cast<Partitioner&>(partitioner)); start_for& a = *new(task::allocate_root()) start_for(range, body,partitioner);
#else #else
// Bound context prevents exceptions from body to affect ne sting or sibling algorithms, // Bound context prevents exceptions from body to affect ne sting or sibling algorithms,
// and allows users to handle exceptions safely by wrapping parallel_for in the try-block. // and allows users to handle exceptions safely by wrapping parallel_for in the try-block.
task_group_context context; task_group_context context;
start_for& a = *new(task::allocate_root(context)) start_for (range,body,const_cast<Partitioner&>(partitioner)); start_for& a = *new(task::allocate_root(context)) start_for (range,body,partitioner);
#endif /* __TBB_TASK_GROUP_CONTEXT && !TBB_JOIN_OUTER_TASK_GROUP */ #endif /* __TBB_TASK_GROUP_CONTEXT && !TBB_JOIN_OUTER_TASK_GROUP */
task::spawn_root_and_wait(a); task::spawn_root_and_wait(a);
} }
} }
#if __TBB_TASK_GROUP_CONTEXT #if __TBB_TASK_GROUP_CONTEXT
static void run( const Range& range, const Body& body, const Parti tioner& partitioner, task_group_context& context ) { static void run( const Range& range, const Body& body, Partitioner & partitioner, task_group_context& context ) {
if( !range.empty() ) { if( !range.empty() ) {
start_for& a = *new(task::allocate_root(context)) start_for (range,body,const_cast<Partitioner&>(partitioner)); start_for& a = *new(task::allocate_root(context)) start_for (range,body,partitioner);
task::spawn_root_and_wait(a); task::spawn_root_and_wait(a);
} }
} }
#endif /* __TBB_TASK_GROUP_CONTEXT */ #endif /* __TBB_TASK_GROUP_CONTEXT */
//! create a continuation task, serve as callback for partitioner //! create a continuation task, serve as callback for partitioner
flag_task *create_continuation() { flag_task *create_continuation() {
return new( allocate_continuation() ) flag_task(); return new( allocate_continuation() ) flag_task();
} }
//! Run body for range //! Run body for range
void run_body( Range &r ) { my_body( r ); } void run_body( Range &r ) { my_body( r ); }
skipping to change at line 138 skipping to change at line 138
template<typename Function, typename Index> template<typename Function, typename Index>
class parallel_for_body : internal::no_assign { class parallel_for_body : internal::no_assign {
const Function &my_func; const Function &my_func;
const Index my_begin; const Index my_begin;
const Index my_step; const Index my_step;
public: public:
parallel_for_body( const Function& _func, Index& _begin, Index& _st ep) parallel_for_body( const Function& _func, Index& _begin, Index& _st ep)
: my_func(_func), my_begin(_begin), my_step(_step) {} : my_func(_func), my_begin(_begin), my_step(_step) {}
void operator()( tbb::blocked_range<Index>& r ) const { void operator()( tbb::blocked_range<Index>& r ) const {
#if __INTEL_COMPILER
#pragma ivdep
#endif
for( Index i = r.begin(), k = my_begin + i * my_step; i < r.en d(); i++, k = k + my_step) for( Index i = r.begin(), k = my_begin + i * my_step; i < r.en d(); i++, k = k + my_step)
my_func( k ); my_func( k );
} }
}; };
} // namespace internal } // namespace internal
//! @endcond //! @endcond
// Requirements on Range concept are documented in blocked_range.h // Requirements on Range concept are documented in blocked_range.h
/** \page parallel_for_body_req Requirements on parallel_for body /** \page parallel_for_body_req Requirements on parallel_for body
skipping to change at line 162 skipping to change at line 165
**/ **/
/** \name parallel_for /** \name parallel_for
See also requirements on \ref range_req "Range" and \ref parallel_for_b ody_req "parallel_for Body". **/ See also requirements on \ref range_req "Range" and \ref parallel_for_b ody_req "parallel_for Body". **/
//@{ //@{
//! Parallel iteration over range with default partitioner. //! Parallel iteration over range with default partitioner.
/** @ingroup algorithms **/ /** @ingroup algorithms **/
template<typename Range, typename Body> template<typename Range, typename Body>
void parallel_for( const Range& range, const Body& body ) { void parallel_for( const Range& range, const Body& body ) {
internal::start_for<Range,Body,__TBB_DEFAULT_PARTITIONER>::run(range,bo dy,__TBB_DEFAULT_PARTITIONER()); internal::start_for<Range,Body,const __TBB_DEFAULT_PARTITIONER>::run(ra nge,body,__TBB_DEFAULT_PARTITIONER());
} }
//! Parallel iteration over range with simple partitioner. //! Parallel iteration over range with simple partitioner.
/** @ingroup algorithms **/ /** @ingroup algorithms **/
template<typename Range, typename Body> template<typename Range, typename Body>
void parallel_for( const Range& range, const Body& body, const simple_parti tioner& partitioner ) { void parallel_for( const Range& range, const Body& body, const simple_parti tioner& partitioner ) {
internal::start_for<Range,Body,simple_partitioner>::run(range,body,part itioner); internal::start_for<Range,Body,const simple_partitioner>::run(range,bod y,partitioner);
} }
//! Parallel iteration over range with auto_partitioner. //! Parallel iteration over range with auto_partitioner.
/** @ingroup algorithms **/ /** @ingroup algorithms **/
template<typename Range, typename Body> template<typename Range, typename Body>
void parallel_for( const Range& range, const Body& body, const auto_partiti oner& partitioner ) { void parallel_for( const Range& range, const Body& body, const auto_partiti oner& partitioner ) {
internal::start_for<Range,Body,auto_partitioner>::run(range,body,partit ioner); internal::start_for<Range,Body,const auto_partitioner>::run(range,body, partitioner);
} }
//! Parallel iteration over range with affinity_partitioner. //! Parallel iteration over range with affinity_partitioner.
/** @ingroup algorithms **/ /** @ingroup algorithms **/
template<typename Range, typename Body> template<typename Range, typename Body>
void parallel_for( const Range& range, const Body& body, affinity_partition er& partitioner ) { void parallel_for( const Range& range, const Body& body, affinity_partition er& partitioner ) {
internal::start_for<Range,Body,affinity_partitioner>::run(range,body,pa rtitioner); internal::start_for<Range,Body,affinity_partitioner>::run(range,body,pa rtitioner);
} }
#if __TBB_TASK_GROUP_CONTEXT #if __TBB_TASK_GROUP_CONTEXT
//! Parallel iteration over range with default partitioner and user-supplie
d context.
/** @ingroup algorithms **/
template<typename Range, typename Body>
void parallel_for( const Range& range, const Body& body, task_group_context
& context ) {
internal::start_for<Range,Body,const __TBB_DEFAULT_PARTITIONER>::run(ra
nge, body, __TBB_DEFAULT_PARTITIONER(), context);
}
//! Parallel iteration over range with simple partitioner and user-supplied context. //! Parallel iteration over range with simple partitioner and user-supplied context.
/** @ingroup algorithms **/ /** @ingroup algorithms **/
template<typename Range, typename Body> template<typename Range, typename Body>
void parallel_for( const Range& range, const Body& body, const simple_parti tioner& partitioner, task_group_context& context ) { void parallel_for( const Range& range, const Body& body, const simple_parti tioner& partitioner, task_group_context& context ) {
internal::start_for<Range,Body,simple_partitioner>::run(range, body, pa rtitioner, context); internal::start_for<Range,Body,const simple_partitioner>::run(range, bo dy, partitioner, context);
} }
//! Parallel iteration over range with auto_partitioner and user-supplied c ontext. //! Parallel iteration over range with auto_partitioner and user-supplied c ontext.
/** @ingroup algorithms **/ /** @ingroup algorithms **/
template<typename Range, typename Body> template<typename Range, typename Body>
void parallel_for( const Range& range, const Body& body, const auto_partiti oner& partitioner, task_group_context& context ) { void parallel_for( const Range& range, const Body& body, const auto_partiti oner& partitioner, task_group_context& context ) {
internal::start_for<Range,Body,auto_partitioner>::run(range, body, part itioner, context); internal::start_for<Range,Body,const auto_partitioner>::run(range, body , partitioner, context);
} }
//! Parallel iteration over range with affinity_partitioner and user-suppli ed context. //! Parallel iteration over range with affinity_partitioner and user-suppli ed context.
/** @ingroup algorithms **/ /** @ingroup algorithms **/
template<typename Range, typename Body> template<typename Range, typename Body>
void parallel_for( const Range& range, const Body& body, affinity_partition er& partitioner, task_group_context& context ) { void parallel_for( const Range& range, const Body& body, affinity_partition er& partitioner, task_group_context& context ) {
internal::start_for<Range,Body,affinity_partitioner>::run(range,body,pa rtitioner, context); internal::start_for<Range,Body,affinity_partitioner>::run(range,body,pa rtitioner, context);
} }
#endif /* __TBB_TASK_GROUP_CONTEXT */ #endif /* __TBB_TASK_GROUP_CONTEXT */
//@} //@}
namespace strict_ppl { namespace strict_ppl {
//@{ //@{
//! Parallel iteration over a range of integers with a step provided //! Implementation of parallel iteration over stepped range of integers wit
template <typename Index, typename Function> h explicit step and partitioner
void parallel_for(Index first, Index last, Index step, const Function& f) { template <typename Index, typename Function, typename Partitioner>
void parallel_for_impl(Index first, Index last, Index step, const Function&
f, Partitioner& partitioner) {
if (step <= 0 ) if (step <= 0 )
internal::throw_exception(internal::eid_nonpositive_step); // throw s std::invalid_argument internal::throw_exception(internal::eid_nonpositive_step); // throw s std::invalid_argument
else if (last > first) { else if (last > first) {
// Above "else" avoids "potential divide by zero" warning on some p latforms // Above "else" avoids "potential divide by zero" warning on some p latforms
Index end = (last - first - Index(1)) / step + Index(1); Index end = (last - first - Index(1)) / step + Index(1);
tbb::blocked_range<Index> range(static_cast<Index>(0), end); tbb::blocked_range<Index> range(static_cast<Index>(0), end);
internal::parallel_for_body<Function, Index> body(f, first, step); internal::parallel_for_body<Function, Index> body(f, first, step);
tbb::parallel_for(range, body, tbb::auto_partitioner()); tbb::parallel_for(range, body, partitioner);
} }
} }
//! Parallel iteration over a range of integers with a default step value
//! Parallel iteration over a range of integers with a step provided and de
fault partitioner
template <typename Index, typename Function>
void parallel_for(Index first, Index last, Index step, const Function& f) {
parallel_for_impl<Index,Function,const auto_partitioner>(first, last, s
tep, f, auto_partitioner());
}
//! Parallel iteration over a range of integers with a step provided and si
mple partitioner
template <typename Index, typename Function>
void parallel_for(Index first, Index last, Index step, const Function& f, c
onst simple_partitioner& partitioner) {
parallel_for_impl<Index,Function,const simple_partitioner>(first, last,
step, f, partitioner);
}
//! Parallel iteration over a range of integers with a step provided and au
to partitioner
template <typename Index, typename Function>
void parallel_for(Index first, Index last, Index step, const Function& f, c
onst auto_partitioner& partitioner) {
parallel_for_impl<Index,Function,const auto_partitioner>(first, last, s
tep, f, partitioner);
}
//! Parallel iteration over a range of integers with a step provided and af
finity partitioner
template <typename Index, typename Function>
void parallel_for(Index first, Index last, Index step, const Function& f, a
ffinity_partitioner& partitioner) {
parallel_for_impl(first, last, step, f, partitioner);
}
//! Parallel iteration over a range of integers with a default step value a
nd default partitioner
template <typename Index, typename Function> template <typename Index, typename Function>
void parallel_for(Index first, Index last, const Function& f) { void parallel_for(Index first, Index last, const Function& f) {
parallel_for(first, last, static_cast<Index>(1), f); parallel_for_impl<Index,Function,const auto_partitioner>(first, last, s
tatic_cast<Index>(1), f, auto_partitioner());
}
//! Parallel iteration over a range of integers with a default step value a
nd simple partitioner
template <typename Index, typename Function>
void parallel_for(Index first, Index last, const Function& f, const simple_
partitioner& partitioner) {
parallel_for_impl<Index,Function,const simple_partitioner>(first, last,
static_cast<Index>(1), f, partitioner);
}
//! Parallel iteration over a range of integers with a default step value a
nd auto partitioner
template <typename Index, typename Function>
void parallel_for(Index first, Index last, const Function& f, const auto_pa
rtitioner& partitioner) {
parallel_for_impl<Index,Function,const auto_partitioner>(first, last, s
tatic_cast<Index>(1), f, partitioner);
}
//! Parallel iteration over a range of integers with a default step value a
nd affinity partitioner
template <typename Index, typename Function>
void parallel_for(Index first, Index last, const Function& f, affinity_part
itioner& partitioner) {
parallel_for_impl(first, last, static_cast<Index>(1), f, partitioner);
} }
#if __TBB_TASK_GROUP_CONTEXT #if __TBB_TASK_GROUP_CONTEXT
//! Parallel iteration over a range of integers with explicit step and task //! Implementation of parallel iteration over stepped range of integers wit
group context h explicit step, task group context, and partitioner
template <typename Index, typename Function> template <typename Index, typename Function, typename Partitioner>
void parallel_for(Index first, Index last, Index step, const Function& f, t void parallel_for_impl(Index first, Index last, Index step, const Function&
bb::task_group_context &context) { f, Partitioner& partitioner, tbb::task_group_context &context) {
if (step <= 0 ) if (step <= 0 )
internal::throw_exception(internal::eid_nonpositive_step); // throw s std::invalid_argument internal::throw_exception(internal::eid_nonpositive_step); // throw s std::invalid_argument
else if (last > first) { else if (last > first) {
// Above "else" avoids "potential divide by zero" warning on some p latforms // Above "else" avoids "potential divide by zero" warning on some p latforms
Index end = (last - first - Index(1)) / step + Index(1); Index end = (last - first - Index(1)) / step + Index(1);
tbb::blocked_range<Index> range(static_cast<Index>(0), end); tbb::blocked_range<Index> range(static_cast<Index>(0), end);
internal::parallel_for_body<Function, Index> body(f, first, step); internal::parallel_for_body<Function, Index> body(f, first, step);
tbb::parallel_for(range, body, tbb::auto_partitioner(), context); tbb::parallel_for(range, body, partitioner, context);
} }
} }
//! Parallel iteration over a range of integers with a default step value a
nd explicit task group context //! Parallel iteration over a range of integers with explicit step, task gr
oup context, and default partitioner
template <typename Index, typename Function>
void parallel_for(Index first, Index last, Index step, const Function& f, t
bb::task_group_context &context) {
parallel_for_impl<Index,Function,const auto_partitioner>(first, last, s
tep, f, auto_partitioner(), context);
}
//! Parallel iteration over a range of integers with explicit step, task gr
oup context, and simple partitioner
template <typename Index, typename Function>
void parallel_for(Index first, Index last, Index step, const Function& f, c
onst simple_partitioner& partitioner, tbb::task_group_context &context) {
parallel_for_impl<Index,Function,const simple_partitioner>(first, last,
step, f, partitioner, context);
}
//! Parallel iteration over a range of integers with explicit step, task gr
oup context, and auto partitioner
template <typename Index, typename Function>
void parallel_for(Index first, Index last, Index step, const Function& f, c
onst auto_partitioner& partitioner, tbb::task_group_context &context) {
parallel_for_impl<Index,Function,const auto_partitioner>(first, last, s
tep, f, partitioner, context);
}
//! Parallel iteration over a range of integers with explicit step, task gr
oup context, and affinity partitioner
template <typename Index, typename Function>
void parallel_for(Index first, Index last, Index step, const Function& f, a
ffinity_partitioner& partitioner, tbb::task_group_context &context) {
parallel_for_impl(first, last, step, f, partitioner, context);
}
//! Parallel iteration over a range of integers with a default step value,
explicit task group context, and default partitioner
template <typename Index, typename Function> template <typename Index, typename Function>
void parallel_for(Index first, Index last, const Function& f, tbb::task_gro up_context &context) { void parallel_for(Index first, Index last, const Function& f, tbb::task_gro up_context &context) {
parallel_for(first, last, static_cast<Index>(1), f, context); parallel_for_impl<Index,Function,const auto_partitioner>(first, last, s tatic_cast<Index>(1), f, auto_partitioner(), context);
} }
//! Parallel iteration over a range of integers with a default step value,
explicit task group context, and simple partitioner
template <typename Index, typename Function, typename Partitioner>
void parallel_for(Index first, Index last, const Function& f, const simple_
partitioner& partitioner, tbb::task_group_context &context) {
parallel_for_impl<Index,Function,const simple_partitioner>(first, last,
static_cast<Index>(1), f, partitioner, context);
}
//! Parallel iteration over a range of integers with a default step value,
explicit task group context, and auto partitioner
template <typename Index, typename Function, typename Partitioner>
void parallel_for(Index first, Index last, const Function& f, const auto_pa
rtitioner& partitioner, tbb::task_group_context &context) {
parallel_for_impl<Index,Function,const auto_partitioner>(first, last, s
tatic_cast<Index>(1), f, partitioner, context);
}
//! Parallel iteration over a range of integers with a default step value,
explicit task group context, and affinity_partitioner
template <typename Index, typename Function, typename Partitioner>
void parallel_for(Index first, Index last, const Function& f, affinity_part
itioner& partitioner, tbb::task_group_context &context) {
parallel_for_impl(first, last, static_cast<Index>(1), f, partitioner, c
ontext);
}
#endif /* __TBB_TASK_GROUP_CONTEXT */ #endif /* __TBB_TASK_GROUP_CONTEXT */
//@} //@}
} // namespace strict_ppl } // namespace strict_ppl
using strict_ppl::parallel_for; using strict_ppl::parallel_for;
} // namespace tbb } // namespace tbb
#if TBB_PREVIEW_SERIAL_SUBSET #if TBB_PREVIEW_SERIAL_SUBSET
 End of changes. 21 change blocks. 
25 lines changed or deleted 155 lines changed or added


 partitioner.h   partitioner.h 
skipping to change at line 117 skipping to change at line 117
namespace interface6 { namespace interface6 {
//! @cond INTERNAL //! @cond INTERNAL
namespace internal { namespace internal {
using namespace tbb::internal; using namespace tbb::internal;
template<typename Range, typename Body, typename Partitioner> class start_f or; template<typename Range, typename Body, typename Partitioner> class start_f or;
template<typename Range, typename Body, typename Partitioner> class start_r educe; template<typename Range, typename Body, typename Partitioner> class start_r educe;
//! Join task node that contains shared flag for stealing feedback //! Join task node that contains shared flag for stealing feedback
class flag_task: public task { class flag_task: public task {
public: public:
tbb::atomic<bool> child_stolen; tbb::atomic<bool> my_child_stolen;
flag_task() { child_stolen = false; } flag_task() { my_child_stolen = false; }
task* execute() { return NULL; } task* execute() { return NULL; }
static void mark_task_stolen(task &t) {
tbb::atomic<bool> &flag = static_cast<flag_task*>(t.parent())->my_c
hild_stolen;
#if TBB_USE_THREADING_TOOLS
// Threading tools respect lock prefix but report false-positive da
ta-race via plain store
flag.fetch_and_store<release>(true);
#else
flag = true;
#endif //TBB_USE_THREADING_TOOLS
}
static bool is_peer_stolen(task &t) {
return static_cast<flag_task*>(t.parent())->my_child_stolen;
}
}; };
//! Task to signal the demand without carrying the work //! Task to signal the demand without carrying the work
class signal_task: public task { class signal_task: public task {
public: public:
task* execute() { task* execute() {
if( is_stolen_task() ) { if( is_stolen_task() ) {
static_cast<flag_task*>(parent())->child_stolen = true; flag_task::mark_task_stolen(*this);
} }
return NULL; return NULL;
} }
}; };
//! Depth is a relative depth of recursive division inside a range pool. Re lative depth allows //! Depth is a relative depth of recursive division inside a range pool. Re lative depth allows
//! infinite absolute depth of the recursion for heavily imbalanced workloa ds with range represented //! infinite absolute depth of the recursion for heavily imbalanced workloa ds with range represented
//! by a number that cannot fit into machine word. //! by a number that cannot fit into machine word.
typedef unsigned char depth_t; typedef unsigned char depth_t;
skipping to change at line 293 skipping to change at line 305
#if __TBB_INITIAL_TASK_IMBALANCE #if __TBB_INITIAL_TASK_IMBALANCE
if( src.my_divisor <= 1 ) my_divisor = 0; if( src.my_divisor <= 1 ) my_divisor = 0;
else my_divisor = src.my_divisor = (src.my_divisor+1u) / 2u; else my_divisor = src.my_divisor = (src.my_divisor+1u) / 2u;
#else #else
my_divisor = src.my_divisor / 2u; my_divisor = src.my_divisor / 2u;
src.my_divisor = src.my_divisor - my_divisor; // TODO: check the ef fect separately src.my_divisor = src.my_divisor - my_divisor; // TODO: check the ef fect separately
if(my_divisor) src.my_max_depth += static_cast<depth_t>(__TBB_Log2( src.my_divisor/my_divisor)); if(my_divisor) src.my_max_depth += static_cast<depth_t>(__TBB_Log2( src.my_divisor/my_divisor));
#endif #endif
} }
bool check_being_stolen( task &t) { // part of old should_execute_range () bool check_being_stolen( task &t) { // part of old should_execute_range ()
if( !my_divisor ) { if( !my_divisor ) { // if not from the top P tasks of binary tree
my_divisor = 1; // todo: replace by on-stack flag (partition_st my_divisor = 1; // TODO: replace by on-stack flag (partition_st
ate's member)? ate's member)?
if( t.is_stolen_task() ) { if( t.is_stolen_task() ) {
#if TBB_USE_EXCEPTIONS #if TBB_USE_EXCEPTIONS
// RTTI is available, check whether the cast is valid // RTTI is available, check whether the cast is valid
__TBB_ASSERT(dynamic_cast<flag_task*>(t.parent()), 0); __TBB_ASSERT(dynamic_cast<flag_task*>(t.parent()), 0);
// correctness of the cast relies on avoiding the root task for which: // correctness of the cast relies on avoiding the root task for which:
// - initial value of my_divisor != 0 (protected by separat e assertion) // - initial value of my_divisor != 0 (protected by separat e assertion)
// - is_stolen_task() always return false for the root task . // - is_stolen_task() always returns false for the root tas k.
#endif #endif
static_cast<flag_task*>(t.parent())->child_stolen = true; flag_task::mark_task_stolen(t);
my_max_depth++; my_max_depth++;
return true; return true;
} }
} }
return false; return false;
} }
bool divisions_left() { // part of old should_execute_range() bool divisions_left() { // part of old should_execute_range()
if( my_divisor > 1 ) return true; if( my_divisor > 1 ) return true;
if( my_divisor && my_max_depth > 1 ) { // can split the task and on ce more internally. TODO: on-stack flag instead if( my_divisor && my_max_depth > 1 ) { // can split the task and on ce more internally. TODO: on-stack flag instead
// keep same fragmentation while splitting for the local task p ool // keep same fragmentation while splitting for the local task p ool
my_max_depth--; my_max_depth--;
my_divisor = 0; my_divisor = 0; // decrease max_depth once per task
return true; return true;
} else return false; } else return false;
} }
bool should_create_trap() { bool should_create_trap() {
return my_divisor > 0; return my_divisor > 0;
} }
bool check_for_demand(task &t) { bool check_for_demand(task &t) {
if( static_cast<flag_task*>(t.parent())->child_stolen ) { if( flag_task::is_peer_stolen(t) ) {
my_max_depth++; my_max_depth++;
return true; return true;
} else return false; } else return false;
} }
void align_depth(depth_t base) { void align_depth(depth_t base) {
__TBB_ASSERT(base <= my_max_depth, 0); __TBB_ASSERT(base <= my_max_depth, 0);
my_max_depth -= base; my_max_depth -= base;
} }
depth_t max_depth() { return my_max_depth; } depth_t max_depth() { return my_max_depth; }
}; };
skipping to change at line 383 skipping to change at line 395
void note_affinity( task::affinity_id id ) { void note_affinity( task::affinity_id id ) {
if( map_begin<map_end ) if( map_begin<map_end )
my_array[map_begin] = id; my_array[map_begin] = id;
} }
bool check_for_demand( task &t ) { bool check_for_demand( task &t ) {
if( !my_delay ) { if( !my_delay ) {
if( map_mid<map_end ) { if( map_mid<map_end ) {
__TBB_ASSERT(my_max_depth>__TBB_Log2(map_end-map_mid), 0); __TBB_ASSERT(my_max_depth>__TBB_Log2(map_end-map_mid), 0);
return true;// do not do my_max_depth++ here, but be sure m y_max_depth is big enough return true;// do not do my_max_depth++ here, but be sure m y_max_depth is big enough
} }
if( static_cast<flag_task*>(t.parent())->child_stolen ) { if( flag_task::is_peer_stolen(t) ) {
my_max_depth++; my_max_depth++;
return true; return true;
} }
} else my_delay = false; } else my_delay = false;
return false; return false;
} }
bool divisions_left() { // part of old should_execute_range() bool divisions_left() { // part of old should_execute_range()
return my_divisor > 1; return my_divisor > 1;
} }
bool should_create_trap() { bool should_create_trap() {
 End of changes. 9 change blocks. 
11 lines changed or deleted 25 lines changed or added


 recursive_mutex.h   recursive_mutex.h 
skipping to change at line 55 skipping to change at line 55
/** Mutex that allows recursive mutex acquisition. /** Mutex that allows recursive mutex acquisition.
@ingroup synchronization */ @ingroup synchronization */
class recursive_mutex { class recursive_mutex {
public: public:
//! Construct unacquired recursive_mutex. //! Construct unacquired recursive_mutex.
recursive_mutex() { recursive_mutex() {
#if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS #if TBB_USE_ASSERT || TBB_USE_THREADING_TOOLS
internal_construct(); internal_construct();
#else #else
#if _WIN32||_WIN64 #if _WIN32||_WIN64
InitializeCriticalSection(&impl); InitializeCriticalSectionEx(&impl, 4000, 0);
#else #else
pthread_mutexattr_t mtx_attr; pthread_mutexattr_t mtx_attr;
int error_code = pthread_mutexattr_init( &mtx_attr ); int error_code = pthread_mutexattr_init( &mtx_attr );
if( error_code ) if( error_code )
tbb::internal::handle_perror(error_code,"recursive_mutex: pthre ad_mutexattr_init failed"); tbb::internal::handle_perror(error_code,"recursive_mutex: pthre ad_mutexattr_init failed");
pthread_mutexattr_settype( &mtx_attr, PTHREAD_MUTEX_RECURSIVE ); pthread_mutexattr_settype( &mtx_attr, PTHREAD_MUTEX_RECURSIVE );
error_code = pthread_mutex_init( &impl, &mtx_attr ); error_code = pthread_mutex_init( &impl, &mtx_attr );
if( error_code ) if( error_code )
tbb::internal::handle_perror(error_code,"recursive_mutex: pthre ad_mutex_init failed"); tbb::internal::handle_perror(error_code,"recursive_mutex: pthre ad_mutex_init failed");
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 tbb_config.h   tbb_config.h 
skipping to change at line 41 skipping to change at line 41
/** 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__ * 100 + __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 #if __INTEL_COMPILER == 9999 && __INTEL_COMPILER_BUILD_DATE == 20110811
/* Intel Composer XE 2011 Update 6 incorrectly sets __INTEL_COMPILER. Fix i t. */ /* Intel Composer XE 2011 Update 6 incorrectly sets __INTEL_COMPILER. Fix i t. */
#undef __INTEL_COMPILER #undef __INTEL_COMPILER
#define __INTEL_COMPILER 1210 #define __INTEL_COMPILER 1210
skipping to change at line 87 skipping to change at line 88
/*ICC 12.1 Upd 10 and 13 beta Upd 2 fixed exception_ptr linking issue*/ \ /*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 == 1300 && __INTEL_COMPILER_BUILD_DATE >= 20120530) \
|| (__INTEL_COMPILER == 1210 && __INTEL_COMPILER_BUILD_DATE >= 20120410) || (__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)**/ /** 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) #elif (__TBB_GCC_VERSION >= 40404) && (__TBB_GCC_VERSION < 40600)
#define __TBB_EXCEPTION_PTR_PRESENT __GXX_EXPERIMENTAL_CXX0X __ && __INTEL_COMPILER >= 1200 #define __TBB_EXCEPTION_PTR_PRESENT __GXX_EXPERIMENTAL_CXX0X __ && __INTEL_COMPILER >= 1200
#else #else
#define __TBB_EXCEPTION_PTR_PRESENT 0 #define __TBB_EXCEPTION_PTR_PRESENT 0
#endif #endif
#define __TBB_MAKE_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1700 || (__ GXX_EXPERIMENTAL_CXX0X__ && __TBB_GCC_VERSION >= 40600)) #define __TBB_MAKE_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1700 || (__ GXX_EXPERIMENTAL_CXX0X__ && __TBB_GCC_VERSION >= 40600))
#define __TBB_STATIC_ASSERT_PRESENT __GXX_EXPERIMENTAL_CXX0X __ || (_MSC_VER >= 1600)
#define __TBB_CPP11_TUPLE_PRESENT (_MSC_VER >= 1600) || (( __GXX_EXPERIMENTAL_CXX0X__) && (__TBB_GCC_VERSION >= 40300)) #define __TBB_CPP11_TUPLE_PRESENT (_MSC_VER >= 1600) || (( __GXX_EXPERIMENTAL_CXX0X__) && (__TBB_GCC_VERSION >= 40300))
/** TODO: re-check for compiler version greater than 12.1 if it support
s initializer lists**/
#define __TBB_INITIALIZER_LISTS_PRESENT 0
#elif __clang__ #elif __clang__
//TODO: these options need to be rechecked //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_CXX0 X__ && __TBB_CLANG_VERSION >= 20900) #define __TBB_CPP11_RVALUE_REF_PRESENT (__GXX_EXPERIMENTAL_CXX0 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_MAKE_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_CXX0 X__ && __TBB_CLANG_VERSION > 30100)// TODO: check version
#define __TBB_STATIC_ASSERT_PRESENT (__GXX_EXPERIMENTAL_CXX0 X__ && __TBB_CLANG_VERSION >= 20900)
#define __TBB_CPP11_TUPLE_PRESENT ((__GXX_EXPERIMENTAL_CXX 0X__) && (__TBB_GCC_VERSION >= 40300)) #define __TBB_CPP11_TUPLE_PRESENT ((__GXX_EXPERIMENTAL_CXX 0X__) && (__TBB_GCC_VERSION >= 40300))
#define __TBB_INITIALIZER_LISTS_PRESENT 0
#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 __
/** __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 here is a substitution for _GLIB CXX_ATOMIC_BUILTINS_4, which is a prerequisite /** __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. 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. **/ 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_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_MAKE_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_CXX0 X__ && __TBB_GCC_VERSION >= 40600)
#define __TBB_STATIC_ASSERT_PRESENT ((__TBB_GCC_VERSION >= 4 0300) && (__GXX_EXPERIMENTAL_CXX0X__))
#define __TBB_CPP11_TUPLE_PRESENT ((__GXX_EXPERIMENTAL_CXX 0X__) && (__TBB_GCC_VERSION >= 40300)) #define __TBB_CPP11_TUPLE_PRESENT ((__GXX_EXPERIMENTAL_CXX 0X__) && (__TBB_GCC_VERSION >= 40300))
#define __TBB_INITIALIZER_LISTS_PRESENT ((__GXX_EXPERIMENTAL_CXX 0X__) && (__TBB_GCC_VERSION >= 40400))
#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_STATIC_ASSERT_PRESENT (_MSC_VER >= 1600)
#define __TBB_MAKE_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1700) #define __TBB_MAKE_EXCEPTION_PTR_PRESENT (_MSC_VER >= 1700)
#define __TBB_CPP11_TUPLE_PRESENT (_MSC_VER >= 1600) #define __TBB_CPP11_TUPLE_PRESENT (_MSC_VER >= 1600)
#define __TBB_INITIALIZER_LISTS_PRESENT 0
#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_STATIC_ASSERT_PRESENT 0
#define __TBB_MAKE_EXCEPTION_PTR_PRESENT 0 #define __TBB_MAKE_EXCEPTION_PTR_PRESENT 0
#define __TBB_CPP11_TUPLE_PRESENT 0 #define __TBB_CPP11_TUPLE_PRESENT 0
#define __TBB_INITIALIZER_LISTS_PRESENT 0
#endif #endif
//TODO: not clear how exactly this macro affects exception_ptr - investigat e //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 // 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) #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 #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
#elif _MSC_VER && (_MSC_VER >= 1300 || __INTEL_COMPILER) #elif _MSC_VER && (_MSC_VER >= 1300 || __INTEL_COMPILER)
#define __TBB_DECLSPEC_ALIGN_PRESENT 1 #define __TBB_DECLSPEC_ALIGN_PRESENT 1
#endif #endif
/* Actually ICC supports gcc __sync_* intrinsics starting 11.1,
* but 64 bit support for 32 bit target comes in later ones*/
/* TODO: change the version back to 4.1.2 once macro __TBB_WORD_SIZE become optional */ /* TODO: change the version back to 4.1.2 once macro __TBB_WORD_SIZE become optional */
#if (__TBB_GCC_VERSION >= 40306) && !defined(__INTEL_COMPILER) #if (__TBB_GCC_VERSION >= 40306) || (__INTEL_COMPILER >= 1200)
/** built-in atomics available in GCC since 4.1.2 **/ /** built-in atomics available in GCC since 4.1.2 **/
#define __TBB_GCC_BUILTIN_ATOMICS_PRESENT 1 #define __TBB_GCC_BUILTIN_ATOMICS_PRESENT 1
#endif #endif
#if (__INTEL_COMPILER >= 1210)
/** built-in C++11 style atomics available in compiler since 12.1 **/
#define __TBB_ICC_BUILTIN_ATOMICS_PRESENT 1
#endif
/** User controlled TBB features & modes **/ /** User controlled TBB features & modes **/
#ifndef TBB_USE_DEBUG #ifndef TBB_USE_DEBUG
#ifdef TBB_DO_ASSERT #ifdef TBB_DO_ASSERT
#define TBB_USE_DEBUG TBB_DO_ASSERT #define TBB_USE_DEBUG TBB_DO_ASSERT
#else #else
#ifdef _DEBUG #ifdef _DEBUG
#define TBB_USE_DEBUG _DEBUG #define TBB_USE_DEBUG _DEBUG
#else #else
#define TBB_USE_DEBUG 0 #define TBB_USE_DEBUG 0
skipping to change at line 230 skipping to change at line 249
#endif #endif
#endif /* defined TBB_USE_CAPTURED_EXCEPTION */ #endif /* defined TBB_USE_CAPTURED_EXCEPTION */
/** Check whether the request to use GCC atomics can be satisfied **/ /** Check whether the request to use GCC atomics can be satisfied **/
#if (TBB_USE_GCC_BUILTINS && !__TBB_GCC_BUILTIN_ATOMICS_PRESENT) #if (TBB_USE_GCC_BUILTINS && !__TBB_GCC_BUILTIN_ATOMICS_PRESENT)
#error "GCC atomic built-ins are not supported." #error "GCC atomic built-ins are not supported."
#endif #endif
/** Internal TBB features & modes **/ /** Internal TBB features & modes **/
/** __TBB_DYNAMIC_LOAD_ENABLED describes the system possibility to dynamic /** __TBB_WEAK_SYMBOLS_PRESENT denotes that the system supports the weak sy
load libraries mbol mechanism **/
__TBB_SOURCE_DIRECTLY_INCLUDED is a mode used in whitebox testing when #define __TBB_WEAK_SYMBOLS_PRESENT !_WIN32 && !__APPLE__ && !__sun && ((__T
it's necessary to test internal functions not exported from TBB DLLs BB_GCC_VERSION >= 40000) || defined(__INTEL_COMPILER))
**/
/** __TBB_DYNAMIC_LOAD_ENABLED describes the system possibility to load sha red libraries at run time **/
#ifndef __TBB_DYNAMIC_LOAD_ENABLED #ifndef __TBB_DYNAMIC_LOAD_ENABLED
#define __TBB_DYNAMIC_LOAD_ENABLED 1 #define __TBB_DYNAMIC_LOAD_ENABLED 1
#elif !(_WIN32||_WIN64) && !__TBB_DYNAMIC_LOAD_ENABLED
#define __TBB_WEAK_SYMBOLS 1
#endif #endif
/** __TBB_SOURCE_DIRECTLY_INCLUDED is a mode used in whitebox testing when
it's necessary to test internal functions not exported from TBB DLLs
**/
#if (_WIN32||_WIN64) && __TBB_SOURCE_DIRECTLY_INCLUDED #if (_WIN32||_WIN64) && __TBB_SOURCE_DIRECTLY_INCLUDED
#define __TBB_NO_IMPLICIT_LINKAGE 1 #define __TBB_NO_IMPLICIT_LINKAGE 1
#define __TBBMALLOC_NO_IMPLICIT_LINKAGE 1 #define __TBBMALLOC_NO_IMPLICIT_LINKAGE 1
#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
skipping to change at line 288 skipping to change at line 307
#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) && \ #if !defined(__TBB_SURVIVE_THREAD_SWITCH) && \
(_WIN32 || _WIN64 || __APPLE__ || __linux__) (_WIN32 || _WIN64 || __APPLE__ || (__linux__ && !__ANDROID__))
#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
skipping to change at line 318 skipping to change at line 337
#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.
**/ **/
#if __ANDROID__ && __TBB_GCC_VERSION <= 40403 && !__GCC_HAVE_SYNC_COMPARE_A
ND_SWAP_8
/** Necessary because on Android 8-byte CAS and F&A are not available f
or some processor architectures,
but no mandatory warning message appears from GCC 4.4.3. Instead, o
nly a linkage error occurs when
these atomic operations are used (such as in unit test test_atomic.
exe). **/
#define __TBB_GCC_64BIT_ATOMIC_BUILTINS_BROKEN 1
#endif
#if __GNUC__ && __TBB_x86_64 && __INTEL_COMPILER == 1200 #if __GNUC__ && __TBB_x86_64 && __INTEL_COMPILER == 1200
#define __TBB_ICC_12_0_INL_ASM_FSTCW_BROKEN 1 #define __TBB_ICC_12_0_INL_ASM_FSTCW_BROKEN 1
#endif #endif
#if _MSC_VER && __INTEL_COMPILER && (__INTEL_COMPILER<1110 || __INTEL_COMPI LER==1110 && __INTEL_COMPILER_BUILD_DATE < 20091012) #if _MSC_VER && __INTEL_COMPILER && (__INTEL_COMPILER<1110 || __INTEL_COMPI LER==1110 && __INTEL_COMPILER_BUILD_DATE < 20091012)
/** Necessary to avoid ICL error (or warning in non-strict mode): /** Necessary to avoid ICL error (or warning in non-strict mode):
"exception specification for implicitly declared virtual destructor is "exception specification for implicitly declared virtual destructor is
incompatible with that of overridden one". **/ incompatible with that of overridden one". **/
#define __TBB_DEFAULT_DTOR_THROW_SPEC_BROKEN 1 #define __TBB_DEFAULT_DTOR_THROW_SPEC_BROKEN 1
#endif #endif
skipping to change at line 399 skipping to change at line 425
#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 #if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP
NOR__==5) && defined(__GXX_EXPERIMENTAL_CXX0X__) #define __TBB_WIN8UI_SUPPORT 1
#else
#define __TBB_WIN8UI_SUPPORT 0
#endif
#if !defined(__EXCEPTIONS) && __GNUC__==4 && (__GNUC_MINOR__==4 ||__GNUC_MI
NOR__==5 || (__INTEL_COMPILER==1300 && __TBB_GCC_VERSION>=40600 && __TBB_GC
C_VERSION<=40700)) && defined(__GXX_EXPERIMENTAL_CXX0X__)
/* There is an issue for specific GCC toolchain when C++11 is enabled /* There is an issue for specific GCC toolchain when C++11 is enabled
and exceptions are disabled: and exceptions are disabled:
exceprion_ptr.h/nested_exception.h are using throw unconditionally. exceprion_ptr.h/nested_exception.h are using throw unconditionally.
*/ */
#define __TBB_LIBSTDCPP_EXCEPTION_HEADERS_BROKEN 1 #define __TBB_LIBSTDCPP_EXCEPTION_HEADERS_BROKEN 1
#else #else
#define __TBB_LIBSTDCPP_EXCEPTION_HEADERS_BROKEN 0 #define __TBB_LIBSTDCPP_EXCEPTION_HEADERS_BROKEN 0
#endif #endif
#endif /* __TBB_tbb_config_H */ #endif /* __TBB_tbb_config_H */
 End of changes. 21 change blocks. 
11 lines changed or deleted 50 lines changed or added


 tbb_machine.h   tbb_machine.h 
skipping to change at line 192 skipping to change at line 192
#if __MINGW64__ || __MINGW32__ #if __MINGW64__ || __MINGW32__
extern "C" __declspec(dllimport) int __stdcall SwitchToThread( void ); extern "C" __declspec(dllimport) int __stdcall SwitchToThread( void );
#define __TBB_Yield() SwitchToThread() #define __TBB_Yield() SwitchToThread()
#if (TBB_USE_GCC_BUILTINS && __TBB_GCC_BUILTIN_ATOMICS_PRESENT) #if (TBB_USE_GCC_BUILTINS && __TBB_GCC_BUILTIN_ATOMICS_PRESENT)
#include "machine/gcc_generic.h" #include "machine/gcc_generic.h"
#elif __MINGW64__ #elif __MINGW64__
#include "machine/linux_intel64.h" #include "machine/linux_intel64.h"
#elif __MINGW32__ #elif __MINGW32__
#include "machine/linux_ia32.h" #include "machine/linux_ia32.h"
#endif #endif
#elif (TBB_USE_ICC_BUILTINS && __TBB_ICC_BUILTIN_ATOMICS_PRESENT)
#include "machine/icc_generic.h"
#elif defined(_M_IX86) #elif defined(_M_IX86)
#include "machine/windows_ia32.h" #include "machine/windows_ia32.h"
#elif defined(_M_X64) #elif defined(_M_X64)
#include "machine/windows_intel64.h" #include "machine/windows_intel64.h"
#elif _XBOX #elif _XBOX
#include "machine/xbox360_ppc.h" #include "machine/xbox360_ppc.h"
#endif #endif
#ifdef _MANAGED #ifdef _MANAGED
#pragma managed(pop) #pragma managed(pop)
#endif #endif
#elif __TBB_DEFINE_MIC #elif __TBB_DEFINE_MIC
#include "machine/mic_common.h" #include "machine/mic_common.h"
//TODO: check if ICC atomic intrinsics are available for MIC
#include "machine/linux_intel64.h" #include "machine/linux_intel64.h"
#elif __linux__ || __FreeBSD__ || __NetBSD__ #elif __linux__ || __FreeBSD__ || __NetBSD__
#if (TBB_USE_GCC_BUILTINS && __TBB_GCC_BUILTIN_ATOMICS_PRESENT) #if (TBB_USE_GCC_BUILTINS && __TBB_GCC_BUILTIN_ATOMICS_PRESENT)
#include "machine/gcc_generic.h" #include "machine/gcc_generic.h"
#elif (TBB_USE_ICC_BUILTINS && __TBB_ICC_BUILTIN_ATOMICS_PRESENT)
#include "machine/icc_generic.h"
#elif __i386__ #elif __i386__
#include "machine/linux_ia32.h" #include "machine/linux_ia32.h"
#elif __x86_64__ #elif __x86_64__
#include "machine/linux_intel64.h" #include "machine/linux_intel64.h"
#elif __ia64__ #elif __ia64__
#include "machine/linux_ia64.h" #include "machine/linux_ia64.h"
#elif __powerpc__ #elif __powerpc__
#include "machine/mac_ppc.h" #include "machine/mac_ppc.h"
#elif __TBB_GCC_BUILTIN_ATOMICS_PRESENT #elif __TBB_GCC_BUILTIN_ATOMICS_PRESENT
#include "machine/gcc_generic.h" #include "machine/gcc_generic.h"
#endif #endif
#include "machine/linux_common.h" #include "machine/linux_common.h"
#elif __APPLE__ #elif __APPLE__
//TODO: TBB_USE_GCC_BUILTINS is not used for Mac, Sun, Aix
#if __i386__ #if (TBB_USE_ICC_BUILTINS && __TBB_ICC_BUILTIN_ATOMICS_PRESENT)
#include "machine/icc_generic.h"
#elif __i386__
#include "machine/linux_ia32.h" #include "machine/linux_ia32.h"
#elif __x86_64__ #elif __x86_64__
#include "machine/linux_intel64.h" #include "machine/linux_intel64.h"
#elif __POWERPC__ #elif __POWERPC__
#include "machine/mac_ppc.h" #include "machine/mac_ppc.h"
#endif #endif
#include "machine/macos_common.h" #include "machine/macos_common.h"
#elif _AIX #elif _AIX
skipping to change at line 263 skipping to change at line 270
#include <sched.h> #include <sched.h>
#define __TBB_Yield() sched_yield() #define __TBB_Yield() sched_yield()
#endif /* OS selection */ #endif /* OS selection */
#ifndef __TBB_64BIT_ATOMICS #ifndef __TBB_64BIT_ATOMICS
#define __TBB_64BIT_ATOMICS 1 #define __TBB_64BIT_ATOMICS 1
#endif #endif
//TODO: replace usage of these functions with usage of tbb::atomic, and the
n remove them
//TODO: map functions with W suffix to use cast to tbb::atomic and accordin
g op, i.e. as_atomic().op()
// Special atomic functions // Special atomic functions
#if __TBB_USE_FENCED_ATOMICS #if __TBB_USE_FENCED_ATOMICS
#define __TBB_machine_cmpswp1 __TBB_machine_cmpswp1full_fence #define __TBB_machine_cmpswp1 __TBB_machine_cmpswp1full_fence
#define __TBB_machine_cmpswp2 __TBB_machine_cmpswp2full_fence #define __TBB_machine_cmpswp2 __TBB_machine_cmpswp2full_fence
#define __TBB_machine_cmpswp4 __TBB_machine_cmpswp4full_fence #define __TBB_machine_cmpswp4 __TBB_machine_cmpswp4full_fence
#define __TBB_machine_cmpswp8 __TBB_machine_cmpswp8full_fence #define __TBB_machine_cmpswp8 __TBB_machine_cmpswp8full_fence
#if __TBB_WORDSIZE==8 #if __TBB_WORDSIZE==8
#define __TBB_machine_fetchadd8 __TBB_machine_fetchadd8 full_fence #define __TBB_machine_fetchadd8 __TBB_machine_fetchadd8 full_fence
#define __TBB_machine_fetchstore8 __TBB_machine_fetchstor e8full_fence #define __TBB_machine_fetchstore8 __TBB_machine_fetchstor e8full_fence
#define __TBB_FetchAndAddWrelease(P,V) __TBB_machine_fetchadd8 release(P,V) #define __TBB_FetchAndAddWrelease(P,V) __TBB_machine_fetchadd8 release(P,V)
#define __TBB_FetchAndIncrementWacquire(P) __TBB_machine_fetchadd8 acquire(P,1) #define __TBB_FetchAndIncrementWacquire(P) __TBB_machine_fetchadd8 acquire(P,1)
#define __TBB_FetchAndDecrementWrelease(P) __TBB_machine_fetchadd8 release(P,(-1)) #define __TBB_FetchAndDecrementWrelease(P) __TBB_machine_fetchadd8 release(P,(-1))
#else #else
#error Define macros for 4-byte word, similarly to the above __TBB_ #define __TBB_machine_fetchadd4 __TBB_machine_fetchadd4
WORDSIZE==8 branch. full_fence
#define __TBB_machine_fetchstore4 __TBB_machine_fetchstor
e4full_fence
#define __TBB_FetchAndAddWrelease(P,V) __TBB_machine_fetchadd4
release(P,V)
#define __TBB_FetchAndIncrementWacquire(P) __TBB_machine_fetchadd4
acquire(P,1)
#define __TBB_FetchAndDecrementWrelease(P) __TBB_machine_fetchadd4
release(P,(-1))
#endif /* __TBB_WORDSIZE==4 */ #endif /* __TBB_WORDSIZE==4 */
#else /* !__TBB_USE_FENCED_ATOMICS */ #else /* !__TBB_USE_FENCED_ATOMICS */
#define __TBB_FetchAndAddWrelease(P,V) __TBB_FetchAndAddW(P,V) #define __TBB_FetchAndAddWrelease(P,V) __TBB_FetchAndAddW(P,V)
#define __TBB_FetchAndIncrementWacquire(P) __TBB_FetchAndAddW(P,1) #define __TBB_FetchAndIncrementWacquire(P) __TBB_FetchAndAddW(P,1)
#define __TBB_FetchAndDecrementWrelease(P) __TBB_FetchAndAddW(P,(-1)) #define __TBB_FetchAndDecrementWrelease(P) __TBB_FetchAndAddW(P,(-1))
#endif /* !__TBB_USE_FENCED_ATOMICS */ #endif /* !__TBB_USE_FENCED_ATOMICS */
#if __TBB_WORDSIZE==4 #if __TBB_WORDSIZE==4
#define __TBB_CompareAndSwapW(P,V,C) __TBB_machine_cmpswp4(P,V,C) #define __TBB_CompareAndSwapW(P,V,C) __TBB_machine_cmpswp4(P,V,C)
#define __TBB_FetchAndAddW(P,V) __TBB_machine_fetchadd4(P,V) #define __TBB_FetchAndAddW(P,V) __TBB_machine_fetchadd4(P,V)
 End of changes. 6 change blocks. 
4 lines changed or deleted 23 lines changed or added


 tbb_stddef.h   tbb_stddef.h 
skipping to change at line 37 skipping to change at line 37
*/ */
#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 1 #define TBB_VERSION_MINOR 1
// Engineering-focused interface version // Engineering-focused interface version
#define TBB_INTERFACE_VERSION 6100 #define TBB_INTERFACE_VERSION 6101
#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. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 tuple   tuple 
skipping to change at line 40 skipping to change at line 40
#define __TBB_tuple_H #define __TBB_tuple_H
#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_TYPENAME_T_PACK
#define __TBB_CLASS_U_PACK #define __TBB_TYPENAME_U_PACK
#define __TBB_NULL_TYPE_PACK #define __TBB_NULL_TYPE_PACK
#define __TBB_REF_T_PARAM_PACK #define __TBB_REF_T_PARAM_PACK
#define __TBB_CONST_REF_T_PARAM_PACK #define __TBB_CONST_REF_T_PARAM_PACK
#define __TBB_T_PARAM_LIST_PACK #define __TBB_T_PARAM_LIST_PACK
#define __TBB_CONST_NULL_REF_PACK #define __TBB_CONST_NULL_REF_PACK
// //
#elif __TBB_VARIADIC_MAX == 6 #elif __TBB_VARIADIC_MAX == 6
#define __TBB_T_PACK ,T5 #define __TBB_T_PACK ,T5
#define __TBB_U_PACK ,U5 #define __TBB_U_PACK ,U5
#define __TBB_CLASS_T_PACK , class T5 #define __TBB_TYPENAME_T_PACK , typename T5
#define __TBB_CLASS_U_PACK , class U5 #define __TBB_TYPENAME_U_PACK , typename U5
#define __TBB_NULL_TYPE_PACK , null_type #define __TBB_NULL_TYPE_PACK , null_type
#define __TBB_REF_T_PARAM_PACK ,T5& t5 #define __TBB_REF_T_PARAM_PACK ,T5& t5
#define __TBB_CONST_REF_T_PARAM_PACK ,const T5& t5 #define __TBB_CONST_REF_T_PARAM_PACK ,const T5& t5
#define __TBB_T_PARAM_LIST_PACK ,t5 #define __TBB_T_PARAM_LIST_PACK ,t5
#define __TBB_CONST_NULL_REF_PACK , const null_type& #define __TBB_CONST_NULL_REF_PACK , const null_type&
// //
#elif __TBB_VARIADIC_MAX == 7 #elif __TBB_VARIADIC_MAX == 7
#define __TBB_T_PACK ,T5, T6 #define __TBB_T_PACK ,T5, T6
#define __TBB_U_PACK ,U5, U6 #define __TBB_U_PACK ,U5, U6
#define __TBB_CLASS_T_PACK , class T5 , class T6 #define __TBB_TYPENAME_T_PACK , typename T5 , typename T6
#define __TBB_CLASS_U_PACK , class U5 , class U6 #define __TBB_TYPENAME_U_PACK , typename U5 , typename U6
#define __TBB_NULL_TYPE_PACK , null_type, null_type #define __TBB_NULL_TYPE_PACK , null_type, null_type
#define __TBB_REF_T_PARAM_PACK ,T5& t5, T6& t6 #define __TBB_REF_T_PARAM_PACK ,T5& t5, T6& t6
#define __TBB_CONST_REF_T_PARAM_PACK ,const T5& t5, const T6& t6 #define __TBB_CONST_REF_T_PARAM_PACK ,const T5& t5, const T6& t6
#define __TBB_T_PARAM_LIST_PACK ,t5 ,t6 #define __TBB_T_PARAM_LIST_PACK ,t5 ,t6
#define __TBB_CONST_NULL_REF_PACK , const null_type&, const null_type& #define __TBB_CONST_NULL_REF_PACK , const null_type&, const null_type&
// //
#elif __TBB_VARIADIC_MAX == 8 #elif __TBB_VARIADIC_MAX == 8
#define __TBB_T_PACK ,T5, T6, T7 #define __TBB_T_PACK ,T5, T6, T7
#define __TBB_U_PACK ,U5, U6, U7 #define __TBB_U_PACK ,U5, U6, U7
#define __TBB_CLASS_T_PACK , class T5 , class T6, class T7 #define __TBB_TYPENAME_T_PACK , typename T5 , typename T6, typename T7
#define __TBB_CLASS_U_PACK , class U5 , class U6, class U7 #define __TBB_TYPENAME_U_PACK , typename U5 , typename U6, typename U7
#define __TBB_NULL_TYPE_PACK , null_type, null_type, null_type #define __TBB_NULL_TYPE_PACK , null_type, null_type, null_type
#define __TBB_REF_T_PARAM_PACK ,T5& t5, T6& t6, T7& t7 #define __TBB_REF_T_PARAM_PACK ,T5& t5, T6& t6, T7& t7
#define __TBB_CONST_REF_T_PARAM_PACK , const T5& t5, const T6& t6, const T7 & t7 #define __TBB_CONST_REF_T_PARAM_PACK , const T5& t5, const T6& t6, const T7 & t7
#define __TBB_T_PARAM_LIST_PACK ,t5 ,t6 ,t7 #define __TBB_T_PARAM_LIST_PACK ,t5 ,t6 ,t7
#define __TBB_CONST_NULL_REF_PACK , const null_type&, const null_type&, con st null_type& #define __TBB_CONST_NULL_REF_PACK , const null_type&, const null_type&, con st null_type&
// //
#elif __TBB_VARIADIC_MAX == 9 #elif __TBB_VARIADIC_MAX == 9
#define __TBB_T_PACK ,T5, T6, T7, T8 #define __TBB_T_PACK ,T5, T6, T7, T8
#define __TBB_U_PACK ,U5, U6, U7, U8 #define __TBB_U_PACK ,U5, U6, U7, U8
#define __TBB_CLASS_T_PACK , class T5, class T6, class T7, class T8 #define __TBB_TYPENAME_T_PACK , typename T5, typename T6, typename T7, type
#define __TBB_CLASS_U_PACK , class U5, class U6, class U7, class U8 name T8
#define __TBB_TYPENAME_U_PACK , typename U5, typename U6, typename U7, type
name U8
#define __TBB_NULL_TYPE_PACK , null_type, null_type, null_type, null_type #define __TBB_NULL_TYPE_PACK , null_type, null_type, null_type, null_type
#define __TBB_REF_T_PARAM_PACK ,T5& t5, T6& t6, T7& t7, T8& t8 #define __TBB_REF_T_PARAM_PACK ,T5& t5, T6& t6, T7& t7, T8& t8
#define __TBB_CONST_REF_T_PARAM_PACK , const T5& t5, const T6& t6, const T7 & t7, const T8& t8 #define __TBB_CONST_REF_T_PARAM_PACK , const T5& t5, const T6& t6, const T7 & t7, const T8& t8
#define __TBB_T_PARAM_LIST_PACK ,t5 ,t6 ,t7 ,t8 #define __TBB_T_PARAM_LIST_PACK ,t5 ,t6 ,t7 ,t8
#define __TBB_CONST_NULL_REF_PACK , const null_type&, const null_type&, con st null_type&, const null_type& #define __TBB_CONST_NULL_REF_PACK , const null_type&, const null_type&, con st null_type&, const null_type&
// //
#elif __TBB_VARIADIC_MAX >= 10 #elif __TBB_VARIADIC_MAX >= 10
#define __TBB_T_PACK ,T5, T6, T7, T8, T9 #define __TBB_T_PACK ,T5, T6, T7, T8, T9
#define __TBB_U_PACK ,U5, U6, U7, U8, U9 #define __TBB_U_PACK ,U5, U6, U7, U8, U9
#define __TBB_CLASS_T_PACK , class T5, class T6, class T7, class T8, class #define __TBB_TYPENAME_T_PACK , typename T5, typename T6, typename T7, type
T9 name T8, typename T9
#define __TBB_CLASS_U_PACK , class U5, class U6, class U7, class U8, class #define __TBB_TYPENAME_U_PACK , typename U5, typename U6, typename U7, type
U9 name U8, typename U9
#define __TBB_NULL_TYPE_PACK , null_type, null_type, null_type, null_type, null_type #define __TBB_NULL_TYPE_PACK , null_type, null_type, null_type, null_type, null_type
#define __TBB_REF_T_PARAM_PACK ,T5& t5, T6& t6, T7& t7, T8& t8, T9& t9 #define __TBB_REF_T_PARAM_PACK ,T5& t5, T6& t6, T7& t7, T8& t8, T9& t9
#define __TBB_CONST_REF_T_PARAM_PACK , const T5& t5, const T6& t6, const T7 & t7, const T8& t8, const T9& t9 #define __TBB_CONST_REF_T_PARAM_PACK , const T5& t5, const T6& t6, const T7 & t7, const T8& t8, const T9& t9
#define __TBB_T_PARAM_LIST_PACK ,t5 ,t6 ,t7 ,t8 ,t9 #define __TBB_T_PARAM_LIST_PACK ,t5 ,t6 ,t7 ,t8 ,t9
#define __TBB_CONST_NULL_REF_PACK , const null_type&, const null_type&, con st null_type&, const null_type&, const null_type& #define __TBB_CONST_NULL_REF_PACK , const null_type&, const null_type&, con st null_type&, const null_type&, const null_type&
#endif #endif
namespace tbb { namespace tbb {
namespace interface5 { namespace interface5 {
namespace internal { namespace internal {
struct null_type { }; struct null_type { };
} }
using internal::null_type; using internal::null_type;
// tuple forward declaration // tuple forward declaration
template <class T0=null_type, class T1=null_type, class T2=null_type, class template <typename T0=null_type, typename T1=null_type, typename T2=null_ty
T3=null_type, class T4=null_type pe,
typename T3=null_type, typename T4=null_type
#if __TBB_VARIADIC_MAX >= 6 #if __TBB_VARIADIC_MAX >= 6
, class T5=null_type , typename T5=null_type
#if __TBB_VARIADIC_MAX >= 7 #if __TBB_VARIADIC_MAX >= 7
, class T6=null_type , typename T6=null_type
#if __TBB_VARIADIC_MAX >= 8 #if __TBB_VARIADIC_MAX >= 8
, class T7=null_type , typename T7=null_type
#if __TBB_VARIADIC_MAX >= 9 #if __TBB_VARIADIC_MAX >= 9
, class T8=null_type , typename T8=null_type
#if __TBB_VARIADIC_MAX >= 10 #if __TBB_VARIADIC_MAX >= 10
, class T9=null_type , typename T9=null_type
#endif #endif
#endif #endif
#endif #endif
#endif #endif
#endif #endif
> >
class tuple; class tuple;
namespace internal { namespace internal {
// const null_type temp // const null_type temp
inline const null_type cnull() { return null_type(); } inline const null_type cnull() { return null_type(); }
// cons forward declaration // cons forward declaration
template <class HT, class TT> struct cons; template <typename HT, typename TT> struct cons;
// type of a component of the cons // type of a component of the cons
template<int N, class T> template<int N, typename T>
struct component { struct component {
typedef typename T::tail_type next; typedef typename T::tail_type next;
typedef typename component<N-1,next>::type type; typedef typename component<N-1,next>::type type;
}; };
template<class T> template<typename T>
struct component<0,T> { struct component<0,T> {
typedef typename T::head_type type; typedef typename T::head_type type;
}; };
template<> template<>
struct component<0,null_type> { struct component<0,null_type> {
typedef null_type type; typedef null_type type;
}; };
// const version of component // const version of component
template<int N, class T> template<int N, typename T>
struct component<N, const T> struct component<N, const T>
{ {
typedef typename T::tail_type next; typedef typename T::tail_type next;
typedef const typename component<N-1,next>::type type; typedef const typename component<N-1,next>::type type;
}; };
template<class T> template<typename T>
struct component<0, const T> struct component<0, const T>
{ {
typedef const typename T::head_type type; typedef const typename T::head_type type;
}; };
// helper class for getting components of cons // helper class for getting components of cons
template< int N> template< int N>
struct get_helper { struct get_helper {
template<class HT, class TT> template<typename HT, typename TT>
inline static typename component<N, cons<HT,TT> >::type& get(cons<HT,TT>& t i) { inline static typename component<N, cons<HT,TT> >::type& get(cons<HT,TT>& t i) {
return get_helper<N-1>::get(ti.tail); return get_helper<N-1>::get(ti.tail);
} }
template<class HT, class TT> template<typename HT, typename TT>
inline static typename component<N, cons<HT,TT> >::type const& get(const co ns<HT,TT>& ti) { inline static typename component<N, cons<HT,TT> >::type const& get(const co ns<HT,TT>& ti) {
return get_helper<N-1>::get(ti.tail); return get_helper<N-1>::get(ti.tail);
} }
}; };
template<> template<>
struct get_helper<0> { struct get_helper<0> {
template<class HT, class TT> template<typename HT, typename TT>
inline static typename component<0, cons<HT,TT> >::type& get(cons<HT,TT>& t i) { inline static typename component<0, cons<HT,TT> >::type& get(cons<HT,TT>& t i) {
return ti.head; return ti.head;
} }
template<class HT, class TT> template<typename HT, typename TT>
inline static typename component<0, cons<HT,TT> >::type const& get(const co ns<HT,TT>& ti) { inline static typename component<0, cons<HT,TT> >::type const& get(const co ns<HT,TT>& ti) {
return ti.head; return ti.head;
} }
}; };
// traits adaptor // traits adaptor
template <class T0, class T1, class T2, class T3, class T4 __TBB_CLASS_T_PA CK> template <typename T0, typename T1, typename T2, typename T3, typename T4 _ _TBB_TYPENAME_T_PACK>
struct tuple_traits { struct tuple_traits {
typedef cons <T0, typename tuple_traits<T1, T2, T3, T4 __TBB_T_PACK , n ull_type>::U > U; typedef cons <T0, typename tuple_traits<T1, T2, T3, T4 __TBB_T_PACK , n ull_type>::U > U;
}; };
template <> template <typename T0>
struct tuple_traits<class T0, null_type, null_type, null_type, null_type __ struct tuple_traits<T0, null_type, null_type, null_type, null_type __TBB_NU
TBB_NULL_TYPE_PACK > { LL_TYPE_PACK > {
typedef cons<T0, null_type> U; typedef cons<T0, null_type> U;
}; };
template<> template<>
struct tuple_traits<null_type, null_type, null_type, null_type, null_type _ _TBB_NULL_TYPE_PACK > { struct tuple_traits<null_type, null_type, null_type, null_type, null_type _ _TBB_NULL_TYPE_PACK > {
typedef null_type U; typedef null_type U;
}; };
// core cons defs // core cons defs
template <class HT, class TT> template <typename HT, typename TT>
struct cons{ struct cons{
typedef HT head_type; typedef HT head_type;
typedef TT tail_type; typedef TT tail_type;
HT head; head_type head;
TT tail; tail_type tail;
static const int length = 1 + tail_type::length; static const int length = 1 + tail_type::length;
// default constructors // default constructors
explicit cons() : head(), tail() { } explicit cons() : head(), tail() { }
// non-default constructors // non-default constructors
cons(head_type& h, const tail_type& t) : head(h), tail(t) { } cons(head_type& h, const tail_type& t) : head(h), tail(t) { }
template <class T0, class T1, class T2, class T3, class T4 __TBB_CLASS_ T_PACK > template <typename T0, typename T1, typename T2, typename T3, typename T4 __TBB_TYPENAME_T_PACK >
cons(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4 __TBB_CONST_REF_T_PARAM_PACK) : cons(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4 __TBB_CONST_REF_T_PARAM_PACK) :
head(t0), tail(t1, t2, t3, t4 __TBB_T_PARAM_LIST_PACK, cnull()) { } head(t0), tail(t1, t2, t3, t4 __TBB_T_PARAM_LIST_PACK, cnull()) { }
template <class T0, class T1, class T2, class T3, class T4 __TBB_CLASS_ T_PACK > template <typename T0, typename T1, typename T2, typename T3, typename T4 __TBB_TYPENAME_T_PACK >
cons(T0& t0, T1& t1, T2& t2, T3& t3, T4& t4 __TBB_REF_T_PARAM_PACK) : cons(T0& t0, T1& t1, T2& t2, T3& t3, T4& t4 __TBB_REF_T_PARAM_PACK) :
head(t0), tail(t1, t2, t3, t4 __TBB_T_PARAM_LIST_PACK , cnull()) { } head(t0), tail(t1, t2, t3, t4 __TBB_T_PARAM_LIST_PACK , cnull()) { }
template <class HT1, class TT1> template <typename HT1, typename TT1>
cons(const cons<HT1,TT1>& other) : head(other.head), tail(other.tail) { } cons(const cons<HT1,TT1>& other) : head(other.head), tail(other.tail) { }
cons& operator=(const cons& other) { head = other.head; tail = other.ta il; return *this; } cons& operator=(const cons& other) { head = other.head; tail = other.ta il; return *this; }
friend bool operator==(const cons& me, const cons& other) { friend bool operator==(const cons& me, const cons& other) {
return me.head == other.head && me.tail == other.tail; return me.head == other.head && me.tail == other.tail;
} }
friend bool operator<(const cons& me, const cons& other) { friend bool operator<(const cons& me, const cons& other) {
return me.head < other.head || (!(other.head < me.head) && me.tail < other.tail); return me.head < other.head || (!(other.head < me.head) && me.tail < other.tail);
} }
friend bool operator>(const cons& me, const cons& other) { return othe r<me; } friend bool operator>(const cons& me, const cons& other) { return othe r<me; }
friend bool operator!=(const cons& me, const cons& other) { return !(me ==other); } friend bool operator!=(const cons& me, const cons& other) { return !(me ==other); }
friend bool operator>=(const cons& me, const cons& other) { return !(me <other); } friend bool operator>=(const cons& me, const cons& other) { return !(me <other); }
friend bool operator<=(const cons& me, const cons& other) { return !(me >other); } friend bool operator<=(const cons& me, const cons& other) { return !(me >other); }
template<class HT1, class TT1> template<typename HT1, typename TT1>
friend bool operator==(const cons<HT,TT>& me, const cons<HT1,TT1>& othe r) { friend bool operator==(const cons<HT,TT>& me, const cons<HT1,TT1>& othe r) {
return me.head == other.head && me.tail == other.tail; return me.head == other.head && me.tail == other.tail;
} }
template<class HT1, class TT1> template<typename HT1, typename TT1>
friend bool operator<(const cons<HT,TT>& me, const cons<HT1,TT1>& other ) { friend bool operator<(const cons<HT,TT>& me, const cons<HT1,TT1>& other ) {
return me.head < other.head || (!(other.head < me.head) && me.tail < other.tail); return me.head < other.head || (!(other.head < me.head) && me.tail < other.tail);
} }
template<class HT1, class TT1> template<typename HT1, typename TT1>
friend bool operator>(const cons<HT,TT>& me, const cons<HT1,TT1>& other ) { return other<me; } friend bool operator>(const cons<HT,TT>& me, const cons<HT1,TT1>& other ) { return other<me; }
template<class HT1, class TT1> template<typename HT1, typename TT1>
friend bool operator!=(const cons<HT,TT>& me, const cons<HT1,TT1>& othe r) { return !(me==other); } friend bool operator!=(const cons<HT,TT>& me, const cons<HT1,TT1>& othe r) { return !(me==other); }
template<class HT1, class TT1> template<typename HT1, typename TT1>
friend bool operator>=(const cons<HT,TT>& me, const cons<HT1,TT1>& othe r) { return !(me<other); } friend bool operator>=(const cons<HT,TT>& me, const cons<HT1,TT1>& othe r) { return !(me<other); }
template<class HT1, class TT1> template<typename HT1, typename TT1>
friend bool operator<=(const cons<HT,TT>& me, const cons<HT1,TT1>& othe r) { return !(me>other); } friend bool operator<=(const cons<HT,TT>& me, const cons<HT1,TT1>& othe r) { return !(me>other); }
}; // cons }; // cons
template <class HT> template <typename HT>
struct cons<HT,null_type> { struct cons<HT,null_type> {
typedef HT head_type; typedef HT head_type;
typedef null_type tail_type; typedef null_type tail_type;
static const int length = 1;
head_type head; head_type head;
static const int length = 1;
// default constructor // default constructor
cons() : head() { /*std::cout << "default constructor 1\n";*/ } cons() : head() { /*std::cout << "default constructor 1\n";*/ }
cons(const null_type&, const null_type&, const null_type&, const null_t ype&, const null_type& __TBB_CONST_NULL_REF_PACK) : head() { /*std::cout << "default constructor 2\n";*/ } cons(const null_type&, const null_type&, const null_type&, const null_t ype&, const null_type& __TBB_CONST_NULL_REF_PACK) : head() { /*std::cout << "default constructor 2\n";*/ }
// non-default constructor // non-default constructor
template<class T1> template<typename T1>
cons(T1& t1, const null_type&, const null_type&, const null_type&, cons t null_type& __TBB_CONST_NULL_REF_PACK) : head(t1) { /*std::cout << "non-de fault a1, t1== " << t1 << "\n";*/} cons(T1& t1, const null_type&, const null_type&, const null_type&, cons t null_type& __TBB_CONST_NULL_REF_PACK) : head(t1) { /*std::cout << "non-de fault a1, t1== " << t1 << "\n";*/}
cons(head_type& h, const null_type& = null_type() ) : head(h) { } cons(head_type& h, const null_type& = null_type() ) : head(h) { }
cons(const head_type& t0, const null_type&, const null_type&, const nul l_type&, const null_type& __TBB_CONST_NULL_REF_PACK) : head(t0) { } cons(const head_type& t0, const null_type&, const null_type&, const nul l_type&, const null_type& __TBB_CONST_NULL_REF_PACK) : head(t0) { }
// converting constructor // converting constructor
template<class HT1> template<typename HT1>
cons(HT1 h1, const null_type&, const null_type&, const null_type&, cons t null_type& __TBB_CONST_NULL_REF_PACK) : head(h1) { } cons(HT1 h1, const null_type&, const null_type&, const null_type&, cons t null_type& __TBB_CONST_NULL_REF_PACK) : head(h1) { }
// copy constructor // copy constructor
template<class HT1> template<typename HT1>
cons( const cons<HT1, null_type>& other) : head(other.head) { } cons( const cons<HT1, null_type>& other) : head(other.head) { }
// assignment operator // assignment operator
cons& operator=(const cons& other) { head = other.head; return *this; } cons& operator=(const cons& other) { head = other.head; return *this; }
friend bool operator==(const cons& me, const cons& other) { return me.h ead == other.head; } friend bool operator==(const cons& me, const cons& other) { return me.h ead == other.head; }
friend bool operator<(const cons& me, const cons& other) { return me.he ad < other.head; } friend bool operator<(const cons& me, const cons& other) { return me.he ad < other.head; }
friend bool operator>(const cons& me, const cons& other) { return other <me; } friend bool operator>(const cons& me, const cons& other) { return other <me; }
friend bool operator!=(const cons& me, const cons& other) {return !(me= =other); } friend bool operator!=(const cons& me, const cons& other) {return !(me= =other); }
friend bool operator<=(const cons& me, const cons& other) {return !(me> other); } friend bool operator<=(const cons& me, const cons& other) {return !(me> other); }
friend bool operator>=(const cons& me, const cons& other) {return !(me< other); } friend bool operator>=(const cons& me, const cons& other) {return !(me< other); }
template<class HT1> template<typename HT1>
friend bool operator==(const cons<HT,null_type>& me, const cons<HT1,nul l_type>& other) { friend bool operator==(const cons<HT,null_type>& me, const cons<HT1,nul l_type>& other) {
return me.head == other.head; return me.head == other.head;
} }
template<class HT1> template<typename HT1>
friend bool operator<(const cons<HT,null_type>& me, const cons<HT1,null _type>& other) { friend bool operator<(const cons<HT,null_type>& me, const cons<HT1,null _type>& other) {
return me.head < other.head; return me.head < other.head;
} }
template<class HT1> template<typename HT1>
friend bool operator>(const cons<HT,null_type>& me, const cons<HT1,null _type>& other) { return other<me; } friend bool operator>(const cons<HT,null_type>& me, const cons<HT1,null _type>& other) { return other<me; }
template<class HT1> template<typename HT1>
friend bool operator!=(const cons<HT,null_type>& me, const cons<HT1,nul l_type>& other) { return !(me==other); } friend bool operator!=(const cons<HT,null_type>& me, const cons<HT1,nul l_type>& other) { return !(me==other); }
template<class HT1> template<typename HT1>
friend bool operator<=(const cons<HT,null_type>& me, const cons<HT1,nul l_type>& other) { return !(me>other); } friend bool operator<=(const cons<HT,null_type>& me, const cons<HT1,nul l_type>& other) { return !(me>other); }
template<class HT1> template<typename HT1>
friend bool operator>=(const cons<HT,null_type>& me, const cons<HT1,nul l_type>& other) { return !(me<other); } friend bool operator>=(const cons<HT,null_type>& me, const cons<HT1,nul l_type>& other) { return !(me<other); }
}; // cons }; // cons
template <> template <>
struct cons<null_type,null_type> { typedef null_type tail_type; static cons t int length = 0; }; struct cons<null_type,null_type> { typedef null_type tail_type; static cons t int length = 0; };
// wrapper for default constructor // wrapper for default constructor
template<class T> template<typename T>
inline const T wrap_dcons(T*) { return T(); } inline const T wrap_dcons(T*) { return T(); }
} // namespace internal } // namespace internal
// tuple definition // tuple definition
template<class T0, class T1, class T2, class T3, class T4 __TBB_CLASS_T_PAC K > template<typename T0, typename T1, typename T2, typename T3, typename T4 __ TBB_TYPENAME_T_PACK >
class tuple : public internal::tuple_traits<T0, T1, T2, T3, T4 __TBB_T_PACK >::U { class tuple : public internal::tuple_traits<T0, T1, T2, T3, T4 __TBB_T_PACK >::U {
// friends // friends
template <class T> friend class tuple_size; template <typename T> friend class tuple_size;
template<int N, class T> friend struct tuple_element; template<int N, typename T> friend struct tuple_element;
// stl components // stl components
typedef tuple<T0,T1,T2,T3,T4 __TBB_T_PACK > value_type; typedef tuple<T0,T1,T2,T3,T4 __TBB_T_PACK > value_type;
typedef value_type *pointer; typedef value_type *pointer;
typedef const value_type *const_pointer; typedef const value_type *const_pointer;
typedef value_type &reference; typedef value_type &reference;
typedef const value_type &const_reference; typedef const value_type &const_reference;
typedef size_t size_type; typedef size_t size_type;
typedef typename internal::tuple_traits<T0,T1,T2,T3, T4 __TBB_T_PACK >: :U my_cons; typedef typename internal::tuple_traits<T0,T1,T2,T3, T4 __TBB_T_PACK >: :U my_cons;
public:
public:
tuple(const T0& t0=internal::wrap_dcons((T0*)NULL) tuple(const T0& t0=internal::wrap_dcons((T0*)NULL)
,const T1& t1=internal::wrap_dcons((T1*)NULL) ,const T1& t1=internal::wrap_dcons((T1*)NULL)
,const T2& t2=internal::wrap_dcons((T2*)NULL) ,const T2& t2=internal::wrap_dcons((T2*)NULL)
,const T3& t3=internal::wrap_dcons((T3*)NULL) ,const T3& t3=internal::wrap_dcons((T3*)NULL)
,const T4& t4=internal::wrap_dcons((T4*)NULL) ,const T4& t4=internal::wrap_dcons((T4*)NULL)
#if __TBB_VARIADIC_MAX >= 6 #if __TBB_VARIADIC_MAX >= 6
,const T5& t5=internal::wrap_dcons((T5*)NULL) ,const T5& t5=internal::wrap_dcons((T5*)NULL)
#if __TBB_VARIADIC_MAX >= 7 #if __TBB_VARIADIC_MAX >= 7
,const T6& t6=internal::wrap_dcons((T6*)NULL) ,const T6& t6=internal::wrap_dcons((T6*)NULL)
#if __TBB_VARIADIC_MAX >= 8 #if __TBB_VARIADIC_MAX >= 8
skipping to change at line 387 skipping to change at line 392
#if __TBB_VARIADIC_MAX >= 9 #if __TBB_VARIADIC_MAX >= 9
,const T8& t8=internal::wrap_dcons((T8*)NULL) ,const T8& t8=internal::wrap_dcons((T8*)NULL)
#if __TBB_VARIADIC_MAX >= 10 #if __TBB_VARIADIC_MAX >= 10
,const T9& t9=internal::wrap_dcons((T9*)NULL) ,const T9& t9=internal::wrap_dcons((T9*)NULL)
#endif #endif
#endif #endif
#endif #endif
#endif #endif
#endif #endif
) : ) :
internal::tuple_traits<T0,T1,T2,T3,T4 __TBB_T_PACK >::U(t0,t1,t2,t3 ,t4 __TBB_T_PARAM_LIST_PACK) { } my_cons(t0,t1,t2,t3,t4 __TBB_T_PARAM_LIST_PACK) { }
template<int N> template<int N>
struct internal_tuple_element { struct internal_tuple_element {
typedef typename internal::component<N,my_cons>::type type; typedef typename internal::component<N,my_cons>::type type;
}; };
template<int N> template<int N>
typename internal_tuple_element<N>::type& get() { return internal::get_ helper<N>::get(*this); } typename internal_tuple_element<N>::type& get() { return internal::get_ helper<N>::get(*this); }
template<int N> template<int N>
typename internal_tuple_element<N>::type const& get() const { return in ternal::get_helper<N>::get(*this); } typename internal_tuple_element<N>::type const& get() const { return in ternal::get_helper<N>::get(*this); }
template<class U1, class U2> template<typename U1, typename U2>
tuple& operator=(const internal::cons<U1,U2>& other) { tuple& operator=(const internal::cons<U1,U2>& other) {
my_cons::operator=(other); my_cons::operator=(other);
return *this; return *this;
} }
template<class U1, class U2> template<typename U1, typename U2>
tuple& operator=(const std::pair<U1,U2>& other) { tuple& operator=(const std::pair<U1,U2>& other) {
// __TBB_ASSERT(tuple_size<value_type>::value == 2, "Invalid size f or pair to tuple assignment"); // __TBB_ASSERT(tuple_size<value_type>::value == 2, "Invalid size f or pair to tuple assignment");
this->head = other.first; this->head = other.first;
this->tail.head = other.second; this->tail.head = other.second;
return *this; return *this;
} }
friend bool operator==(const tuple& me, const tuple& other) {return sta tic_cast<const my_cons &>(me)==(other);} friend bool operator==(const tuple& me, const tuple& other) {return sta tic_cast<const my_cons &>(me)==(other);}
friend bool operator<(const tuple& me, const tuple& other) {return sta tic_cast<const my_cons &>(me)<(other);} friend bool operator<(const tuple& me, const tuple& other) {return sta tic_cast<const my_cons &>(me)<(other);}
friend bool operator>(const tuple& me, const tuple& other) {return sta tic_cast<const my_cons &>(me)>(other);} friend bool operator>(const tuple& me, const tuple& other) {return sta tic_cast<const my_cons &>(me)>(other);}
friend bool operator!=(const tuple& me, const tuple& other) {return sta tic_cast<const my_cons &>(me)!=(other);} friend bool operator!=(const tuple& me, const tuple& other) {return sta tic_cast<const my_cons &>(me)!=(other);}
friend bool operator>=(const tuple& me, const tuple& other) {return sta tic_cast<const my_cons &>(me)>=(other);} friend bool operator>=(const tuple& me, const tuple& other) {return sta tic_cast<const my_cons &>(me)>=(other);}
friend bool operator<=(const tuple& me, const tuple& other) {return sta tic_cast<const my_cons &>(me)<=(other);} friend bool operator<=(const tuple& me, const tuple& other) {return sta tic_cast<const my_cons &>(me)<=(other);}
template<class U0, class U1, class U2, class U3, class U4 __TBB_CLASS_U
_PACK >
friend bool operator==(const tuple& me, const tuple<U0,U1,U2,U3,U4 __TB
B_U_PACK >& other) {
return static_cast<const my_cons &>(me)==(other);
}
template<class U0, class U1, class U2, class U3, class U4 __TBB_CLASS_U
_PACK >
friend bool operator<(const tuple& me, const tuple<U0,U1,U2,U3,U4 __TBB
_U_PACK >& other) {
return static_cast<const my_cons &>(me)<(other);
}
template<class U0, class U1, class U2, class U3, class U4 __TBB_CLASS_U
_PACK >
friend bool operator>(const tuple& me, const tuple<U0,U1,U2,U3,U4 __TBB
_U_PACK >& other) {
return static_cast<const my_cons &>(me)>(other);
}
template<class U0, class U1, class U2, class U3, class U4 __TBB_CLASS_U
_PACK >
friend bool operator!=(const tuple& me, const tuple<U0,U1,U2,U3,U4 __TB
B_U_PACK >& other) {
return static_cast<const my_cons &>(me)!=(other);
}
template<class U0, class U1, class U2, class U3, class U4 __TBB_CLASS_U
_PACK >
friend bool operator>=(const tuple& me, const tuple<U0,U1,U2,U3,U4 __TB
B_U_PACK >& other) {
return static_cast<const my_cons &>(me)>=(other);
}
template<class U0, class U1, class U2, class U3, class U4 __TBB_CLASS_U
_PACK >
friend bool operator<=(const tuple& me, const tuple<U0,U1,U2,U3,U4 __TB
B_U_PACK >& other) {
return static_cast<const my_cons &>(me)<=(other);
}
}; // tuple }; // tuple
// empty tuple // empty tuple
template<> template<>
class tuple<null_type, null_type, null_type, null_type, null_type __TBB_NUL L_TYPE_PACK > : public null_type { class tuple<null_type, null_type, null_type, null_type, null_type __TBB_NUL L_TYPE_PACK > : public null_type {
typedef null_type inherited;
}; };
// helper classes // helper classes
template < class T> template < typename T>
class tuple_size { class tuple_size {
public: public:
static const size_t value = 1 + tuple_size<typename T::tail_type>::valu e; static const size_t value = 1 + tuple_size<typename T::tail_type>::valu e;
}; };
template <> template <>
class tuple_size<tuple<> > { class tuple_size<tuple<> > {
public: public:
static const size_t value = 0; static const size_t value = 0;
}; };
template <> template <>
class tuple_size<null_type> { class tuple_size<null_type> {
public: public:
static const size_t value = 0; static const size_t value = 0;
}; };
template<int N, class T> template<int N, typename T>
struct tuple_element { struct tuple_element {
typedef typename internal::component<N, typename T::my_cons>::type type ; typedef typename internal::component<N, typename T::my_cons>::type type ;
}; };
template<int N, class T0, class T1, class T2, class T3, class T4 __TBB_CLAS S_T_PACK > template<int N, typename T0, typename T1, typename T2, typename T3, typenam e T4 __TBB_TYPENAME_T_PACK >
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 internal::get_help er<N>::get(t); }
template<int N, class T0, class T1, class T2, class T3, class T4 __TBB_CLAS S_T_PACK > template<int N, typename T0, typename T1, typename T2, typename T3, typenam e T4 __TBB_TYPENAME_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 internal::ge t_helper<N>::get(t); }
} // interface5 } // interface5
} // tbb } // tbb
#if !__TBB_CPP11_TUPLE_PRESENT #if !__TBB_CPP11_TUPLE_PRESENT
namespace std { namespace tbb {
using tbb::interface5::tuple; namespace flow {
using tbb::interface5::tuple_size; using tbb::interface5::tuple;
using tbb::interface5::tuple_element; using tbb::interface5::tuple_size;
using tbb::interface5::get; using tbb::interface5::tuple_element;
using tbb::interface5::get;
}
} }
#endif #endif
#undef __TBB_T_PACK #undef __TBB_T_PACK
#undef __TBB_U_PACK #undef __TBB_U_PACK
#undef __TBB_CLASS_T_PACK #undef __TBB_TYPENAME_T_PACK
#undef __TBB_CLASS_U_PACK #undef __TBB_TYPENAME_U_PACK
#undef __TBB_NULL_TYPE_PACK #undef __TBB_NULL_TYPE_PACK
#undef __TBB_REF_T_PARAM_PACK #undef __TBB_REF_T_PARAM_PACK
#undef __TBB_CONST_REF_T_PARAM_PACK #undef __TBB_CONST_REF_T_PARAM_PACK
#undef __TBB_T_PARAM_LIST_PACK #undef __TBB_T_PARAM_LIST_PACK
#undef __TBB_CONST_NULL_REF_PACK #undef __TBB_CONST_NULL_REF_PACK
#endif /* __TBB_tuple_H */ #endif /* __TBB_tuple_H */
 End of changes. 66 change blocks. 
121 lines changed or deleted 87 lines changed or added


 windows_api.h   windows_api.h 
skipping to change at line 46 skipping to change at line 46
#define NONET #define NONET
#define NOD3D #define NOD3D
#include <xtl.h> #include <xtl.h>
#else // Assume "usual" Windows #else // Assume "usual" Windows
#include <windows.h> #include <windows.h>
#endif // _XBOX #endif // _XBOX
#if !defined(_WIN32_WINNT) #if _WIN32_WINNT < 0x0600
// The following Windows API function is declared explicitly; // The following Windows API function is declared explicitly;
// otherwise any user would have to specify /D_WIN32_WINNT=0x0400 // otherwise it fails to compile by VS2005.
extern "C" BOOL WINAPI TryEnterCriticalSection( LPCRITICAL_SECTION ); #if !defined(WINBASEAPI) || (_WIN32_WINNT < 0x0501 && _MSC_VER == 1400)
#define __TBB_WINBASEAPI extern "C"
#else
#define __TBB_WINBASEAPI WINBASEAPI
#endif
__TBB_WINBASEAPI BOOL WINAPI TryEnterCriticalSection( LPCRITICAL_SECTION );
__TBB_WINBASEAPI BOOL WINAPI InitializeCriticalSectionAndSpinCount( LPCRITI
CAL_SECTION, DWORD );
// Overloading WINBASEAPI macro and using local functions missing in Window
s XP/2003
#define InitializeCriticalSectionEx inlineInitializeCriticalSectionEx
#define CreateSemaphoreEx inlineCreateSemaphoreEx
#define CreateEventEx inlineCreateEventEx
inline BOOL WINAPI inlineInitializeCriticalSectionEx( LPCRITICAL_SECTION lp
CriticalSection, DWORD dwSpinCount, DWORD )
{
return InitializeCriticalSectionAndSpinCount( lpCriticalSection, dwSpin
Count );
}
inline HANDLE WINAPI inlineCreateSemaphoreEx( LPSECURITY_ATTRIBUTES lpSemap
horeAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName, DWO
RD, DWORD )
{
return CreateSemaphore( lpSemaphoreAttributes, lInitialCount, lMaximumC
ount, lpName );
}
inline HANDLE WINAPI inlineCreateEventEx( LPSECURITY_ATTRIBUTES lpEventAttr
ibutes, LPCTSTR lpName, DWORD dwFlags, DWORD )
{
BOOL manual_reset = dwFlags&0x00000001 ? TRUE : FALSE; // CREATE_EVENT_
MANUAL_RESET
BOOL initial_set = dwFlags&0x00000002 ? TRUE : FALSE; // CREATE_EVENT_
INITIAL_SET
return CreateEvent( lpEventAttributes, manual_reset, initial_set, lpNam
e );
}
#endif
#if defined(RTL_SRWLOCK_INIT)
#ifndef __TBB_USE_SRWLOCK
// TODO: turn it on when bug 1952 will be fixed
#define __TBB_USE_SRWLOCK 0
#endif
#endif #endif
#else #else
#error tbb/machine/windows_api.h should only be used for Windows based plat forms #error tbb/machine/windows_api.h should only be used for Windows based plat forms
#endif // _WIN32 || _WIN64 #endif // _WIN32 || _WIN64
#endif // __TBB_machine_windows_api_H #endif // __TBB_machine_windows_api_H
 End of changes. 2 change blocks. 
3 lines changed or deleted 45 lines changed or added


 windows_ia32.h   windows_ia32.h 
skipping to change at line 35 skipping to change at line 35
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.
*/ */
#if !defined(__TBB_machine_H) || defined(__TBB_machine_windows_ia32_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_windows_ia32_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_windows_ia32_H #define __TBB_machine_windows_ia32_H
#include "msvc_ia32_common.h"
#define __TBB_WORDSIZE 4 #define __TBB_WORDSIZE 4
#define __TBB_BIG_ENDIAN 0 #define __TBB_BIG_ENDIAN 0
#if __INTEL_COMPILER #if __INTEL_COMPILER && (__INTEL_COMPILER < 1100)
#define __TBB_compiler_fence() __asm { __asm nop } #define __TBB_compiler_fence() __asm { __asm nop }
#elif _MSC_VER >= 1300 #define __TBB_full_memory_fence() __asm { __asm mfence }
extern "C" void _ReadWriteBarrier(); #elif _MSC_VER >= 1300 || __INTEL_COMPILER
#pragma intrinsic(_ReadWriteBarrier) #pragma intrinsic(_ReadWriteBarrier)
#define __TBB_compiler_fence() _ReadWriteBarrier() #pragma intrinsic(_mm_mfence)
#define __TBB_compiler_fence() _ReadWriteBarrier()
#define __TBB_full_memory_fence() _mm_mfence()
#else #else
#error Unsupported compiler - need to define __TBB_{control,acquire,rel ease}_consistency_helper to support it #error Unsupported compiler - need to define __TBB_{control,acquire,rel ease}_consistency_helper to support it
#endif #endif
#define __TBB_control_consistency_helper() __TBB_compiler_fence() #define __TBB_control_consistency_helper() __TBB_compiler_fence()
#define __TBB_acquire_consistency_helper() __TBB_compiler_fence() #define __TBB_acquire_consistency_helper() __TBB_compiler_fence()
#define __TBB_release_consistency_helper() __TBB_compiler_fence() #define __TBB_release_consistency_helper() __TBB_compiler_fence()
#define __TBB_full_memory_fence() __asm { __asm mfence }
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
// Workaround for overzealous compiler warnings in /Wp64 mode // Workaround for overzealous compiler warnings in /Wp64 mode
#pragma warning (push) #pragma warning (push)
#pragma warning (disable: 4244 4267) #pragma warning (disable: 4244 4267)
#endif #endif
extern "C" { extern "C" {
__int64 __TBB_EXPORTED_FUNC __TBB_machine_cmpswp8 (volatile void *ptr, __int64 value, __int64 comparand ); __int64 __TBB_EXPORTED_FUNC __TBB_machine_cmpswp8 (volatile void *ptr, __int64 value, __int64 comparand );
__int64 __TBB_EXPORTED_FUNC __TBB_machine_fetchadd8 (volatile void *ptr , __int64 addend ); __int64 __TBB_EXPORTED_FUNC __TBB_machine_fetchadd8 (volatile void *ptr , __int64 addend );
__int64 __TBB_EXPORTED_FUNC __TBB_machine_fetchstore8 (volatile void *p tr, __int64 value ); __int64 __TBB_EXPORTED_FUNC __TBB_machine_fetchstore8 (volatile void *p tr, __int64 value );
void __TBB_EXPORTED_FUNC __TBB_machine_store8 (volatile void *ptr, __in t64 value ); void __TBB_EXPORTED_FUNC __TBB_machine_store8 (volatile void *ptr, __in t64 value );
__int64 __TBB_EXPORTED_FUNC __TBB_machine_load8 (const volatile void *p tr); __int64 __TBB_EXPORTED_FUNC __TBB_machine_load8 (const volatile void *p tr);
} }
//TODO: use _InterlockedXXX intrinsics as they available since VC 2005
#define __TBB_MACHINE_DEFINE_ATOMICS(S,T,U,A,C) \ #define __TBB_MACHINE_DEFINE_ATOMICS(S,T,U,A,C) \
static inline T __TBB_machine_cmpswp##S ( volatile void * ptr, U value, U c omparand ) { \ static inline T __TBB_machine_cmpswp##S ( volatile void * ptr, U value, U c omparand ) { \
T result; \ T result; \
volatile T *p = (T *)ptr; \ volatile T *p = (T *)ptr; \
__asm \ __asm \
{ \ { \
__asm mov edx, p \ __asm mov edx, p \
__asm mov C , value \ __asm mov C , value \
__asm mov A , comparand \ __asm mov A , comparand \
__asm lock cmpxchg [edx], C \ __asm lock cmpxchg [edx], C \
skipping to change at line 114 skipping to change at line 118
} \ } \
return result; \ return result; \
} }
__TBB_MACHINE_DEFINE_ATOMICS(1, __int8, __int8, al, cl) __TBB_MACHINE_DEFINE_ATOMICS(1, __int8, __int8, al, cl)
__TBB_MACHINE_DEFINE_ATOMICS(2, __int16, __int16, ax, cx) __TBB_MACHINE_DEFINE_ATOMICS(2, __int16, __int16, ax, cx)
__TBB_MACHINE_DEFINE_ATOMICS(4, ptrdiff_t, ptrdiff_t, eax, ecx) __TBB_MACHINE_DEFINE_ATOMICS(4, ptrdiff_t, ptrdiff_t, eax, ecx)
#undef __TBB_MACHINE_DEFINE_ATOMICS #undef __TBB_MACHINE_DEFINE_ATOMICS
#if ( _MSC_VER>=1400 && !defined(__INTEL_COMPILER) ) || (__INTEL_COMPILER>
=1200)
// MSVC did not have this intrinsic prior to VC8.
// ICL 11.1 fails to compile a TBB example if __TBB_Log2 uses the intrinsic
.
#define __TBB_LOG2_USE_BSR_INTRINSIC 1
extern "C" unsigned char _BitScanReverse( unsigned long* i, unsigned long w
);
#pragma intrinsic(_BitScanReverse)
#endif
static inline intptr_t __TBB_machine_lg( uintptr_t i ) {
unsigned long j;
#if __TBB_LOG2_USE_BSR_INTRINSIC
_BitScanReverse( &j, i );
#else
__asm
{
bsr eax, i
mov j, eax
}
#endif
return j;
}
static inline void __TBB_machine_OR( volatile void *operand, __int32 addend ) { static inline void __TBB_machine_OR( volatile void *operand, __int32 addend ) {
__asm __asm
{ {
mov eax, addend mov eax, addend
mov edx, [operand] mov edx, [operand]
lock or [edx], eax lock or [edx], eax
} }
} }
static inline void __TBB_machine_AND( volatile void *operand, __int32 adden d ) { static inline void __TBB_machine_AND( volatile void *operand, __int32 adden d ) {
__asm __asm
{ {
mov eax, addend mov eax, addend
mov edx, [operand] mov edx, [operand]
lock and [edx], eax lock and [edx], eax
} }
} }
static inline void __TBB_machine_pause (__int32 delay ) {
_asm
{
mov eax, delay
__TBB_L1:
pause
add eax, -1
jne __TBB_L1
}
return;
}
#define __TBB_AtomicOR(P,V) __TBB_machine_OR(P,V) #define __TBB_AtomicOR(P,V) __TBB_machine_OR(P,V)
#define __TBB_AtomicAND(P,V) __TBB_machine_AND(P,V) #define __TBB_AtomicAND(P,V) __TBB_machine_AND(P,V)
//TODO: Check if it possible and profitable for IA-32 on (Linux and Windows ) //TODO: Check if it possible and profitable for IA-32 on (Linux and Windows )
//to use of 64-bit load/store via floating point registers together with fu ll fence //to use of 64-bit load/store via floating point registers together with fu ll fence
//for sequentially consistent load/store, instead of CAS. //for sequentially consistent load/store, instead of CAS.
#define __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE 1 #define __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE 1
#define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 #define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1
#define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1 #define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1
#define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 #define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1
// Definition of other functions
extern "C" __declspec(dllimport) int __stdcall SwitchToThread( void );
#define __TBB_Yield() SwitchToThread()
#define __TBB_Pause(V) __TBB_machine_pause(V)
#define __TBB_Log2(V) __TBB_machine_lg(V)
#if defined(_MSC_VER)&&_MSC_VER<1400
static inline void* __TBB_machine_get_current_teb () {
void* pteb;
__asm mov eax, fs:[0x18]
__asm mov pteb, eax
return pteb;
}
#endif
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
#pragma warning (pop) #pragma warning (pop)
#endif // warnings 4244, 4267 are back #endif // warnings 4244, 4267 are back
// API to retrieve/update FPU control setting
#define __TBB_CPU_CTL_ENV_PRESENT 1
struct __TBB_cpu_ctl_env_t {
int mxcsr;
short x87cw;
};
inline void __TBB_get_cpu_ctl_env ( __TBB_cpu_ctl_env_t* ctl ) {
__asm {
__asm mov eax, ctl
__asm stmxcsr [eax]
__asm fstcw [eax+4]
}
}
inline void __TBB_set_cpu_ctl_env ( const __TBB_cpu_ctl_env_t* ctl ) {
__asm {
__asm mov eax, ctl
__asm ldmxcsr [eax]
__asm fldcw [eax+4]
}
}
 End of changes. 9 change blocks. 
58 lines changed or deleted 10 lines changed or added


 windows_intel64.h   windows_intel64.h 
skipping to change at line 39 skipping to change at line 39
#if !defined(__TBB_machine_H) || defined(__TBB_machine_windows_intel64_H) #if !defined(__TBB_machine_H) || defined(__TBB_machine_windows_intel64_H)
#error Do not #include this internal file directly; use public TBB headers instead. #error Do not #include this internal file directly; use public TBB headers instead.
#endif #endif
#define __TBB_machine_windows_intel64_H #define __TBB_machine_windows_intel64_H
#define __TBB_WORDSIZE 8 #define __TBB_WORDSIZE 8
#define __TBB_BIG_ENDIAN 0 #define __TBB_BIG_ENDIAN 0
#include <intrin.h> #include <intrin.h>
#include "msvc_ia32_common.h"
//TODO: Use _InterlockedXXX16 intrinsics for 2 byte operations
#if !__INTEL_COMPILER #if !__INTEL_COMPILER
#pragma intrinsic(_InterlockedOr64) #pragma intrinsic(_InterlockedOr64)
#pragma intrinsic(_InterlockedAnd64) #pragma intrinsic(_InterlockedAnd64)
#pragma intrinsic(_InterlockedCompareExchange) #pragma intrinsic(_InterlockedCompareExchange)
#pragma intrinsic(_InterlockedCompareExchange64) #pragma intrinsic(_InterlockedCompareExchange64)
#pragma intrinsic(_InterlockedExchangeAdd) #pragma intrinsic(_InterlockedExchangeAdd)
#pragma intrinsic(_InterlockedExchangeAdd64) #pragma intrinsic(_InterlockedExchangeAdd64)
#pragma intrinsic(_InterlockedExchange) #pragma intrinsic(_InterlockedExchange)
#pragma intrinsic(_InterlockedExchange64) #pragma intrinsic(_InterlockedExchange64)
#endif /* !defined(__INTEL_COMPILER) */ #endif /* !(__INTEL_COMPILER) */
#if __INTEL_COMPILER #if __INTEL_COMPILER && (__INTEL_COMPILER < 1100)
#define __TBB_compiler_fence() __asm { __asm nop } #define __TBB_compiler_fence() __asm { __asm nop }
#define __TBB_full_memory_fence() __asm { __asm mfence } #define __TBB_full_memory_fence() __asm { __asm mfence }
#elif _MSC_VER >= 1300 #elif _MSC_VER >= 1300 || __INTEL_COMPILER
extern "C" void _ReadWriteBarrier();
#pragma intrinsic(_ReadWriteBarrier) #pragma intrinsic(_ReadWriteBarrier)
#pragma intrinsic(_mm_mfence) #pragma intrinsic(_mm_mfence)
#pragma intrinsic(_mm_pause)
#define __TBB_compiler_fence() _ReadWriteBarrier() #define __TBB_compiler_fence() _ReadWriteBarrier()
#define __TBB_full_memory_fence() _mm_mfence() #define __TBB_full_memory_fence() _mm_mfence()
#endif #endif
#define __TBB_control_consistency_helper() __TBB_compiler_fence() #define __TBB_control_consistency_helper() __TBB_compiler_fence()
#define __TBB_acquire_consistency_helper() __TBB_compiler_fence() #define __TBB_acquire_consistency_helper() __TBB_compiler_fence()
#define __TBB_release_consistency_helper() __TBB_compiler_fence() #define __TBB_release_consistency_helper() __TBB_compiler_fence()
// ATTENTION: if you ever change argument types in machine-specific primiti ves, // ATTENTION: if you ever change argument types in machine-specific primiti ves,
// please take care of atomic_word<> specializations in tbb/atomic.h // please take care of atomic_word<> specializations in tbb/atomic.h
skipping to change at line 98 skipping to change at line 98
inline __int64 __TBB_machine_cmpswp8 (volatile void *ptr, __int64 value, __ int64 comparand ) { inline __int64 __TBB_machine_cmpswp8 (volatile void *ptr, __int64 value, __ int64 comparand ) {
return _InterlockedCompareExchange64( (__int64*)ptr, value, comparand ) ; return _InterlockedCompareExchange64( (__int64*)ptr, value, comparand ) ;
} }
inline __int64 __TBB_machine_fetchadd8 (volatile void *ptr, __int64 addend ) { inline __int64 __TBB_machine_fetchadd8 (volatile void *ptr, __int64 addend ) {
return _InterlockedExchangeAdd64( (__int64*)ptr, addend ); return _InterlockedExchangeAdd64( (__int64*)ptr, addend );
} }
inline __int64 __TBB_machine_fetchstore8 (volatile void *ptr, __int64 value ) { inline __int64 __TBB_machine_fetchstore8 (volatile void *ptr, __int64 value ) {
return _InterlockedExchange64( (__int64*)ptr, value ); return _InterlockedExchange64( (__int64*)ptr, value );
} }
inline void __TBB_machine_pause_v6 (__int32 delay ) {
for (;delay>0; --delay )
_mm_pause();
}
#define __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE 1 #define __TBB_USE_FETCHSTORE_AS_FULL_FENCED_STORE 1
#define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1 #define __TBB_USE_GENERIC_HALF_FENCED_LOAD_STORE 1
#define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1 #define __TBB_USE_GENERIC_RELAXED_LOAD_STORE 1
#define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1 #define __TBB_USE_GENERIC_SEQUENTIAL_CONSISTENCY_LOAD_STORE 1
extern "C" unsigned char _BitScanReverse64( unsigned long* i, unsigned __in
t64 w );
#pragma intrinsic(_BitScanReverse64)
inline __int64 __TBB_machine_lg( unsigned __int64 i ) {
unsigned long j;
_BitScanReverse64( &j, i );
return j;
}
inline void __TBB_machine_OR( volatile void *operand, intptr_t addend ) { inline void __TBB_machine_OR( volatile void *operand, intptr_t addend ) {
_InterlockedOr64((__int64*)operand, addend); _InterlockedOr64((__int64*)operand, addend);
} }
inline void __TBB_machine_AND( volatile void *operand, intptr_t addend ) { inline void __TBB_machine_AND( volatile void *operand, intptr_t addend ) {
_InterlockedAnd64((__int64*)operand, addend); _InterlockedAnd64((__int64*)operand, addend);
} }
#define __TBB_AtomicOR(P,V) __TBB_machine_OR(P,V) #define __TBB_AtomicOR(P,V) __TBB_machine_OR(P,V)
#define __TBB_AtomicAND(P,V) __TBB_machine_AND(P,V) #define __TBB_AtomicAND(P,V) __TBB_machine_AND(P,V)
extern "C" __declspec(dllimport) int __stdcall SwitchToThread( void );
#define __TBB_Yield() SwitchToThread()
#define __TBB_Pause(V) __TBB_machine_pause_v6(V)
#define __TBB_Log2(V) __TBB_machine_lg(V)
// API to retrieve/update FPU control setting
#define __TBB_CPU_CTL_ENV_PRESENT 1
struct __TBB_cpu_ctl_env_t {
int mxcsr;
short x87cw;
};
extern "C" {
void __TBB_EXPORTED_FUNC __TBB_get_cpu_ctl_env ( __TBB_cpu_ctl_env_t* )
;
void __TBB_EXPORTED_FUNC __TBB_set_cpu_ctl_env ( const __TBB_cpu_ctl_en
v_t* );
}
 End of changes. 9 change blocks. 
20 lines changed or deleted 5 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/