_flow_graph_node_impl.h   _flow_graph_node_impl.h 
skipping to change at line 376 skipping to change at line 376
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();
} }
task * apply_body_impl_bypass( const input_type &i) { task * apply_body_impl_bypass( const input_type &i) {
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
// There is an extra copied needed to capture the
// body execution without the try_put
tbb::internal::fgt_begin_body( my_body );
output_type v = (*my_body)(i);
tbb::internal::fgt_end_body( my_body );
task * new_task = successors().try_put_task( v );
#else
task * new_task = successors().try_put_task( (*my_body)(i) ); task * new_task = successors().try_put_task( (*my_body)(i) );
#endif
return new_task; 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;
skipping to change at line 432 skipping to change at line 441
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();
} }
// for multifunction nodes we do not have a single successor as suc h. So we just tell // for multifunction nodes we do not have a single successor as suc h. So we just tell
// the task we were successful. // the task we were successful.
task * apply_body_impl_bypass( const input_type &i) { task * apply_body_impl_bypass( const input_type &i) {
tbb::internal::fgt_begin_body( my_body );
(*my_body)(i, my_output_ports); (*my_body)(i, my_output_ports);
tbb::internal::fgt_end_body( my_body );
task * new_task = SUCCESSFULLY_ENQUEUED; task * new_task = SUCCESSFULLY_ENQUEUED;
return new_task; 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();
skipping to change at line 519 skipping to change at line 530
graph* my_graph_ptr; graph* my_graph_ptr;
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_bypass< continue_input< Output >, cont inue_msg >; 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 */ task *apply_body_bypass( input_type ) { /* override */ task *apply_body_bypass( input_type ) {
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
// There is an extra copied needed to capture the
// body execution without the try_put
tbb::internal::fgt_begin_body( my_body );
output_type v = (*my_body)( continue_msg() );
tbb::internal::fgt_end_body( my_body );
return successors().try_put_task( v );
#else
return successors().try_put_task( (*my_body)( continue_msg() ) ); return successors().try_put_task( (*my_body)( continue_msg() ) );
#endif
} }
//! Spawns a task that applies the body //! Spawns a task that applies the body
/* override */ task *execute( ) { /* override */ task *execute( ) {
task* tp = my_graph_ptr->root_task(); task* tp = my_graph_ptr->root_task();
return (tp) ? return (tp) ?
new ( task::allocate_additional_child_of( *tp ) ) new ( task::allocate_additional_child_of( *tp ) )
apply_body_task_bypass< continue_input< Output >, conti nue_msg >( *this, continue_msg() ) : apply_body_task_bypass< continue_input< Output >, conti nue_msg >( *this, continue_msg() ) :
NULL; NULL;
} }
 End of changes. 6 change blocks. 
0 lines changed or deleted 20 lines changed or added


 _mutex_padding.h   _mutex_padding.h 
skipping to change at line 43 skipping to change at line 43
// from a pool. Because we allow them to be defined anywhere they must be two cache lines in size. // from a pool. Because we allow them to be defined anywhere they must be two cache lines in size.
namespace tbb { namespace tbb {
namespace interface7 { namespace interface7 {
namespace internal { namespace internal {
static const size_t cache_line_size = 64; static const size_t cache_line_size = 64;
// Pad a mutex to occupy a number of full cache lines sufficient to avoid f alse sharing // Pad a mutex to occupy a number of full cache lines sufficient to avoid f alse sharing
// with other data; space overhead is up to 2*cache_line_size-1. // with other data; space overhead is up to 2*cache_line_size-1.
template<typename Mutex, bool is_rw> class padded_mutex;
template<typename Mutex> template<typename Mutex>
class padded_mutex { class padded_mutex<Mutex,false> {
typedef long pad_type; typedef long pad_type;
pad_type my_pad[((sizeof(Mutex)+cache_line_size-1)/cache_line_size+1)*c ache_line_size/sizeof(pad_type)]; pad_type my_pad[((sizeof(Mutex)+cache_line_size-1)/cache_line_size+1)*c ache_line_size/sizeof(pad_type)];
Mutex *impl() { return (Mutex *)((uintptr_t(this)|(cache_line_size-1))+ 1);} Mutex *impl() { return (Mutex *)((uintptr_t(this)|(cache_line_size-1))+ 1);}
public: public:
static const bool is_rw_mutex = Mutex::is_rw_mutex; static const bool is_rw_mutex = Mutex::is_rw_mutex;
static const bool is_recursive_mutex = Mutex::is_recursive_mutex; static const bool is_recursive_mutex = Mutex::is_recursive_mutex;
static const bool is_fair_mutex = Mutex::is_fair_mutex; static const bool is_fair_mutex = Mutex::is_fair_mutex;
skipping to change at line 72 skipping to change at line 74
scoped_lock() : my_scoped_lock() {} scoped_lock() : my_scoped_lock() {}
scoped_lock( padded_mutex& m ) : my_scoped_lock(*m.impl()) { } scoped_lock( padded_mutex& m ) : my_scoped_lock(*m.impl()) { }
~scoped_lock() { } ~scoped_lock() { }
void acquire( padded_mutex& m ) { my_scoped_lock.acquire(*m.impl()) ; } void acquire( padded_mutex& m ) { my_scoped_lock.acquire(*m.impl()) ; }
bool try_acquire( padded_mutex& m ) { return my_scoped_lock.try_acq uire(*m.impl()); } bool try_acquire( padded_mutex& m ) { return my_scoped_lock.try_acq uire(*m.impl()); }
void release() { my_scoped_lock.release(); } void release() { my_scoped_lock.release(); }
}; };
}; };
template<typename Mutex>
class padded_mutex<Mutex,true> {
typedef long pad_type;
pad_type my_pad[((sizeof(Mutex)+cache_line_size-1)/cache_line_size+1)*c
ache_line_size/sizeof(pad_type)];
Mutex *impl() { return (Mutex *)((uintptr_t(this)|(cache_line_size-1))+
1);}
public:
static const bool is_rw_mutex = Mutex::is_rw_mutex;
static const bool is_recursive_mutex = Mutex::is_recursive_mutex;
static const bool is_fair_mutex = Mutex::is_fair_mutex;
padded_mutex() { new(impl()) Mutex(); }
~padded_mutex() { impl()->~Mutex(); }
//! Represents acquisition of a mutex.
class scoped_lock : tbb::internal::no_copy {
typename Mutex::scoped_lock my_scoped_lock;
public:
scoped_lock() : my_scoped_lock() {}
scoped_lock( padded_mutex& m, bool write = true ) : my_scoped_lock(
*m.impl(),write) { }
~scoped_lock() { }
void acquire( padded_mutex& m, bool write = true ) { my_scoped_lock
.acquire(*m.impl(),write); }
bool try_acquire( padded_mutex& m, bool write = true ) { return my_
scoped_lock.try_acquire(*m.impl(),write); }
bool upgrade_to_writer() { return my_scoped_lock.upgrade_to_writer(
); }
bool downgrade_to_reader() { return my_scoped_lock.downgrade_to_rea
der(); }
void release() { my_scoped_lock.release(); }
};
};
} // namespace internal } // namespace internal
} // namespace interface7 } // namespace interface7
} // namespace tbb } // namespace tbb
#endif /* __TBB_mutex_padding_H */ #endif /* __TBB_mutex_padding_H */
 End of changes. 3 change blocks. 
1 lines changed or deleted 41 lines changed or added


 _x86_eliding_mutex_impl.h   _x86_eliding_mutex_impl.h 
skipping to change at line 42 skipping to change at line 42
#ifndef __TBB_spin_mutex_H #ifndef __TBB_spin_mutex_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_x86_32 || __TBB_x86_64 ) #if ( __TBB_x86_32 || __TBB_x86_64 )
namespace tbb { namespace tbb {
namespace interface7 { namespace interface7 {
namespace internal { namespace internal {
template<typename Mutex> template<typename Mutex, bool is_rw>
class padded_mutex; class padded_mutex;
//! An eliding lock that occupies a single byte. //! An eliding lock that occupies a single byte.
/** A x86_eliding_mutex is an HLE-enabled spin mutex. It is recommended to /** A x86_eliding_mutex is an HLE-enabled spin mutex. It is recommended to
put the mutex on a cache line that is not shared by the data it protect s. put the mutex on a cache line that is not shared by the data it protect s.
It should be used for locking short critical sections where the lock is It should be used for locking short critical sections where the lock is
contended but the data it protects are not. If zero-initialized, the contended but the data it protects are not. If zero-initialized, the
mutex is considered unheld. mutex is considered unheld.
@ingroup synchronization */ @ingroup synchronization */
class x86_eliding_mutex { class x86_eliding_mutex {
//! 0 if lock is released, 1 if lock is acquired. //! 0 if lock is released, 1 if lock is acquired.
__TBB_atomic_flag flag; __TBB_atomic_flag flag;
friend class padded_mutex<x86_eliding_mutex>; friend class padded_mutex<x86_eliding_mutex, false>;
public: public:
//! Construct unacquired lock. //! Construct unacquired lock.
/** Equivalent to zero-initialization of *this. */ /** Equivalent to zero-initialization of *this. */
x86_eliding_mutex() : flag(0) {} x86_eliding_mutex() : flag(0) {}
// bug in gcc 3.x.x causes syntax error in spite of the friend declaration above. // bug in gcc 3.x.x causes syntax error in spite of the friend declaration above.
// Make the scoped_lock public in that case. // Make the scoped_lock public in that case.
#if __TBB_USE_X86_ELIDING_MUTEX || __TBB_GCC_VERSION < 40000 #if __TBB_USE_X86_ELIDING_MUTEX || __TBB_GCC_VERSION < 40000
#else #else
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 cache_aligned_allocator.h   cache_aligned_allocator.h 
skipping to change at line 105 skipping to change at line 105
void deallocate( pointer p, size_type ) { void deallocate( pointer p, size_type ) {
internal::NFS_Free(p); internal::NFS_Free(p);
} }
//! Largest value for which method allocate might succeed. //! Largest value for which method allocate might succeed.
size_type max_size() const throw() { size_type max_size() const throw() {
return (~size_t(0)-internal::NFS_MaxLineSize)/sizeof(value_type); return (~size_t(0)-internal::NFS_MaxLineSize)/sizeof(value_type);
} }
//! Copy-construct value at location pointed to by p. //! Copy-construct value at location pointed to by p.
#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESEN T #if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
template<typename U, typename... Args> template<typename U, typename... Args>
void construct(U *p, Args&&... args) void construct(U *p, Args&&... args)
#if __TBB_CPP11_STD_FORWARD_BROKEN #if __TBB_CPP11_STD_FORWARD_BROKEN
{ ::new((void *)p) U((args)...); } { ::new((void *)p) U((args)...); }
#else #else
{ ::new((void *)p) U(std::forward<Args>(args)...); } { ::new((void *)p) U(std::forward<Args>(args)...); }
#endif #endif
#else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_P RESENT #else // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);} void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);}
#endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_ PRESENT #endif // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
//! Destroy value at location pointed to by p. //! Destroy value at location pointed to by p.
void destroy( pointer p ) {p->~value_type();} void destroy( pointer p ) {p->~value_type();}
}; };
#if _MSC_VER && !defined(__INTEL_COMPILER) #if _MSC_VER && !defined(__INTEL_COMPILER)
#pragma warning (pop) #pragma warning (pop)
#endif // warning 4100 is back #endif // warning 4100 is back
//! Analogous to std::allocator<void>, as defined in ISO C++ Standard, Sect ion 20.4.1 //! Analogous to std::allocator<void>, as defined in ISO C++ Standard, Sect ion 20.4.1
 End of changes. 3 change blocks. 
3 lines changed or deleted 3 lines changed or added


 flow_graph.h   flow_graph.h 
skipping to change at line 41 skipping to change at line 41
#include "tbb_stddef.h" #include "tbb_stddef.h"
#include "atomic.h" #include "atomic.h"
#include "spin_mutex.h" #include "spin_mutex.h"
#include "null_mutex.h" #include "null_mutex.h"
#include "spin_rw_mutex.h" #include "spin_rw_mutex.h"
#include "null_rw_mutex.h" #include "null_rw_mutex.h"
#include "task.h" #include "task.h"
#include "concurrent_vector.h" #include "concurrent_vector.h"
#include "internal/_aggregator_impl.h" #include "internal/_aggregator_impl.h"
#include "tbb_profiling.h"
#if TBB_DEPRECATED_FLOW_ENQUEUE #if TBB_DEPRECATED_FLOW_ENQUEUE
#define FLOW_SPAWN(a) tbb::task::enqueue((a)) #define FLOW_SPAWN(a) tbb::task::enqueue((a))
#else #else
#define FLOW_SPAWN(a) tbb::task::spawn((a)) #define FLOW_SPAWN(a) tbb::task::spawn((a))
#endif #endif
// 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>
skipping to change at line 274 skipping to change at line 275
} }
//! 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 task * 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; }
}; };
} // interface7
} // flow
} // tbb
#include "internal/_flow_graph_trace_impl.h"
namespace tbb {
namespace flow {
namespace interface7 {
#include "internal/_flow_graph_impl.h" #include "internal/_flow_graph_impl.h"
using namespace internal::graph_policy_namespace; using namespace internal::graph_policy_namespace;
class graph; class graph;
class graph_node; class graph_node;
template <typename GraphContainerType, typename GraphNodeType> template <typename GraphContainerType, typename GraphNodeType>
class graph_iterator { class graph_iterator {
friend class graph; friend class graph;
skipping to change at line 389 skipping to change at line 399
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)
{ {
own_context = true; own_context = true;
cancelled = false; cancelled = false;
caught_exception = false; caught_exception = false;
my_context = new task_group_context(); my_context = new task_group_context();
my_root_task = ( new ( task::allocate_root(*my_context) ) empty_tas k ); my_root_task = ( new ( task::allocate_root(*my_context) ) empty_tas k );
my_root_task->set_ref_count(1); my_root_task->set_ref_count(1);
tbb::internal::fgt_graph( this );
} }
//! Constructs a graph with use_this_context as context //! Constructs a graph with use_this_context as context
explicit graph(task_group_context& use_this_context) : explicit graph(task_group_context& use_this_context) :
my_context(&use_this_context), my_nodes(NULL), my_nodes_last(NULL) my_context(&use_this_context), my_nodes(NULL), my_nodes_last(NULL)
{ {
own_context = false; own_context = false;
my_root_task = ( new ( task::allocate_root(*my_context) ) empty_tas k ); my_root_task = ( new ( task::allocate_root(*my_context) ) empty_tas k );
my_root_task->set_ref_count(1); my_root_task->set_ref_count(1);
tbb::internal::fgt_graph( this );
} }
//! Destroys the graph. //! Destroys the graph.
/** Calls wait_for_all, then destroys the root task and context. */ /** Calls wait_for_all, then destroys the root task and context. */
~graph() { ~graph() {
wait_for_all(); wait_for_all();
my_root_task->set_ref_count(0); my_root_task->set_ref_count(0);
task::destroy( *my_root_task ); task::destroy( *my_root_task );
if (own_context) delete my_context; if (own_context) delete my_context;
} }
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
void set_name( const char *name ) {
tbb::internal::fgt_graph_desc( this, name );
}
#endif
//! Used to register that an external entity may still interact with th e graph. //! Used to register that an external entity may still interact with th e graph.
/** The graph will not return from wait_for_all until a matching number of decrement_wait_count calls /** The graph will not return from wait_for_all until a matching number of decrement_wait_count calls
is made. */ is made. */
void increment_wait_count() { void increment_wait_count() {
if (my_root_task) if (my_root_task)
my_root_task->increment_ref_count(); my_root_task->increment_ref_count();
} }
//! Deregisters an external entity that may have interacted with the gr aph. //! Deregisters an external entity that may have interacted with the gr aph.
/** The graph will not return from wait_for_all until all the number of decrement_wait_count calls /** The graph will not return from wait_for_all until all the number of decrement_wait_count calls
skipping to change at line 556 skipping to change at line 574
graph& my_graph; graph& my_graph;
graph_node *next, *prev; graph_node *next, *prev;
public: public:
graph_node(graph& g) : my_graph(g) { graph_node(graph& g) : my_graph(g) {
my_graph.register_node(this); my_graph.register_node(this);
} }
virtual ~graph_node() { virtual ~graph_node() {
my_graph.remove_node(this); my_graph.remove_node(this);
} }
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
virtual void set_name( const char *name ) = 0;
#endif
protected: protected:
virtual void reset() = 0; virtual void reset() = 0;
}; };
inline void graph::register_node(graph_node *n) { inline void graph::register_node(graph_node *n) {
n->next = NULL; n->next = NULL;
{ {
spin_mutex::scoped_lock lock(nodelist_mutex); spin_mutex::scoped_lock lock(nodelist_mutex);
n->prev = my_nodes_last; n->prev = my_nodes_last;
if (my_nodes_last) my_nodes_last->next = n; if (my_nodes_last) my_nodes_last->next = n;
skipping to change at line 620 skipping to change at line 642
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 >
source_node( graph &g, Body body, bool is_active = true ) source_node( graph &g, Body body, bool is_active = true )
: graph_node(g), my_active(is_active), init_my_active(is_active), : graph_node(g), my_active(is_active), init_my_active(is_active),
my_body( new internal::source_body_leaf< output_type, Body>(body) ) , my_body( new internal::source_body_leaf< output_type, Body>(body) ) ,
my_reserved(false), my_has_cached_item(false) my_reserved(false), my_has_cached_item(false)
{ {
my_successors.set_owner(this); my_successors.set_owner(this);
tbb::internal::fgt_node_with_body( tbb::internal::FLOW_SOURCE_NODE,
&this->my_graph,
static_cast<sender<output_type>
*>(this), this->my_body );
} }
//! Copy constructor //! Copy constructor
source_node( const source_node& src ) : source_node( const source_node& src ) :
graph_node(src.my_graph), sender<Output>(), graph_node(src.my_graph), sender<Output>(),
my_active(src.init_my_active), my_active(src.init_my_active),
init_my_active(src.init_my_active), my_body( src.my_body->clone() ) , init_my_active(src.init_my_active), my_body( src.my_body->clone() ) ,
my_reserved(false), my_has_cached_item(false) my_reserved(false), my_has_cached_item(false)
{ {
my_successors.set_owner(this); my_successors.set_owner(this);
tbb::internal::fgt_node_with_body( tbb::internal::FLOW_SOURCE_NODE,
&this->my_graph,
static_cast<sender<output_type>
*>(this), this->my_body );
} }
//! The destructor //! The destructor
~source_node() { delete my_body; } ~source_node() { delete my_body; }
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name );
}
#endif
//! Add a new successor to this node //! Add a new successor to this node
/* override */ bool register_successor( receiver<output_type> &r ) { /* override */ bool register_successor( receiver<output_type> &r ) {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
my_successors.register_successor(r); my_successors.register_successor(r);
if ( my_active ) if ( my_active )
spawn_put(); spawn_put();
return true; return true;
} }
//! Removes a successor from this node //! Removes a successor from this node
skipping to change at line 800 skipping to change at line 832
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
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), internal::function_input<input_type,output_type,Allo graph_node(g), internal::function_input<input_type,output_type,Allo
cator>(g, concurrency, body) cator>(g, concurrency, body) {
{} tbb::internal::fgt_node_with_body( tbb::internal::FLOW_FUNCTION_NOD
E, &this->graph_node::my_graph, static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type>
*>(this), this->my_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() {
{} tbb::internal::fgt_node_with_body( tbb::internal::FLOW_FUNCTION_NOD
E, &this->my_graph, static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type>
*>(this), this->my_body );
}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name );
}
#endif
protected: protected:
template< typename R, typename B > friend class run_and_put_task; 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::broadcast_cache ;
template<typename X, typename Y> friend class internal::round_robin_cac he; template<typename X, typename Y> friend class internal::round_robin_cac he;
using fInput_type::try_put_task; 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(); }
skipping to change at line 838 skipping to change at line 880
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;
//! Constructor //! Constructor
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()
) ) {
{} tbb::internal::fgt_node_with_body( tbb::internal::FLOW_FUNCTION_NOD
E, &this->graph_node::my_graph, static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type>
*>(this), this->my_body );
}
//! Copy constructor //! Copy constructor
function_node( const function_node& src ) : function_node( const function_node& src ) :
graph_node(src.graph_node::my_graph), fInput_type( src, new queue_t graph_node(src.graph_node::my_graph), fInput_type( src, new queue_t
ype() ), fOutput_type() ype() ), fOutput_type() {
{} tbb::internal::fgt_node_with_body( tbb::internal::FLOW_FUNCTION_NOD
E, &this->graph_node::my_graph, static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type>
*>(this), this->my_body );
}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name );
}
#endif
protected: protected:
template< typename R, typename B > friend class run_and_put_task; 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::broadcast_cache ;
template<typename X, typename Y> friend class internal::round_robin_cac he; template<typename X, typename Y> friend class internal::round_robin_cac he;
using fInput_type::try_put_task; 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; }
skipping to change at line 887 skipping to change at line 939
static const int N = tbb::flow::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::multifunctio n_output, 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) {
{} tbb::internal::fgt_multioutput_node_with_body<Output,N>( tbb::inter
nal::FLOW_MULTIFUNCTION_NODE,
&this->gra
ph_node::my_graph, static_cast<receiver<input_type> *>(this),
this->outp
ut_ports(), this->my_body );
}
multifunction_node( const multifunction_node &other) : multifunction_node( const multifunction_node &other) :
graph_node(other.graph_node::my_graph), base_type(other) graph_node(other.graph_node::my_graph), base_type(other) {
{} tbb::internal::fgt_multioutput_node_with_body<Output,N>( tbb::inter
nal::FLOW_MULTIFUNCTION_NODE,
&this->gra
ph_node::my_graph, static_cast<receiver<input_type> *>(this),
this->outp
ut_ports(), this->my_body );
}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_multioutput_node_desc( this, name );
}
#endif
// 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<tbb::flow::tuple_size<Output>::v alue, internal::multifunction_output, Output>::type, Allocator> { typename internal::wrap_tuple_elements<tbb::flow::tuple_size<Output>::v alue, internal::multifunction_output, Output>::type, Allocator> {
protected: protected:
using graph_node::my_graph; using graph_node::my_graph;
static const int N = tbb::flow::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::multifuncti on_output, 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()) {
{} tbb::internal::fgt_multioutput_node_with_body<Output,N>( tbb::inter
nal::FLOW_MULTIFUNCTION_NODE,
&this->gra
ph_node::my_graph, static_cast<receiver<input_type> *>(this),
this->outp
ut_ports(), this->my_body );
}
multifunction_node( const multifunction_node &other) : multifunction_node( const multifunction_node &other) :
graph_node(other.graph_node::my_graph), base_type(other, new queue_ graph_node(other.graph_node::my_graph), base_type(other, new queue_
type()) type()) {
{} tbb::internal::fgt_multioutput_node_with_body<Output,N>( tbb::inter
nal::FLOW_MULTIFUNCTION_NODE,
&this->gra
ph_node::my_graph, static_cast<receiver<input_type> *>(this),
this->outp
ut_ports(), this->my_body );
}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_multioutput_node_desc( this, name );
}
#endif
// 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> {
skipping to change at line 940 skipping to change at line 1020
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) {} tbb::internal::fgt_multioutput_node<TupleType,N>( tbb::internal::FL
OW_SPLIT_NODE, &this->graph_node::my_graph,
static_cast<recei
ver<input_type> *>(this), this->output_ports() );
}
split_node( const split_node & other) : base_type(other) {
tbb::internal::fgt_multioutput_node<TupleType,N>( tbb::internal::FL
OW_SPLIT_NODE, &this->graph_node::my_graph,
static_cast<recei
ver<input_type> *>(this), this->output_ports() );
}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_multioutput_node_desc( this, name );
}
#endif
}; };
//! 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: 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::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 ) {
{} tbb::internal::fgt_node_with_body( tbb::internal::FLOW_CONTINUE_NOD
E, &this->my_graph,
static_cast<receiver<input_type>
*>(this),
static_cast<sender<output_type>
*>(this), this->my_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_ graph_node(g), internal::continue_input<output_type>( g, number_of_
predecessors, body ) predecessors, body ) {
{} tbb::internal::fgt_node_with_body( tbb::internal::FLOW_CONTINUE_NOD
E, &this->my_graph,
static_cast<receiver<input_type>
*>(this),
static_cast<sender<output_type>
*>(this), this->my_body );
}
//! Copy constructor //! Copy constructor
continue_node( const continue_node& src ) : continue_node( const continue_node& src ) :
graph_node(src.graph_node::my_graph), internal::continue_input<outp ut_type>(src), graph_node(src.graph_node::my_graph), internal::continue_input<outp ut_type>(src),
internal::function_output<Output>() internal::function_output<Output>() {
{} tbb::internal::fgt_node_with_body( tbb::internal::FLOW_CONTINUE_NOD
E, &this->my_graph,
static_cast<receiver<input_type>
*>(this),
static_cast<sender<output_type>
*>(this), this->my_body );
}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name );
}
#endif
protected: protected:
template< typename R, typename B > friend class run_and_put_task; 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::broadcast_cache ;
template<typename X, typename Y> friend class internal::round_robin_cac he; template<typename X, typename Y> friend class internal::round_robin_cac he;
using fInput_type::try_put_task; 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; }
skipping to change at line 998 skipping to change at line 1107
protected: 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 );
tbb::internal::fgt_node( tbb::internal::FLOW_OVERWRITE_NODE, &this-
>my_graph,
static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this) );
} }
// Copy constructor; doesn't take anything from src; default won't work // Copy constructor; doesn't take anything from src; default won't work
overwrite_node( const overwrite_node& src ) : overwrite_node( const overwrite_node& src ) :
graph_node(src.my_graph), receiver<T>(), sender<T>(), my_buffer_is_ valid(false) graph_node(src.my_graph), receiver<T>(), sender<T>(), my_buffer_is_ valid(false)
{ {
my_successors.set_owner( this ); my_successors.set_owner( this );
tbb::internal::fgt_node( tbb::internal::FLOW_OVERWRITE_NODE, &this-
>my_graph,
static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this) );
} }
~overwrite_node() {} ~overwrite_node() {}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name );
}
#endif
/* 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 us 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
skipping to change at line 1085 skipping to change at line 1204
template< typename T > template< typename T >
class write_once_node : public overwrite_node<T> { class write_once_node : public overwrite_node<T> {
public: public:
typedef T input_type; typedef T input_type;
typedef T output_type; typedef T output_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
//! Constructor //! Constructor
write_once_node(graph& g) : overwrite_node<T>(g) {} write_once_node(graph& g) : overwrite_node<T>(g) {
tbb::internal::fgt_node( tbb::internal::FLOW_WRITE_ONCE_NODE, &(thi
s->my_graph),
static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this) )
;
}
//! 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)
{} {
tbb::internal::fgt_node( tbb::internal::FLOW_WRITE_ONCE_NODE, &(thi
s->my_graph),
static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this) )
;
}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name );
}
#endif
protected: protected:
template< typename R, typename B > friend class run_and_put_task; 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::broadcast_cache ;
template<typename X, typename Y> friend class internal::round_robin_cac he; template<typename X, typename Y> friend class internal::round_robin_cac he;
/* override */ task *try_put_task( const T &v ) { /* 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 NULL; return NULL;
} else { } else {
skipping to change at line 1123 skipping to change at line 1256
private: 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 );
tbb::internal::fgt_node( tbb::internal::FLOW_BROADCAST_NODE, &this-
>my_graph,
static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this) );
} }
// Copy constructor // Copy constructor
broadcast_node( const broadcast_node& src ) : broadcast_node( const broadcast_node& src ) :
graph_node(src.my_graph), receiver<T>(), sender<T>() graph_node(src.my_graph), receiver<T>(), sender<T>()
{ {
my_successors.set_owner( this ); my_successors.set_owner( this );
tbb::internal::fgt_node( tbb::internal::FLOW_BROADCAST_NODE, &this-
>my_graph,
static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this) );
} }
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name );
}
#endif
//! Adds a successor //! Adds a successor
virtual bool register_successor( receiver<T> &r ) { virtual bool register_successor( receiver<T> &r ) {
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;
skipping to change at line 1338 skipping to change at line 1481
this->release_front(); this->release_front();
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
public: public:
//! Constructor //! Constructor
buffer_node( graph &g ) : graph_node(g), reservable_item_buffer<T>(), buffer_node( graph &g ) : graph_node(g), reservable_item_buffer<T>(),
forwarder_busy(false) { forwarder_busy(false) {
my_successors.set_owner(this); my_successors.set_owner(this);
my_aggregator.initialize_handler(my_handler(this)); my_aggregator.initialize_handler(my_handler(this));
tbb::internal::fgt_node( tbb::internal::FLOW_BUFFER_NODE, &this->my
_graph,
static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this) );
} }
//! Copy constructor //! Copy constructor
buffer_node( const buffer_node& src ) : graph_node(src.my_graph), buffer_node( const buffer_node& src ) : graph_node(src.my_graph),
reservable_item_buffer<T>(), receiver<T>(), sender<T>() { reservable_item_buffer<T>(), receiver<T>(), sender<T>() {
forwarder_busy = false; forwarder_busy = false;
my_successors.set_owner(this); my_successors.set_owner(this);
my_aggregator.initialize_handler(my_handler(this)); my_aggregator.initialize_handler(my_handler(this));
tbb::internal::fgt_node( tbb::internal::FLOW_BUFFER_NODE, &this->my
_graph,
static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this) );
} }
virtual ~buffer_node() {} virtual ~buffer_node() {}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name );
}
#endif
// //
// 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);
skipping to change at line 1516 skipping to change at line 1669
__TBB_store_with_release(op->status, SUCCEEDED); __TBB_store_with_release(op->status, SUCCEEDED);
} }
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;
//! Constructor //! Constructor
queue_node( graph &g ) : buffer_node<T, A>(g) {} queue_node( graph &g ) : buffer_node<T, A>(g) {
tbb::internal::fgt_node( tbb::internal::FLOW_QUEUE_NODE, &(this->my
_graph),
static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this) )
;
}
//! Copy constructor //! Copy constructor
queue_node( const queue_node& src) : buffer_node<T, A>(src) {} queue_node( const queue_node& src) : buffer_node<T, A>(src) {
tbb::internal::fgt_node( tbb::internal::FLOW_QUEUE_NODE, &(this->my
_graph),
static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this) )
;
}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name );
}
#endif
}; };
//! Forwards messages in sequence order //! Forwards messages in sequence order
template< typename T, typename A=cache_aligned_allocator<T> > template< typename T, typename A=cache_aligned_allocator<T> >
class sequencer_node : public queue_node<T, A> { class sequencer_node : public queue_node<T, A> {
internal::function_body< T, size_t > *my_sequencer; internal::function_body< T, size_t > *my_sequencer;
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;
//! Constructor //! Constructor
template< typename Sequencer > template< typename Sequencer >
sequencer_node( graph &g, const Sequencer& s ) : queue_node<T, A>(g), sequencer_node( graph &g, const Sequencer& s ) : queue_node<T, A>(g),
my_sequencer(new internal::function_body_leaf< T, size_t, Sequencer my_sequencer(new internal::function_body_leaf< T, size_t, Sequencer
>(s) ) {} >(s) ) {
tbb::internal::fgt_node( tbb::internal::FLOW_SEQUENCER_NODE, &(this
->my_graph),
static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this) )
;
}
//! Copy constructor //! Copy constructor
sequencer_node( const sequencer_node& src ) : queue_node<T, A>(src), sequencer_node( const sequencer_node& src ) : queue_node<T, A>(src),
my_sequencer( src.my_sequencer->clone() ) {} my_sequencer( src.my_sequencer->clone() ) {
tbb::internal::fgt_node( tbb::internal::FLOW_SEQUENCER_NODE, &(this
->my_graph),
static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this) )
;
}
//! Destructor //! Destructor
~sequencer_node() { delete my_sequencer; } ~sequencer_node() { delete my_sequencer; }
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name );
}
#endif
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 sequencer_operatio n; typedef typename buffer_node<T, A>::buffer_operation sequencer_operatio n;
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
private: private:
/* override */ void internal_push(sequencer_operation *op) { /* override */ void internal_push(sequencer_operation *op) {
size_type tag = (*my_sequencer)(*(op->elem)); size_type tag = (*my_sequencer)(*(op->elem));
skipping to change at line 1573 skipping to change at line 1756
template< typename T, typename Compare = std::less<T>, typename A=cache_ali gned_allocator<T> > template< typename T, typename Compare = std::less<T>, typename A=cache_ali gned_allocator<T> >
class priority_queue_node : public buffer_node<T, A> { class priority_queue_node : public buffer_node<T, A> {
public: public:
typedef T input_type; typedef T input_type;
typedef T output_type; typedef T output_type;
typedef buffer_node<T,A> base_type; typedef buffer_node<T,A> base_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
//! Constructor //! Constructor
priority_queue_node( graph &g ) : buffer_node<T, A>(g), mark(0) {} priority_queue_node( graph &g ) : buffer_node<T, A>(g), mark(0) {
tbb::internal::fgt_node( tbb::internal::FLOW_PRIORITY_QUEUE_NODE, &
(this->my_graph),
static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this) )
;
}
//! Copy constructor //! Copy constructor
priority_queue_node( const priority_queue_node &src ) : buffer_node<T, priority_queue_node( const priority_queue_node &src ) : buffer_node<T,
A>(src), mark(0) {} A>(src), mark(0) {
tbb::internal::fgt_node( tbb::internal::FLOW_PRIORITY_QUEUE_NODE, &
(this->my_graph),
static_cast<receiver<input_type> *>(this),
static_cast<sender<output_type> *>(this) )
;
}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name );
}
#endif
protected: protected:
/*override*/void reset() { /*override*/void reset() {
mark = 0; mark = 0;
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;
skipping to change at line 1777 skipping to change at line 1974
protected: 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:
size_t my_threshold; size_t my_threshold;
size_t my_count; size_t my_count; //number of successful puts
internal::predecessor_cache< T > my_predecessors; size_t my_tries; //number of active put attempts
internal::reservable_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_bypass< 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> >;
bool check_conditions() {
return ( my_count + my_tries < my_threshold && !my_predecessors.emp
ty() && !my_successors.empty() );
}
// only returns a valid task pointer or NULL, never SUCCESSFULLY_ENQUEU ED // only returns a valid task pointer or NULL, never SUCCESSFULLY_ENQUEU ED
task * decrement_counter() { task *forward_task() {
input_type v; input_type v;
task *rval = NULL; task *rval = NULL;
bool reserved = false;
{
spin_mutex::scoped_lock lock(my_mutex);
if ( check_conditions() )
++my_tries;
else
return NULL;
}
// If we can't get / put an item immediately then drop the count //SUCCESS
if ( my_predecessors.get_item( v ) == false // if we can reserve and can put, we consume the reservation
|| (rval = my_successors.try_put_task(v)) == NULL ) { // we increment the count and decrement the tries
if ( (my_predecessors.try_reserve(v)) == true ){
reserved=true;
if ( (rval = my_successors.try_put_task(v)) != NULL ){
{
spin_mutex::scoped_lock lock(my_mutex);
++my_count;
--my_tries;
my_predecessors.try_consume();
if ( check_conditions() ) {
task* tp = this->my_graph.root_task();
if ( tp ) {
task *rtask = new ( task::allocate_additional_c
hild_of( *tp ) )
internal::forward_task_bypass< limiter_node
<T> >( *this );
FLOW_SPAWN (*rtask);
}
}
}
return rval;
}
}
//FAILURE
//if we can't reserve, we decrement the tries
//if we can reserve but can't put, we decrement the tries and relea
se the reservation
{
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
if(my_count) --my_count; --my_tries;
task* tp = this->my_graph.root_task(); if (reserved) my_predecessors.try_release();
if ( !my_predecessors.empty() && tp ) { if ( check_conditions() ) {
task *rtask = new ( task::allocate_additional_child_of( *tp task* tp = this->my_graph.root_task();
) ) if ( tp ) {
internal::forward_task_bypass< limiter_node<T> >( *this task *rtask = new ( task::allocate_additional_child_of(
); *tp ) )
__TBB_ASSERT(!rval, "Have two tasks to handle"); internal::forward_task_bypass< limiter_node<T> >( *
return rtask; this );
__TBB_ASSERT(!rval, "Have two tasks to handle");
return rtask;
}
} }
return rval;
} }
return rval;
} }
void forward() { void forward() {
{ __TBB_ASSERT(false, "Should never be called");
spin_mutex::scoped_lock lock(my_mutex); return;
if ( my_count < my_threshold )
++my_count;
else
return;
}
task * rtask = decrement_counter();
if(rtask) FLOW_SPAWN(*rtask);
} }
task *forward_task() { task * decrement_counter() {
{ {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
if ( my_count >= my_threshold ) if(my_count) --my_count;
return NULL;
++my_count;
} }
task * rtask = decrement_counter(); return forward_task();
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_threshold(threshold), my_count(0), graph_node(g), my_threshold(threshold), my_count(0), my_tries(0),
init_decrement_predecessors(num_decrement_predecessors), init_decrement_predecessors(num_decrement_predecessors),
decrement(num_decrement_predecessors) decrement(num_decrement_predecessors)
{ {
my_predecessors.set_owner(this); my_predecessors.set_owner(this);
my_successors.set_owner(this); my_successors.set_owner(this);
decrement.set_owner(this); decrement.set_owner(this);
tbb::internal::fgt_node( tbb::internal::FLOW_LIMITER_NODE, &this->m
y_graph,
static_cast<receiver<input_type> *>(this),
static_cast<receiver<continue_msg> *>(&decrement),
static_cast<sender<output_type> *>(this) )
;
} }
//! Copy constructor //! Copy constructor
limiter_node( const limiter_node& src ) : limiter_node( const limiter_node& src ) :
graph_node(src.my_graph), receiver<T>(), sender<T>(), graph_node(src.my_graph), receiver<T>(), sender<T>(),
my_threshold(src.my_threshold), my_count(0), my_threshold(src.my_threshold), my_count(0), my_tries(0),
init_decrement_predecessors(src.init_decrement_predecessors), init_decrement_predecessors(src.init_decrement_predecessors),
decrement(src.init_decrement_predecessors) decrement(src.init_decrement_predecessors)
{ {
my_predecessors.set_owner(this); my_predecessors.set_owner(this);
my_successors.set_owner(this); my_successors.set_owner(this);
decrement.set_owner(this); decrement.set_owner(this);
tbb::internal::fgt_node( tbb::internal::FLOW_LIMITER_NODE, &this->m
y_graph,
static_cast<receiver<input_type> *>(this),
static_cast<receiver<continue_msg> *>(&decrement),
static_cast<sender<output_type> *>(this) )
;
} }
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name );
}
#endif
//! Replace the current successor with this new successor //! Replace the current successor with this new successor
/* override */ bool register_successor( receiver<output_type> &r ) { /* override */ bool register_successor( receiver<output_type> &r ) {
spin_mutex::scoped_lock lock(my_mutex);
bool was_empty = my_successors.empty();
my_successors.register_successor(r); my_successors.register_successor(r);
//spawn a forward task if this is the only successor
if ( was_empty && !my_predecessors.empty() && my_count + my_tries <
my_threshold ) {
task* tp = this->my_graph.root_task();
if ( tp ) {
FLOW_SPAWN( (* new ( task::allocate_additional_child_of( *t
p ) )
internal::forward_task_bypass < limiter_node<T>
>( *this ) ) );
}
}
return true; return true;
} }
//! 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;
} }
//! Removes src from 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 ) {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
my_predecessors.add( src ); my_predecessors.add( src );
task* tp = this->my_graph.root_task(); task* tp = this->my_graph.root_task();
if ( my_count < my_threshold && !my_successors.empty() && tp ) { if ( my_count + my_tries < my_threshold && !my_successors.empty() & & tp ) {
FLOW_SPAWN( (* new ( task::allocate_additional_child_of( *tp ) ) FLOW_SPAWN( (* new ( task::allocate_additional_child_of( *tp ) )
internal::forward_task_bypass < 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;
skipping to change at line 1900 skipping to change at line 2149
protected: protected:
template< typename R, typename B > friend class run_and_put_task; 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::broadcast_cache ;
template<typename X, typename Y> friend class internal::round_robin_cac he; template<typename X, typename Y> friend class internal::round_robin_cac he;
//! Puts an item to this receiver //! Puts an item to this receiver
/* override */ task *try_put_task( const T &t ) { /* override */ task *try_put_task( const T &t ) {
{ {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
if ( my_count >= my_threshold ) if ( my_count + my_tries >= my_threshold )
return NULL; return NULL;
else else
++my_count; ++my_tries;
} }
task * rtask = my_successors.try_put_task(t); task * rtask = my_successors.try_put_task(t);
if ( !rtask ) { // try_put_task failed. if ( !rtask ) { // try_put_task failed.
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
--my_count; --my_tries;
task* tp = this->my_graph.root_task(); task* tp = this->my_graph.root_task();
if ( !my_predecessors.empty() && tp ) { if ( check_conditions() && tp ) {
rtask = new ( task::allocate_additional_child_of( *tp ) ) rtask = new ( task::allocate_additional_child_of( *tp ) )
internal::forward_task_bypass< limiter_node<T> >( *this ); internal::forward_task_bypass< limiter_node<T> >( *this );
} }
} }
else {
spin_mutex::scoped_lock lock(my_mutex);
++my_count;
--my_tries;
}
return rtask; 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(); }
skipping to change at line 1948 skipping to change at line 2202
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 <tbb::flow::tuple_size<OutputTuple>::value, reserving_port, OutputTuple, re serving> { 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 = tbb::flow::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) {} tbb::internal::fgt_multiinput_node<OutputTuple,N>( tbb::internal::F
LOW_JOIN_NODE_RESERVING, &this->my_graph,
this->input_ports(), static_cas
t< sender< output_type > *>(this) );
}
join_node(const join_node &other) : unfolded_type(other) {
tbb::internal::fgt_multiinput_node<OutputTuple,N>( tbb::internal::F
LOW_JOIN_NODE_RESERVING, &this->my_graph,
this->input_ports(), static_cas
t< sender< output_type > *>(this) );
}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name );
}
#endif
}; };
template<typename OutputTuple> template<typename OutputTuple>
class join_node<OutputTuple,queueing>: public internal::unfolded_join_node< tbb::flow::tuple_size<OutputTuple>::value, queueing_port, OutputTuple, queu eing> { 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 = tbb::flow::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) {} tbb::internal::fgt_multiinput_node<OutputTuple,N>( tbb::internal::F
LOW_JOIN_NODE_QUEUEING, &this->my_graph,
this->input_ports(), static_cas
t< sender< output_type > *>(this) );
}
join_node(const join_node &other) : unfolded_type(other) {
tbb::internal::fgt_multiinput_node<OutputTuple,N>( tbb::internal::F
LOW_JOIN_NODE_QUEUEING, &this->my_graph,
this->input_ports(), static_cas
t< sender< output_type > *>(this) );
}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name );
}
#endif
}; };
// 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<tbb::flow::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 = tbb::flow::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 __TBB_B0, typename __TBB_B1> template<typename __TBB_B0, typename __TBB_B1>
join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1) : unfolded_type(g, b0, b1 join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1) : unfolded_type(g, b0, b1
) { } ) {
tbb::internal::fgt_multiinput_node<OutputTuple,N>( tbb::internal::F
LOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
this->input_port
s(), static_cast< sender< output_type > *>(this) );
}
template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2> template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2>
join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2) : unfolded_t join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2) : unfolded_t
ype(g, b0, b1, b2) { } ype(g, b0, b1, b2) {
tbb::internal::fgt_multiinput_node<OutputTuple,N>( tbb::internal::F
LOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
this->input_port
s(), static_cast< sender< output_type > *>(this) );
}
template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typen ame __TBB_B3> template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typen ame __TBB_B3>
join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3) join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3)
: unfolded_type(g, b0, b1, b2, b3) { } : unfolded_type(g, b0, b1, b2, b3) {
tbb::internal::fgt_multiinput_node<OutputTuple,N>( tbb::internal::F
LOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
this->input_port
s(), static_cast< sender< output_type > *>(this) );
}
template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typen ame __TBB_B3, typename __TBB_B4> template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typen ame __TBB_B3, typename __TBB_B4>
join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4) : join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4) :
unfolded_type(g, b0, b1, b2, b3, b4) { } unfolded_type(g, b0, b1, b2, b3, b4) {
tbb::internal::fgt_multiinput_node<OutputTuple,N>( tbb::internal::F
LOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
this->input_port
s(), static_cast< sender< output_type > *>(this) );
}
#if __TBB_VARIADIC_MAX >= 6 #if __TBB_VARIADIC_MAX >= 6
template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typen ame __TBB_B3, typename __TBB_B4, template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typen ame __TBB_B3, typename __TBB_B4,
typename __TBB_B5> typename __TBB_B5>
join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5) : join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5) :
unfolded_type(g, b0, b1, b2, b3, b4, b5) { } unfolded_type(g, b0, b1, b2, b3, b4, b5) {
tbb::internal::fgt_multiinput_node<OutputTuple,N>( tbb::internal::F
LOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
this->input_port
s(), static_cast< sender< output_type > *>(this) );
}
#endif #endif
#if __TBB_VARIADIC_MAX >= 7 #if __TBB_VARIADIC_MAX >= 7
template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typen ame __TBB_B3, typename __TBB_B4, template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typen ame __TBB_B3, typename __TBB_B4,
typename __TBB_B5, typename __TBB_B6> typename __TBB_B5, typename __TBB_B6>
join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6) : join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6) :
unfolded_type(g, b0, b1, b2, b3, b4, b5, b6) { } unfolded_type(g, b0, b1, b2, b3, b4, b5, b6) {
tbb::internal::fgt_multiinput_node<OutputTuple,N>( tbb::internal::F
LOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
this->input_port
s(), static_cast< sender< output_type > *>(this) );
}
#endif #endif
#if __TBB_VARIADIC_MAX >= 8 #if __TBB_VARIADIC_MAX >= 8
template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typen ame __TBB_B3, typename __TBB_B4, template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typen ame __TBB_B3, typename __TBB_B4,
typename __TBB_B5, typename __TBB_B6, typename __TBB_B7> typename __TBB_B5, typename __TBB_B6, typename __TBB_B7>
join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6, join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6,
__TBB_B7 b7) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7) __TBB_B7 b7) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7)
{ } {
tbb::internal::fgt_multiinput_node<OutputTuple,N>( tbb::internal::F
LOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
this->input_port
s(), static_cast< sender< output_type > *>(this) );
}
#endif #endif
#if __TBB_VARIADIC_MAX >= 9 #if __TBB_VARIADIC_MAX >= 9
template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typen ame __TBB_B3, typename __TBB_B4, template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typen ame __TBB_B3, typename __TBB_B4,
typename __TBB_B5, typename __TBB_B6, typename __TBB_B7, typename _ _TBB_B8> typename __TBB_B5, typename __TBB_B6, typename __TBB_B7, typename _ _TBB_B8>
join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6, join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6,
__TBB_B7 b7, __TBB_B8 b8) : unfolded_type(g, b0, b1, b2, b3, b4 __TBB_B7 b7, __TBB_B8 b8) : unfolded_type(g, b0, b1, b2, b3, b4
, b5, b6, b7, b8) { } , b5, b6, b7, b8) {
tbb::internal::fgt_multiinput_node<OutputTuple,N>( tbb::internal::F
LOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
this->input_port
s(), static_cast< sender< output_type > *>(this) );
}
#endif #endif
#if __TBB_VARIADIC_MAX >= 10 #if __TBB_VARIADIC_MAX >= 10
template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typen ame __TBB_B3, typename __TBB_B4, template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typen ame __TBB_B3, typename __TBB_B4,
typename __TBB_B5, typename __TBB_B6, typename __TBB_B7, typename _ _TBB_B8, typename __TBB_B9> typename __TBB_B5, typename __TBB_B6, typename __TBB_B7, typename _ _TBB_B8, typename __TBB_B9>
join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6, join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6,
__TBB_B7 b7, __TBB_B8 b8, __TBB_B9 b9) : unfolded_type(g, b0, b __TBB_B7 b7, __TBB_B8 b8, __TBB_B9 b9) : unfolded_type(g, b0, b
1, b2, b3, b4, b5, b6, b7, b8, b9) { } 1, b2, b3, b4, b5, b6, b7, b8, b9) {
tbb::internal::fgt_multiinput_node<OutputTuple,N>( tbb::internal::F
LOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
this->input_port
s(), static_cast< sender< output_type > *>(this) );
}
#endif #endif
join_node(const join_node &other) : unfolded_type(other) {} join_node(const join_node &other) : unfolded_type(other) {
tbb::internal::fgt_multiinput_node<OutputTuple,N>( tbb::internal::F
LOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
this->input_port
s(), static_cast< sender< output_type > *>(this) );
}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name );
}
#endif
}; };
#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 = tbb::flow::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) {
tbb::internal::fgt_multiinput_node<InputTuple,N>( tbb::internal::FL
OW_OR_NODE, &this->my_graph,
this->input_ports(), static_cast
< sender< output_type > *>(this) );
}
// Copy constructor // Copy constructor
or_node( const or_node& other ) : unfolded_type(other) { } or_node( const or_node& other ) : unfolded_type(other) {
tbb::internal::fgt_multiinput_node<InputTuple,N>( tbb::internal::FL
OW_OR_NODE, &this->my_graph,
this->input_ports(), static_cast
< sender< output_type > *>(this) );
}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name );
}
#endif
}; };
#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
template< typename T > template< typename T >
inline void make_edge( sender<T> &p, receiver<T> &s ) { inline void make_edge( sender<T> &p, receiver<T> &s ) {
p.register_successor( s ); p.register_successor( s );
tbb::internal::fgt_make_edge( &p, &s );
} }
//! Makes an edge between a single predecessor and a single successor //! Makes an edge between a single predecessor and a single successor
template< typename T > template< typename T >
inline void remove_edge( sender<T> &p, receiver<T> &s ) { inline void remove_edge( sender<T> &p, receiver<T> &s ) {
p.remove_successor( s ); p.remove_successor( s );
tbb::internal::fgt_remove_edge( &p, &s );
} }
//! Returns a copy of the body from a function or continue node //! Returns a copy of the body from a function or continue node
template< typename Body, typename Node > template< typename Body, typename Node >
Body copy_body( Node &n ) { Body copy_body( Node &n ) {
return n.template copy_function_object<Body>(); return n.template copy_function_object<Body>();
} }
} // interface7 } // interface7
 End of changes. 82 change blocks. 
101 lines changed or deleted 544 lines changed or added


 gcc_armv7.h   gcc_armv7.h 
skipping to change at line 90 skipping to change at line 90
{ {
int32_t oldval, res; int32_t oldval, res;
__TBB_full_memory_fence(); __TBB_full_memory_fence();
do { do {
__asm__ __volatile__( __asm__ __volatile__(
"ldrex %1, [%3]\n" "ldrex %1, [%3]\n"
"mov %0, #0\n" "mov %0, #0\n"
"cmp %1, %4\n" "cmp %1, %4\n"
"it eq\n"
"strexeq %0, %5, [%3]\n" "strexeq %0, %5, [%3]\n"
: "=&r" (res), "=&r" (oldval), "+Qo" (*(volatile int32_t*)ptr) : "=&r" (res), "=&r" (oldval), "+Qo" (*(volatile int32_t*)ptr)
: "r" ((int32_t *)ptr), "Ir" (comparand), "r" (value) : "r" ((int32_t *)ptr), "Ir" (comparand), "r" (value)
: "cc"); : "cc");
} while (res); } while (res);
__TBB_full_memory_fence(); __TBB_full_memory_fence();
return oldval; return oldval;
} }
skipping to change at line 120 skipping to change at line 121
int64_t oldval; int64_t oldval;
int32_t res; int32_t res;
__TBB_full_memory_fence(); __TBB_full_memory_fence();
do { do {
__asm__ __volatile__( __asm__ __volatile__(
"mov %0, #0\n" "mov %0, #0\n"
"ldrexd %1, %H1, [%3]\n" "ldrexd %1, %H1, [%3]\n"
"cmp %1, %4\n" "cmp %1, %4\n"
"it eq\n"
"cmpeq %H1, %H4\n" "cmpeq %H1, %H4\n"
"it eq\n"
"strexdeq %0, %5, %H5, [%3]" "strexdeq %0, %5, %H5, [%3]"
: "=&r" (res), "=&r" (oldval), "+Qo" (*(volatile int64_t*)ptr) : "=&r" (res), "=&r" (oldval), "+Qo" (*(volatile int64_t*)ptr)
: "r" ((int64_t *)ptr), "r" (comparand), "r" (value) : "r" ((int64_t *)ptr), "r" (comparand), "r" (value)
: "cc"); : "cc");
} while (res); } while (res);
__TBB_full_memory_fence(); __TBB_full_memory_fence();
return oldval; return oldval;
} }
 End of changes. 3 change blocks. 
0 lines changed or deleted 3 lines changed or added


 gcc_itsx.h   gcc_itsx.h 
skipping to change at line 67 skipping to change at line 67
{ {
// 'pause' instruction aborts HLE/RTM transactions // 'pause' instruction aborts HLE/RTM transactions
__asm__ volatile ("pause\n" : : : "memory" ); __asm__ volatile ("pause\n" : : : "memory" );
} }
inline static void __TBB_machine_unlock_elided( volatile uint8_t* lk ) inline static void __TBB_machine_unlock_elided( volatile uint8_t* lk )
{ {
__asm__ volatile (".byte " __TBB_STRINGIZE(__TBB_OP_XRELEASE)"; movb $0 , %0" __asm__ volatile (".byte " __TBB_STRINGIZE(__TBB_OP_XRELEASE)"; movb $0 , %0"
: "=m"(*lk) : "m"(*lk) : "memory" ); : "=m"(*lk) : "m"(*lk) : "memory" );
} }
#if __TBB_TSX_INTRINSICS_PRESENT
#include <immintrin.h>
#define __TBB_machine_is_in_transaction _xtest
#else
/*!
* Check if the instruction is executed in a transaction or not
*/
inline static bool __TBB_machine_is_in_transaction()
{
int8_t res = 0;
#if __TBB_x86_32
__asm__ volatile (".byte 0x0F; .byte 0x01; .byte 0xD6;\n"
"setz %0" : "=q"(res) : : "memory" );
#else
__asm__ volatile (".byte 0x0F; .byte 0x01; .byte 0xD6;\n"
"setz %0" : "=r"(res) : : "memory" );
#endif
return res==0;
}
#endif /* __TBB_TSX_INTRINSICS_PRESENT */
#if TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX
#if __TBB_TSX_INTRINSICS_PRESENT
#define __TBB_machine_begin_transaction _xbegin
#define __TBB_machine_end_transaction _xend
#define __TBB_machine_transaction_conflict_abort() _xabort(0xff)
#else
/*!
* Enter speculative execution mode.
* @return -1 on success
* abort cause ( or 0 ) on abort
*/
inline static uint32_t __TBB_machine_begin_transaction()
{
uint32_t res = ~uint32_t(0); // success value
__asm__ volatile ("1: .byte 0xC7; .byte 0xF8;\n" // XBEGIN
<abort-offset>
" .long 2f-1b-6\n" // 2f-1b =
= difference in addresses of start
// of XBEG
IN and the MOVL
// 2f - 1b
- 6 == that difference minus the size of the
// XBEGIN
instruction. This is the abort offset to
// 2: belo
w.
" jmp 3f\n" // success
(leave -1 in res)
"2: movl %%eax,%0\n" // store f
ailure code in res
"3:"
:"=r"(res):"0"(res):"memory","%eax");
return res;
}
/*!
* Attempt to commit/end transaction
*/
inline static void __TBB_machine_end_transaction()
{
__asm__ volatile (".byte 0x0F; .byte 0x01; .byte 0xD5" :::"memory");
// XEND
}
/*
* aborts with code 0xFF (lock already held)
*/
inline static void __TBB_machine_transaction_conflict_abort()
{
__asm__ volatile (".byte 0xC6; .byte 0xF8; .byte 0xFF" :::"memory");
}
#endif /* __TBB_TSX_INTRINSICS_PRESENT */
#endif // TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX
 End of changes. 1 change blocks. 
0 lines changed or deleted 0 lines changed or added


 memory_pool.h   memory_pool.h 
skipping to change at line 140 skipping to change at line 140
//! Free previously allocated block of memory. //! Free previously allocated block of memory.
void deallocate( pointer p, size_type ) { void deallocate( pointer p, size_type ) {
my_pool->free(p); my_pool->free(p);
} }
//! Largest value for which method allocate might succeed. //! Largest value for which method allocate might succeed.
size_type max_size() const throw() { size_type max_size() const throw() {
size_type max = static_cast<size_type>(-1) / sizeof (value_type); size_type max = static_cast<size_type>(-1) / sizeof (value_type);
return (max > 0 ? max : 1); return (max > 0 ? max : 1);
} }
//! Copy-construct value at location pointed to by p. //! Copy-construct value at location pointed to by p.
#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESEN T #if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
template<typename U, typename... Args> template<typename U, typename... Args>
void construct(U *p, Args&&... args) void construct(U *p, Args&&... args)
#if __TBB_CPP11_STD_FORWARD_BROKEN #if __TBB_CPP11_STD_FORWARD_BROKEN
{ ::new((void *)p) U((args)...); } { ::new((void *)p) U((args)...); }
#else #else
{ ::new((void *)p) U(std::forward<Args>(args)...); } { ::new((void *)p) U(std::forward<Args>(args)...); }
#endif #endif
#else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_P RESENT #else // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
void construct( pointer p, const value_type& value ) { ::new((void*)(p) ) value_type(value); } void construct( pointer p, const value_type& value ) { ::new((void*)(p) ) value_type(value); }
#endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_ PRESENT #endif // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
//! Destroy value at location pointed to by p. //! Destroy value at location pointed to by p.
void destroy( pointer p ) { p->~value_type(); } void destroy( pointer p ) { p->~value_type(); }
}; };
#if _MSC_VER && !defined(__INTEL_COMPILER) #if _MSC_VER && !defined(__INTEL_COMPILER)
#pragma warning (pop) #pragma warning (pop)
#endif // warning 4100 is back #endif // warning 4100 is back
 End of changes. 3 change blocks. 
3 lines changed or deleted 3 lines changed or added


 msvc_ia32_common.h   msvc_ia32_common.h 
skipping to change at line 192 skipping to change at line 192
extern "C" { extern "C" {
__int8 __TBB_EXPORTED_FUNC __TBB_machine_try_lock_elided (volatile void * ptr); __int8 __TBB_EXPORTED_FUNC __TBB_machine_try_lock_elided (volatile void * ptr);
void __TBB_EXPORTED_FUNC __TBB_machine_unlock_elided (volatile void* ptr); void __TBB_EXPORTED_FUNC __TBB_machine_unlock_elided (volatile void* ptr);
// 'pause' instruction aborts HLE/RTM transactions // 'pause' instruction aborts HLE/RTM transactions
#if __TBB_PAUSE_USE_INTRINSIC #if __TBB_PAUSE_USE_INTRINSIC
inline static void __TBB_machine_try_lock_elided_cancel() { _mm_pause() ; } inline static void __TBB_machine_try_lock_elided_cancel() { _mm_pause() ; }
#else #else
inline static void __TBB_machine_try_lock_elided_cancel() { _asm pause; } inline static void __TBB_machine_try_lock_elided_cancel() { _asm pause; }
#endif #endif
#if __TBB_TSX_INTRINSICS_PRESENT
#define __TBB_machine_is_in_transaction _xtest
#else
__int8 __TBB_EXPORTED_FUNC __TBB_machine_is_in_transaction();
#endif /* __TBB_TSX_INTRINSICS_PRESENT */
#if TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX
#if __TBB_TSX_INTRINSICS_PRESENT
#define __TBB_machine_begin_transaction _xbegin
#define __TBB_machine_end_transaction _xend
// The value (0xFF) below comes from the
// Intel(R) 64 and IA-32 Architectures Optimization Reference Manual 12
.4.5 lock not free
#define __TBB_machine_transaction_conflict_abort() _xabort(0xFF)
#else
unsigned __int32 __TBB_EXPORTED_FUNC __TBB_machine_begin_transaction();
void __TBB_EXPORTED_FUNC __TBB_machine_end_transaction();
void __TBB_EXPORTED_FUNC __TBB_machine_transaction_conflict
_abort();
#endif /* __TBB_TSX_INTRINSICS_PRESENT */
#endif /* TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX */
} }
#endif /* __TBB_machine_msvc_ia32_common_H */ #endif /* __TBB_machine_msvc_ia32_common_H */
 End of changes. 1 change blocks. 
0 lines changed or deleted 25 lines changed or added


 scalable_allocator.h   scalable_allocator.h 
skipping to change at line 267 skipping to change at line 267
//! Free previously allocated block of memory //! Free previously allocated block of memory
void deallocate( pointer p, size_type ) { void deallocate( pointer p, size_type ) {
scalable_free( p ); scalable_free( p );
} }
//! Largest value for which method allocate might succeed. //! Largest value for which method allocate might succeed.
size_type max_size() const throw() { size_type max_size() const throw() {
size_type absolutemax = static_cast<size_type>(-1) / sizeof (value_ type); size_type absolutemax = static_cast<size_type>(-1) / sizeof (value_ type);
return (absolutemax > 0 ? absolutemax : 1); return (absolutemax > 0 ? absolutemax : 1);
} }
#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESEN T #if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
template<typename U, typename... Args> template<typename U, typename... Args>
void construct(U *p, Args&&... args) void construct(U *p, Args&&... args)
#if __TBB_CPP11_STD_FORWARD_BROKEN #if __TBB_CPP11_STD_FORWARD_BROKEN
{ ::new((void *)p) U((args)...); } { ::new((void *)p) U((args)...); }
#else #else
{ ::new((void *)p) U(std::forward<Args>(args)...); } { ::new((void *)p) U(std::forward<Args>(args)...); }
#endif #endif
#else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_P RESENT #else // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);} void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);}
#endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_ PRESENT #endif // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
void destroy( pointer p ) {p->~value_type();} void destroy( pointer p ) {p->~value_type();}
}; };
#if _MSC_VER && !defined(__INTEL_COMPILER) #if _MSC_VER && !defined(__INTEL_COMPILER)
#pragma warning (pop) #pragma warning (pop)
#endif // warning 4100 is back #endif // warning 4100 is back
//! Analogous to std::allocator<void>, as defined in ISO C++ Standard, Sect ion 20.4.1 //! Analogous to std::allocator<void>, as defined in ISO C++ Standard, Sect ion 20.4.1
/** @ingroup memory_allocation */ /** @ingroup memory_allocation */
template<> template<>
 End of changes. 3 change blocks. 
3 lines changed or deleted 3 lines changed or added


 spin_mutex.h   spin_mutex.h 
skipping to change at line 212 skipping to change at line 212
its critical sections, using HW mechanisms to detect real data races an d its critical sections, using HW mechanisms to detect real data races an d
ensure atomicity of the critical sections. In particular, it uses ensure atomicity of the critical sections. In particular, it uses
Intel(R) Transactional Synchronization Extensions (Intel(R) TSX). Intel(R) Transactional Synchronization Extensions (Intel(R) TSX).
Without such HW support, it behaves like a spin_mutex. Without such HW support, it behaves like a spin_mutex.
It should be used for locking short critical sections where the lock is It should be used for locking short critical sections where the lock is
contended but the data it protects are not. If zero-initialized, the contended but the data it protects are not. If zero-initialized, the
mutex is considered unheld. mutex is considered unheld.
@ingroup synchronization */ @ingroup synchronization */
#if ( __TBB_x86_32 || __TBB_x86_64 ) #if ( __TBB_x86_32 || __TBB_x86_64 )
typedef interface7::internal::padded_mutex<interface7::internal::x86_elidin g_mutex> speculative_spin_mutex; typedef interface7::internal::padded_mutex<interface7::internal::x86_elidin g_mutex,false> speculative_spin_mutex;
#else #else
typedef interface7::internal::padded_mutex<spin_mutex> speculative_spin_mut ex; typedef interface7::internal::padded_mutex<spin_mutex,false> speculative_sp in_mutex;
#endif #endif
__TBB_DEFINE_PROFILING_SET_NAME(speculative_spin_mutex) __TBB_DEFINE_PROFILING_SET_NAME(speculative_spin_mutex)
} // namespace tbb } // namespace tbb
#endif /* __TBB_spin_mutex_H */ #endif /* __TBB_spin_mutex_H */
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 spin_rw_mutex.h   spin_rw_mutex.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_spin_rw_mutex_H #ifndef __TBB_spin_rw_mutex_H
#define __TBB_spin_rw_mutex_H #define __TBB_spin_rw_mutex_H
#include "tbb_stddef.h" #include "tbb_stddef.h"
#include "tbb_machine.h" #include "tbb_machine.h"
#include "tbb_profiling.h" #include "tbb_profiling.h"
#include "internal/_mutex_padding.h"
namespace tbb { namespace tbb {
class spin_rw_mutex_v3; class spin_rw_mutex_v3;
typedef spin_rw_mutex_v3 spin_rw_mutex; typedef spin_rw_mutex_v3 spin_rw_mutex;
//! Fast, unfair, spinning reader-writer lock with backoff and writer-prefe rence //! Fast, unfair, spinning reader-writer lock with backoff and writer-prefe rence
/** @ingroup synchronization */ /** @ingroup synchronization */
class spin_rw_mutex_v3 { class spin_rw_mutex_v3 {
//! @cond INTERNAL //! @cond INTERNAL
skipping to change at line 164 skipping to change at line 164
__TBB_ASSERT( !mutex, "holding mutex already" ); __TBB_ASSERT( !mutex, "holding mutex already" );
bool result; bool result;
is_writer = write; is_writer = write;
result = write? m.internal_try_acquire_writer() result = write? m.internal_try_acquire_writer()
: m.internal_try_acquire_reader(); : m.internal_try_acquire_reader();
if( result ) if( result )
mutex = &m; mutex = &m;
return result; return result;
} }
#if TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX
// helper methods for speculation-based spin_rw_mutex
spin_rw_mutex *__internal_get_mutex() {
return mutex;
}
// have to be able to "NULL"-ify the mutex
void __internal_set_mutex(spin_rw_mutex* m) {
mutex = m;
}
void __internal_set_writer(bool flag=true) {
is_writer = flag;
}
#endif /* TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX */
protected: protected:
//! The pointer to the current mutex that is held, or NULL if no mu tex is held. //! The pointer to the current mutex that is held, or NULL if no mu tex is held.
spin_rw_mutex* mutex; spin_rw_mutex* mutex;
//! If mutex!=NULL, then is_writer is true if holding a writer lock , false if holding a reader lock. //! If mutex!=NULL, then is_writer is true if holding a writer lock , false if holding a reader lock.
/** Not defined if not holding a lock. */ /** Not defined if not holding a lock. */
bool is_writer; bool is_writer;
}; };
// Mutex traits // Mutex traits
static const bool is_rw_mutex = true; static const bool is_rw_mutex = true;
skipping to change at line 207 skipping to change at line 223
// Methods for reader locks that resemble ISO C++0x compatibility metho ds. // Methods for reader locks that resemble ISO C++0x compatibility metho ds.
//! Acquire reader lock //! Acquire reader lock
void lock_read() {internal_acquire_reader();} void lock_read() {internal_acquire_reader();}
//! Try acquiring reader lock (non-blocking) //! Try acquiring reader lock (non-blocking)
/** Return true if reader lock acquired; false otherwise. */ /** Return true if reader lock acquired; false otherwise. */
bool try_lock_read() {return internal_try_acquire_reader();} bool try_lock_read() {return internal_try_acquire_reader();}
private: protected:
typedef intptr_t state_t; typedef intptr_t state_t;
static const state_t WRITER = 1; static const state_t WRITER = 1;
static const state_t WRITER_PENDING = 2; static const state_t WRITER_PENDING = 2;
static const state_t READERS = ~(WRITER | WRITER_PENDING); static const state_t READERS = ~(WRITER | WRITER_PENDING);
static const state_t ONE_READER = 4; static const state_t ONE_READER = 4;
static const state_t BUSY = WRITER | READERS; static const state_t BUSY = WRITER | READERS;
//! State of lock //! State of lock
/** Bit 0 = writer is holding lock /** Bit 0 = writer is holding lock
Bit 1 = request by a writer to acquire lock (hint to readers to wai t) Bit 1 = request by a writer to acquire lock (hint to readers to wai t)
Bit 2..N = number of readers holding lock */ Bit 2..N = number of readers holding lock */
state_t state; state_t state;
private:
void __TBB_EXPORTED_METHOD internal_construct(); void __TBB_EXPORTED_METHOD internal_construct();
}; };
__TBB_DEFINE_PROFILING_SET_NAME(spin_rw_mutex) __TBB_DEFINE_PROFILING_SET_NAME(spin_rw_mutex)
} // namespace tbb } // namespace tbb
#if TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX
#if __TBB_TSX_AVAILABLE
#include "internal/_x86_rtm_rw_mutex_impl.h"
#endif
namespace tbb {
namespace interface7 {
//! A cross-platform spin reader/writer mutex with speculative lock acquisi
tion.
/** On platforms with proper HW support, this lock may speculatively execut
e
its critical sections, using HW mechanisms to detect real data races an
d
ensure atomicity of the critical sections. In particular, it uses
Intel(R) Transactional Synchronization Extensions (Intel(R) TSX).
Without such HW support, it behaves like a spin_rw_mutex.
It should be used for locking short critical sections where the lock is
contended but the data it protects are not.
@ingroup synchronization */
#if __TBB_TSX_AVAILABLE
typedef interface7::internal::padded_mutex<tbb::interface7::internal::x86_r
tm_rw_mutex,true> speculative_spin_rw_mutex;
#else
typedef interface7::internal::padded_mutex<tbb::spin_rw_mutex,true> specula
tive_spin_rw_mutex;
#endif
} // namespace interface7
using interface7::speculative_spin_rw_mutex;
__TBB_DEFINE_PROFILING_SET_NAME(speculative_spin_rw_mutex)
} // namespace tbb
#endif /* TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX */
#endif /* __TBB_spin_rw_mutex_H */ #endif /* __TBB_spin_rw_mutex_H */
 End of changes. 7 change blocks. 
2 lines changed or deleted 50 lines changed or added


 tbb_allocator.h   tbb_allocator.h 
skipping to change at line 124 skipping to change at line 124
internal::deallocate_via_handler_v3(p); internal::deallocate_via_handler_v3(p);
} }
//! Largest value for which method allocate might succeed. //! Largest value for which method allocate might succeed.
size_type max_size() const throw() { size_type max_size() const throw() {
size_type max = static_cast<size_type>(-1) / sizeof (value_type); size_type max = static_cast<size_type>(-1) / sizeof (value_type);
return (max > 0 ? max : 1); return (max > 0 ? max : 1);
} }
//! Copy-construct value at location pointed to by p. //! Copy-construct value at location pointed to by p.
#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESEN T #if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
template<typename U, typename... Args> template<typename U, typename... Args>
void construct(U *p, Args&&... args) void construct(U *p, Args&&... args)
#if __TBB_CPP11_STD_FORWARD_BROKEN #if __TBB_CPP11_STD_FORWARD_BROKEN
{ ::new((void *)p) U((args)...); } { ::new((void *)p) U((args)...); }
#else #else
{ ::new((void *)p) U(std::forward<Args>(args)...); } { ::new((void *)p) U(std::forward<Args>(args)...); }
#endif #endif
#else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_P RESENT #else // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);} void construct( pointer p, const value_type& value ) {::new((void*)(p)) value_type(value);}
#endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_ PRESENT #endif // __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
//! Destroy value at location pointed to by p. //! Destroy value at location pointed to by p.
void destroy( pointer p ) {p->~value_type();} void destroy( pointer p ) {p->~value_type();}
//! Returns current allocator //! Returns current allocator
static malloc_type allocator_type() { static malloc_type allocator_type() {
return internal::is_malloc_used_v3() ? standard : scalable; return internal::is_malloc_used_v3() ? standard : scalable;
} }
}; };
 End of changes. 3 change blocks. 
3 lines changed or deleted 3 lines changed or added


 tbb_config.h   tbb_config.h 
skipping to change at line 154 skipping to change at line 154
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_C XX0X__ && __TBB_GCC_VERSION >= 40404 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) #define __TBB_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40404 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
#define __TBB_MAKE_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40600) #define __TBB_MAKE_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40600)
#define __TBB_STATIC_ASSERT_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40300) #define __TBB_STATIC_ASSERT_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40300)
#define __TBB_CPP11_TUPLE_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40300) #define __TBB_CPP11_TUPLE_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40300)
#define __TBB_INITIALIZER_LISTS_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40400) #define __TBB_INITIALIZER_LISTS_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40400)
/** gcc seems have to support constexpr from 4.4 but tests in (test_ato mic) seeming reasonable fail to compile prior 4.6**/ /** gcc seems have to support constexpr from 4.4 but tests in (test_ato mic) seeming reasonable fail to compile prior 4.6**/
#define __TBB_CONSTEXPR_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40400) #define __TBB_CONSTEXPR_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40400)
#define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40400) #define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40400)
#elif _MSC_VER #elif _MSC_VER
#define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 0 #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (_MSC_VER >= 1800)
#define __TBB_CPP11_RVALUE_REF_PRESENT (_MSC_VER >= 1600) #define __TBB_CPP11_RVALUE_REF_PRESENT (_MSC_VER >= 1600)
#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_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 #define __TBB_INITIALIZER_LISTS_PRESENT (_MSC_VER >= 1800)
#define __TBB_CONSTEXPR_PRESENT 0 #define __TBB_CONSTEXPR_PRESENT 0
#define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT 0 #define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (_MSC_VER >= 1800)
#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_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 #define __TBB_INITIALIZER_LISTS_PRESENT 0
#define __TBB_CONSTEXPR_PRESENT 0 #define __TBB_CONSTEXPR_PRESENT 0
#define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT 0 #define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT 0
skipping to change at line 206 skipping to change at line 206
#if __TBB_GCC_VERSION >= 40306 || __INTEL_COMPILER >= 1200 #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 >= 1200 #if __INTEL_COMPILER >= 1200
/** built-in C++11 style atomics available in ICC since 12.0 **/ /** built-in C++11 style atomics available in ICC since 12.0 **/
#define __TBB_ICC_BUILTIN_ATOMICS_PRESENT 1 #define __TBB_ICC_BUILTIN_ATOMICS_PRESENT 1
#endif #endif
#if __MIC__ || __MIC2__
#define __TBB_DEFINE_MIC 1
#endif
#define __TBB_TSX_INTRINSICS_PRESENT ( (__TBB_GCC_VERSION>=40800) || (_MSC_
VER>=1700) || (__INTEL_COMPILER>=1300) ) && !__TBB_DEFINE_MIC
/** 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 244 skipping to change at line 250
#endif /* TBB_USE_THREADING_TOOLS */ #endif /* TBB_USE_THREADING_TOOLS */
#ifndef TBB_USE_PERFORMANCE_WARNINGS #ifndef TBB_USE_PERFORMANCE_WARNINGS
#ifdef TBB_PERFORMANCE_WARNINGS #ifdef TBB_PERFORMANCE_WARNINGS
#define TBB_USE_PERFORMANCE_WARNINGS TBB_PERFORMANCE_WARNINGS #define TBB_USE_PERFORMANCE_WARNINGS TBB_PERFORMANCE_WARNINGS
#else #else
#define TBB_USE_PERFORMANCE_WARNINGS TBB_USE_DEBUG #define TBB_USE_PERFORMANCE_WARNINGS TBB_USE_DEBUG
#endif /* TBB_PEFORMANCE_WARNINGS */ #endif /* TBB_PEFORMANCE_WARNINGS */
#endif /* TBB_USE_PERFORMANCE_WARNINGS */ #endif /* TBB_USE_PERFORMANCE_WARNINGS */
#if __MIC__ || __MIC2__
#define __TBB_DEFINE_MIC 1
#endif
#if !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) && !defined(__SUNPRO_CC) || defined(_XBOX) #if !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) && !defined(__SUNPRO_CC) || defined(_XBOX)
#if TBB_USE_EXCEPTIONS #if TBB_USE_EXCEPTIONS
#error Compilation settings do not support exception handling. Plea se do not set TBB_USE_EXCEPTIONS macro or set it to 0. #error Compilation settings do not support exception handling. Plea se do not set TBB_USE_EXCEPTIONS macro or set it to 0.
#elif !defined(TBB_USE_EXCEPTIONS) #elif !defined(TBB_USE_EXCEPTIONS)
#define TBB_USE_EXCEPTIONS 0 #define TBB_USE_EXCEPTIONS 0
#endif #endif
#elif !defined(TBB_USE_EXCEPTIONS) #elif !defined(TBB_USE_EXCEPTIONS)
#if __TBB_DEFINE_MIC #if __TBB_DEFINE_MIC
#define TBB_USE_EXCEPTIONS 0 #define TBB_USE_EXCEPTIONS 0
#else #else
skipping to change at line 346 skipping to change at line 348
#define __TBB_RECYCLE_TO_ENQUEUE __TBB_BUILD // keep non-official #define __TBB_RECYCLE_TO_ENQUEUE __TBB_BUILD // keep non-official
#if !__TBB_SCHEDULER_OBSERVER #if !__TBB_SCHEDULER_OBSERVER
#error TBB_PREVIEW_TASK_ARENA requires __TBB_SCHEDULER_OBSERVER to be enabled #error TBB_PREVIEW_TASK_ARENA requires __TBB_SCHEDULER_OBSERVER to be enabled
#endif #endif
#endif /* __TBB_TASK_ARENA */ #endif /* __TBB_TASK_ARENA */
#if !defined(TBB_PREVIEW_LOCAL_OBSERVER) && __TBB_BUILD && __TBB_SCHEDULER_ OBSERVER #if !defined(TBB_PREVIEW_LOCAL_OBSERVER) && __TBB_BUILD && __TBB_SCHEDULER_ OBSERVER
#define TBB_PREVIEW_LOCAL_OBSERVER 1 #define TBB_PREVIEW_LOCAL_OBSERVER 1
#endif /* TBB_PREVIEW_LOCAL_OBSERVER */ #endif /* TBB_PREVIEW_LOCAL_OBSERVER */
#ifndef __TBB_ITT_STRUCTURE_API
#define __TBB_ITT_STRUCTURE_API ( !__TBB_DEFINE_MIC && (__TBB_CPF_BUILD ||
TBB_PREVIEW_FLOW_GRAPH_TRACE) )
#endif
#if TBB_USE_EXCEPTIONS && !__TBB_TASK_GROUP_CONTEXT #if TBB_USE_EXCEPTIONS && !__TBB_TASK_GROUP_CONTEXT
#error TBB_USE_EXCEPTIONS requires __TBB_TASK_GROUP_CONTEXT to be enabl ed #error TBB_USE_EXCEPTIONS requires __TBB_TASK_GROUP_CONTEXT to be enabl ed
#endif #endif
#ifndef __TBB_TASK_PRIORITY #ifndef __TBB_TASK_PRIORITY
#define __TBB_TASK_PRIORITY (!__TBB_CPF_BUILD&&__TBB_TASK_GROUP_CONTEXT ) // TODO: it will be enabled for CPF in the next versions #define __TBB_TASK_PRIORITY (!__TBB_CPF_BUILD&&__TBB_TASK_GROUP_CONTEXT ) // TODO: it will be enabled for CPF in the next versions
#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
skipping to change at line 387 skipping to change at line 393
#ifdef _VARIADIC_MAX #ifdef _VARIADIC_MAX
#define __TBB_VARIADIC_MAX _VARIADIC_MAX #define __TBB_VARIADIC_MAX _VARIADIC_MAX
#else #else
#if _MSC_VER >= 1700 #if _MSC_VER >= 1700
#define __TBB_VARIADIC_MAX 5 /* current VS11 setting, may change. */ #define __TBB_VARIADIC_MAX 5 /* current VS11 setting, may change. */
#else #else
#define __TBB_VARIADIC_MAX 10 #define __TBB_VARIADIC_MAX 10
#endif #endif
#endif #endif
#if !defined(TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX)
#define TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX __TBB_CPF_BUILD
#endif /* TBB_PREVIEW_SPECULATIVE_SPIN_RW_MUTEX */
/** __TBB_WIN8UI_SUPPORT enables support of New Windows*8 Store Apps and li mit a possibility to load /** __TBB_WIN8UI_SUPPORT enables support of New Windows*8 Store Apps and li mit a possibility to load
shared libraries at run time only from application container **/ shared libraries at run time only from application container **/
#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP #if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP
#define __TBB_WIN8UI_SUPPORT 1 #define __TBB_WIN8UI_SUPPORT 1
#else #else
#define __TBB_WIN8UI_SUPPORT 0 #define __TBB_WIN8UI_SUPPORT 0
#endif #endif
// Define preprocessor symbols used to determine architecture // Define preprocessor symbols used to determine architecture
#if _WIN32||_WIN64 #if _WIN32||_WIN64
skipping to change at line 419 skipping to change at line 429
# define __TBB_x86_64 1 # define __TBB_x86_64 1
# elif __ia64__ # elif __ia64__
# define __TBB_ipf 1 # define __TBB_ipf 1
# elif __i386__||__i386 // __i386 is for Sun OS # elif __i386__||__i386 // __i386 is for Sun OS
# define __TBB_x86_32 1 # define __TBB_x86_32 1
# else # else
# define __TBB_generic_arch 1 # define __TBB_generic_arch 1
# endif # endif
#endif #endif
#define __TBB_TSX_AVAILABLE (__TBB_x86_32 || __TBB_x86_64) && !__TBB_DEFIN
E_MIC
/** 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 #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, /** 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 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). **/ these atomic operations are used (such as in unit test test_atomic. exe). **/
skipping to change at line 552 skipping to change at line 564
#endif #endif
/** End of __TBB_XXX_BROKEN macro section **/ /** End of __TBB_XXX_BROKEN macro section **/
#if defined(_MSC_VER) && _MSC_VER>=1500 && !defined(__INTEL_COMPILER) #if defined(_MSC_VER) && _MSC_VER>=1500 && !defined(__INTEL_COMPILER)
// A macro to suppress erroneous or benign "unreachable code" MSVC warn ing (4702) // A macro to suppress erroneous or benign "unreachable code" MSVC warn ing (4702)
#define __TBB_MSVC_UNREACHABLE_CODE_IGNORED 1 #define __TBB_MSVC_UNREACHABLE_CODE_IGNORED 1
#endif #endif
#define __TBB_ATOMIC_CTORS (__TBB_CONSTEXPR_PRESENT && __TBB_DEFAULTED_ AND_DELETED_FUNC_PRESENT && (!__TBB_ZERO_INIT_WITH_DEFAULTED_CTOR_BROKEN)) #define __TBB_ATOMIC_CTORS (__TBB_CONSTEXPR_PRESENT && __TBB_DEFAULTED_ AND_DELETED_FUNC_PRESENT && (!__TBB_ZERO_INIT_WITH_DEFAULTED_CTOR_BROKEN))
#define __TBB_ALLOCATOR_CONSTRUCT_VARIADIC (__TBB_CPP11_VARIADIC_TEMPL ATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT)
#endif /* __TBB_tbb_config_H */ #endif /* __TBB_tbb_config_H */
 End of changes. 9 change blocks. 
7 lines changed or deleted 23 lines changed or added


 tbb_profiling.h   tbb_profiling.h 
skipping to change at line 32 skipping to change at line 32
this file and link it with other files to produce an executable, this this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered b y invalidate any other reasons why the executable file might be covered b y
the GNU General Public License. the GNU General Public License.
*/ */
#ifndef __TBB_profiling_H #ifndef __TBB_profiling_H
#define __TBB_profiling_H #define __TBB_profiling_H
namespace tbb {
namespace internal {
//
// This is not under __TBB_ITT_STRUCTURE_API because these values a
re used directly in flow_graph.h.
//
// include list of index names
#define TBB_STRING_RESOURCE(index_name,str) index_name,
enum string_index {
#include "internal/_tbb_strings.h"
NUM_STRINGS
};
#undef TBB_STRING_RESOURCE
enum itt_relation
{
__itt_relation_is_unknown = 0,
__itt_relation_is_dependent_on, /**< "A is dependent on B"
means that A cannot start until B completes */
__itt_relation_is_sibling_of, /**< "A is sibling of B" me
ans that A and B were created as a group */
__itt_relation_is_parent_of, /**< "A is parent of B" mea
ns that A created B */
__itt_relation_is_continuation_of, /**< "A is continuation of
B" means that A assumes the dependencies of B */
__itt_relation_is_child_of, /**< "A is child of B" mean
s that A was created by B (inverse of is_parent_of) */
__itt_relation_is_continued_by, /**< "A is continued by B"
means that B assumes the dependencies of A (inverse of is_continuation_of)
*/
__itt_relation_is_predecessor_to /**< "A is predecessor to B
" means that B cannot start until A completes (inverse of is_dependent_on)
*/
};
}
}
// Check if the tools support is enabled // Check if the tools support is enabled
#if (_WIN32||_WIN64||__linux__) && !__MINGW32__ && TBB_USE_THREADING_TOOLS #if (_WIN32||_WIN64||__linux__) && !__MINGW32__ && TBB_USE_THREADING_TOOLS
#if _WIN32||_WIN64 #if _WIN32||_WIN64
#include <stdlib.h> /* mbstowcs_s */ #include <stdlib.h> /* mbstowcs_s */
#endif #endif
#include "tbb_stddef.h" #include "tbb_stddef.h"
namespace tbb { namespace tbb {
namespace internal { namespace internal {
#if _WIN32||_WIN64 #if _WIN32||_WIN64
void __TBB_EXPORTED_FUNC itt_set_sync_name_v3( void *obj, const wch ar_t* name ); void __TBB_EXPORTED_FUNC itt_set_sync_name_v3( void *obj, const wch ar_t* name );
inline size_t multibyte_to_widechar( wchar_t* wcs, const char* mbs, size_t bufsize) { inline size_t multibyte_to_widechar( wchar_t* wcs, const char* mbs, size_t bufsize) {
#if _MSC_VER>=1400 #if _MSC_VER>=1400
size_t len; size_t len;
mbstowcs_s( &len, wcs, bufsize, mbs, _TRUNCATE ); mbstowcs_s( &len, wcs, bufsize, mbs, _TRUNCATE );
return len; // mbstowcs_s counts null terminator return len; // mbstowcs_s counts null terminator
#else #else
size_t len = mbstowcs( wcs, mbs, bufsize ); size_t len = mbstowcs( wcs, mbs, bufsize );
if(wcs && len!=size_t(-1) ) if(wcs && len!=size_t(-1) )
skipping to change at line 111 skipping to change at line 142
#endif /* !WIN */ #endif /* !WIN */
#endif /* no tools support */ #endif /* no tools support */
#include "atomic.h" #include "atomic.h"
// Need these to work regardless of tools support // Need these to work regardless of tools support
namespace tbb { namespace tbb {
namespace internal { namespace internal {
enum notify_type {prepare=0, cancel, acquired, releasing}; enum notify_type {prepare=0, cancel, acquired, releasing};
const uintptr_t NUM_NOTIFY_TYPES = 4; // set to # elements in enum above const uintptr_t NUM_NOTIFY_TYPES = 4; // set to # elements in enum above
void __TBB_EXPORTED_FUNC call_itt_notify_v5(int t, void *ptr); void __TBB_EXPORTED_FUNC call_itt_notify_v5(int t, void *ptr);
void __TBB_EXPORTED_FUNC itt_store_pointer_with_release_v3(void *ds t, void *src); void __TBB_EXPORTED_FUNC itt_store_pointer_with_release_v3(void *ds t, void *src);
void* __TBB_EXPORTED_FUNC itt_load_pointer_with_acquire_v3(const vo id *src); void* __TBB_EXPORTED_FUNC itt_load_pointer_with_acquire_v3(const vo id *src);
void* __TBB_EXPORTED_FUNC itt_load_pointer_v3( const void* src ); void* __TBB_EXPORTED_FUNC itt_load_pointer_v3( const void* src );
#if __TBB_ITT_STRUCTURE_API
enum itt_domain_enum { ITT_DOMAIN_FLOW=0 };
void __TBB_EXPORTED_FUNC itt_make_task_group_v7( itt_domain_enum do
main, void *group, unsigned long long group_extra,
void *parent, unsi
gned long long parent_extra, string_index name_index );
void __TBB_EXPORTED_FUNC itt_metadata_str_add_v7( itt_domain_enum d
omain, void *addr, unsigned long long addr_extra,
string_index key,
const char *value );
void __TBB_EXPORTED_FUNC itt_relation_add_v7( itt_domain_enum domai
n, void *addr0, unsigned long long addr0_extra,
itt_relation relation
, void *addr1, unsigned long long addr1_extra );
void __TBB_EXPORTED_FUNC itt_task_begin_v7( itt_domain_enum domain,
void *task, unsigned long long task_extra,
void *parent, unsigned
long long parent_extra, string_index name_index );
void __TBB_EXPORTED_FUNC itt_task_end_v7( itt_domain_enum domain );
#endif // __TBB_ITT_STRUCTURE_API
// two template arguments are to workaround /Wp64 warning with tbb: :atomic specialized for unsigned type // two template arguments are to workaround /Wp64 warning with tbb: :atomic specialized for unsigned type
template <typename T, typename U> template <typename T, typename U>
inline void itt_store_word_with_release(tbb::atomic<T>& dst, U src) { inline void itt_store_word_with_release(tbb::atomic<T>& dst, U src) {
#if TBB_USE_THREADING_TOOLS #if TBB_USE_THREADING_TOOLS
// This assertion should be replaced with static_assert // This assertion should be replaced with static_assert
__TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-si zed."); __TBB_ASSERT(sizeof(T) == sizeof(void *), "Type must be word-si zed.");
itt_store_pointer_with_release_v3(&dst, (void *)uintptr_t(src)) ; itt_store_pointer_with_release_v3(&dst, (void *)uintptr_t(src)) ;
#else #else
dst = src; dst = src;
skipping to change at line 198 skipping to change at line 243
return (T)itt_load_pointer_v3(&src); return (T)itt_load_pointer_v3(&src);
#else #else
return src; return src;
#endif #endif
} }
#if TBB_USE_THREADING_TOOLS #if TBB_USE_THREADING_TOOLS
inline void call_itt_notify(notify_type t, void *ptr) { inline void call_itt_notify(notify_type t, void *ptr) {
call_itt_notify_v5((int)t, ptr); call_itt_notify_v5((int)t, ptr);
} }
#else #else
inline void call_itt_notify(notify_type /*t*/, void * /*ptr*/) {} inline void call_itt_notify(notify_type /*t*/, void * /*ptr*/) {}
#endif // TBB_USE_THREADING_TOOLS #endif // TBB_USE_THREADING_TOOLS
#if __TBB_ITT_STRUCTURE_API
inline void itt_make_task_group( itt_domain_enum domain, void *grou
p, unsigned long long group_extra,
void *parent, unsigned long long p
arent_extra, string_index name_index ) {
itt_make_task_group_v7( domain, group, group_extra, parent, par
ent_extra, name_index );
}
inline void itt_metadata_str_add( itt_domain_enum domain, void *add
r, unsigned long long addr_extra,
string_index key, const char *val
ue ) {
itt_metadata_str_add_v7( domain, addr, addr_extra, key, value )
;
}
inline void itt_relation_add( itt_domain_enum domain, void *addr0,
unsigned long long addr0_extra,
itt_relation relation, void *addr1, u
nsigned long long addr1_extra ) {
itt_relation_add_v7( domain, addr0, addr0_extra, relation, addr
1, addr1_extra );
}
inline void itt_task_begin( itt_domain_enum domain, void *task, uns
igned long long task_extra,
void *parent, unsig
ned long long parent_extra, string_index name_index ) {
itt_task_begin_v7( domain, task, task_extra, parent, parent_ext
ra, name_index );
}
inline void itt_task_end( itt_domain_enum domain ) {
itt_task_end_v7( domain );
}
#endif // __TBB_ITT_STRUCTURE_API
} // namespace internal } // namespace internal
} // namespace tbb } // namespace tbb
#endif /* __TBB_profiling_H */ #endif /* __TBB_profiling_H */
 End of changes. 7 change blocks. 
0 lines changed or deleted 103 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 2 #define TBB_VERSION_MINOR 2
// Engineering-focused interface version // Engineering-focused interface version
#define TBB_INTERFACE_VERSION 7001 #define TBB_INTERFACE_VERSION 7002
#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

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