_concurrent_queue_impl.h   _concurrent_queue_impl.h 
skipping to change at line 1017 skipping to change at line 1017
typedef concurrent_queue_iterator_base_v3 concurrent_queue_iterator_base; typedef concurrent_queue_iterator_base_v3 concurrent_queue_iterator_base;
//! Meets requirements of a forward iterator for STL. //! Meets requirements of a forward iterator for STL.
/** Value is either the T or const T type of the container. /** Value is either the T or const T type of the container.
@ingroup containers */ @ingroup containers */
template<typename Container, typename Value> template<typename Container, typename Value>
class concurrent_queue_iterator: public concurrent_queue_iterator_base, class concurrent_queue_iterator: public concurrent_queue_iterator_base,
public std::iterator<std::forward_iterator_tag,Value> { public std::iterator<std::forward_iterator_tag,Value> {
#if !defined(_MSC_VER) || defined(__INTEL_COMPILER) #if !__TBB_TEMPLATE_FRIENDS_BROKEN
template<typename T, class A> template<typename T, class A>
friend class ::tbb::concurrent_bounded_queue; friend class ::tbb::concurrent_bounded_queue;
#else #else
public: // workaround for MSVC public:
#endif #endif
//! Construct iterator pointing to head of queue. //! Construct iterator pointing to head of queue.
concurrent_queue_iterator( const concurrent_queue_base_v3& queue ) : concurrent_queue_iterator( const concurrent_queue_base_v3& queue ) :
concurrent_queue_iterator_base_v3(queue,__TBB_offsetof(concurrent_q ueue_base_v3::padded_page<Value>,last)) concurrent_queue_iterator_base_v3(queue,__TBB_offsetof(concurrent_q ueue_base_v3::padded_page<Value>,last))
{ {
} }
public: public:
concurrent_queue_iterator() {} concurrent_queue_iterator() {}
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 _concurrent_unordered_impl.h   _concurrent_unordered_impl.h 
skipping to change at line 259 skipping to change at line 259
// in the hash table to quickly index into the right subsection of the split-ordered list. // in the hash table to quickly index into the right subsection of the split-ordered list.
bool is_dummy() const { bool is_dummy() const {
return (my_order_key & 0x1) == 0; return (my_order_key & 0x1) == 0;
} }
nodeptr_t my_next; // Next element in the list nodeptr_t my_next; // Next element in the list
value_type my_element; // Element storage value_type my_element; // Element storage
sokey_t my_order_key; // Order key for this element sokey_t my_order_key; // Order key for this element
}; };
// Allocate a new node with the given order key; used to allocate dummy
nodes
nodeptr_t create_node(sokey_t order_key) {
nodeptr_t pnode = my_node_allocator.allocate(1);
pnode->init(order_key);
return (pnode);
}
// Allocate a new node with the given order key and value // Allocate a new node with the given order key and value
nodeptr_t create_node(sokey_t order_key, const T &value) { template<typename Arg>
nodeptr_t create_node(sokey_t order_key, __TBB_FORWARDING_REF(Arg) t){
nodeptr_t pnode = my_node_allocator.allocate(1); nodeptr_t pnode = my_node_allocator.allocate(1);
//TODO: use RAII scoped guard instead of explicit catch
__TBB_TRY { __TBB_TRY {
new(static_cast<void*>(&pnode->my_element)) T(value); new(static_cast<void*>(&pnode->my_element)) T(tbb::internal::fo rward<Arg>(t));
pnode->init(order_key); pnode->init(order_key);
} __TBB_CATCH(...) { } __TBB_CATCH(...) {
my_node_allocator.deallocate(pnode, 1); my_node_allocator.deallocate(pnode, 1);
__TBB_RETHROW(); __TBB_RETHROW();
} }
return (pnode); return (pnode);
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT // Allocate a new node with the given parameters for constructing value
//TODO: try to combine both implementations using poor man forward template<typename __TBB_PARAMETER_PACK Args>
//TODO: use RAII scoped guard instead of explicit catch nodeptr_t create_node_v( __TBB_FORWARDING_REF(Args) __TBB_PARAMETER_PAC
// Allocate a new node with the given order key and value K args){
nodeptr_t create_node(sokey_t order_key, T &&value) {
nodeptr_t pnode = my_node_allocator.allocate(1); nodeptr_t pnode = my_node_allocator.allocate(1);
//TODO: use RAII scoped guard instead of explicit catch
__TBB_TRY { __TBB_TRY {
new(static_cast<void*>(&pnode->my_element)) T(std::move(value)) new(static_cast<void*>(&pnode->my_element)) T(__TBB_PACK_EXPANS
; ION(tbb::internal::forward<Args>(args)));
pnode->init(order_key);
} __TBB_CATCH(...) { } __TBB_CATCH(...) {
my_node_allocator.deallocate(pnode, 1); my_node_allocator.deallocate(pnode, 1);
__TBB_RETHROW(); __TBB_RETHROW();
} }
return (pnode); return (pnode);
} }
#endif //__TBB_CPP11_RVALUE_REF_PRESENT
// Allocate a new node with the given order key; used to allocate dummy
nodes
nodeptr_t create_node(sokey_t order_key) {
nodeptr_t pnode = my_node_allocator.allocate(1);
pnode->init(order_key);
return (pnode);
}
split_ordered_list(allocator_type a = allocator_type()) split_ordered_list(allocator_type a = allocator_type())
: my_node_allocator(a), my_element_count(0) : my_node_allocator(a), my_element_count(0)
{ {
// Immediately allocate a dummy node with order key of 0. This node // Immediately allocate a dummy node with order key of 0. This node
// will always be the head of the list. // will always be the head of the list.
my_head = create_node(0); my_head = create_node(sokey_t(0));
} }
~split_ordered_list() ~split_ordered_list()
{ {
// Clear the list // Clear the list
clear(); clear();
// Remove the head element which is not cleared by clear() // Remove the head element which is not cleared by clear()
nodeptr_t pnode = my_head; nodeptr_t pnode = my_head;
my_head = NULL; my_head = NULL;
skipping to change at line 482 skipping to change at line 481
return const_iterator(it.get_node_ptr(), this); return const_iterator(it.get_node_ptr(), this);
} }
// Erase an element using the allocator // Erase an element using the allocator
void destroy_node(nodeptr_t pnode) { void destroy_node(nodeptr_t pnode) {
if (!pnode->is_dummy()) my_node_allocator.destroy(pnode); if (!pnode->is_dummy()) my_node_allocator.destroy(pnode);
my_node_allocator.deallocate(pnode, 1); my_node_allocator.deallocate(pnode, 1);
} }
// Try to insert a new element in the list. If insert fails, return the // Try to insert a new element in the list.
node that // If insert fails, return the node that was inserted instead.
// was inserted instead. static nodeptr_t try_insert_atomic(nodeptr_t previous, nodeptr_t new_no
nodeptr_t try_insert(nodeptr_t previous, nodeptr_t new_node, nodeptr_t de, nodeptr_t current_node) {
current_node) {
new_node->my_next = current_node; new_node->my_next = current_node;
return previous->atomic_set_next(new_node, current_node); return previous->atomic_set_next(new_node, current_node);
} }
// Insert a new element between passed in iterators // Insert a new element between passed in iterators
std::pair<iterator, bool> try_insert(raw_iterator it, raw_iterator next , const value_type &value, sokey_t order_key, size_type *new_count) std::pair<iterator, bool> try_insert(raw_iterator it, raw_iterator next , nodeptr_t pnode, size_type *new_count)
{ {
nodeptr_t pnode = create_node(order_key, value); nodeptr_t inserted_node = try_insert_atomic(it.get_node_ptr(), pnod
nodeptr_t inserted_node = try_insert(it.get_node_ptr(), pnode, next e, next.get_node_ptr());
.get_node_ptr());
if (inserted_node == pnode) if (inserted_node == pnode)
{ {
// If the insert succeeded, check that the order is correct and increment the element count // If the insert succeeded, check that the order is correct and increment the element count
check_range(it, next); check_range(it, next);
*new_count = __TBB_FetchAndAddW((uintptr_t*)&my_element_count, uintptr_t(1)); *new_count = tbb::internal::as_atomic(my_element_count).fetch_a nd_increment();
return std::pair<iterator, bool>(iterator(pnode, this), true); return std::pair<iterator, bool>(iterator(pnode, this), true);
} }
else else
{ {
// If the insert failed (element already there), then delete th
e new one
destroy_node(pnode);
return std::pair<iterator, bool>(end(), false); return std::pair<iterator, bool>(end(), false);
} }
} }
// Insert a new dummy element, starting search at a parent dummy elemen t // Insert a new dummy element, starting search at a parent dummy elemen t
raw_iterator insert_dummy(raw_iterator it, sokey_t order_key) raw_iterator insert_dummy(raw_iterator it, sokey_t order_key)
{ {
raw_iterator last = raw_end(); raw_iterator last = raw_end();
raw_iterator where = it; raw_iterator where = it;
skipping to change at line 534 skipping to change at line 530
{ {
__TBB_ASSERT(it != last, "Invalid head list node"); __TBB_ASSERT(it != last, "Invalid head list node");
// If the head iterator is at the end of the list, or past the point where this dummy // If the head iterator is at the end of the list, or past the point where this dummy
// node needs to be inserted, then try to insert it. // node needs to be inserted, then try to insert it.
if (where == last || get_order_key(where) > order_key) if (where == last || get_order_key(where) > order_key)
{ {
__TBB_ASSERT(get_order_key(it) < order_key, "Invalid node o rder in the list"); __TBB_ASSERT(get_order_key(it) < order_key, "Invalid node o rder in the list");
// Try to insert it in the right place // Try to insert it in the right place
nodeptr_t inserted_node = try_insert(it.get_node_ptr(), dum my_node, where.get_node_ptr()); nodeptr_t inserted_node = try_insert_atomic(it.get_node_ptr (), dummy_node, where.get_node_ptr());
if (inserted_node == dummy_node) if (inserted_node == dummy_node)
{ {
// Insertion succeeded, check the list for order violat ions // Insertion succeeded, check the list for order violat ions
check_range(it, where); check_range(it, where);
return raw_iterator(dummy_node); return raw_iterator(dummy_node);
} }
else else
{ {
// Insertion failed: either dummy node was inserted by another thread, or // Insertion failed: either dummy node was inserted by another thread, or
skipping to change at line 607 skipping to change at line 603
nodeptr_t previous_node = my_head; nodeptr_t previous_node = my_head;
raw_const_iterator begin_iterator = first++; raw_const_iterator begin_iterator = first++;
// Move all elements one by one, including dummy ones // Move all elements one by one, including dummy ones
for (raw_const_iterator it = first; it != last;) for (raw_const_iterator it = first; it != last;)
{ {
nodeptr_t pnode = it.get_node_ptr(); nodeptr_t pnode = it.get_node_ptr();
nodeptr_t dummy_node = pnode->is_dummy() ? create_node(pnode->g et_order_key()) : create_node(pnode->get_order_key(), pnode->my_element); nodeptr_t dummy_node = pnode->is_dummy() ? create_node(pnode->g et_order_key()) : create_node(pnode->get_order_key(), pnode->my_element);
previous_node = try_insert(previous_node, dummy_node, NULL); previous_node = try_insert_atomic(previous_node, dummy_node, NU LL);
__TBB_ASSERT(previous_node != NULL, "Insertion must succeed"); __TBB_ASSERT(previous_node != NULL, "Insertion must succeed");
raw_const_iterator where = it++; raw_const_iterator where = it++;
source.erase_node(get_iterator(begin_iterator), where); source.erase_node(get_iterator(begin_iterator), where);
} }
check_range(); check_range();
} }
private: private:
//Need to setup private fields of split_ordered_list in move constructo r and assignment of concurrent_unordered_base //Need to setup private fields of split_ordered_list in move constructo r and assignment of concurrent_unordered_base
template <typename Traits> template <typename Traits>
skipping to change at line 792 skipping to change at line 788
const nodeptr_t pnode = it.get_node_ptr(); const nodeptr_t pnode = it.get_node_ptr();
nodeptr_t node; nodeptr_t node;
if (pnode->is_dummy()) { if (pnode->is_dummy()) {
node = my_solist.create_node(pnode->get_order_key() ); node = my_solist.create_node(pnode->get_order_key() );
size_type bucket = __TBB_ReverseBits(pnode->get_ord er_key()) % my_number_of_buckets; size_type bucket = __TBB_ReverseBits(pnode->get_ord er_key()) % my_number_of_buckets;
set_bucket(bucket, node); set_bucket(bucket, node);
}else{ }else{
node = my_solist.create_node(pnode->get_order_key() , std::move(pnode->my_element)); node = my_solist.create_node(pnode->get_order_key() , std::move(pnode->my_element));
} }
previous_node = my_solist.try_insert(previous_node, nod e, NULL); previous_node = my_solist.try_insert_atomic(previous_no de, node, NULL);
__TBB_ASSERT(previous_node != NULL, "Insertion of node failed. Concurrent inserts in constructor ?"); __TBB_ASSERT(previous_node != NULL, "Insertion of node failed. Concurrent inserts in constructor ?");
} }
my_solist.check_range(); my_solist.check_range();
} }
} }
clear_buckets_on_exception.dismiss(); clear_buckets_on_exception.dismiss();
} }
#endif //__TBB_CPP11_RVALUE_REF_PRESENT #endif // __TBB_CPP11_RVALUE_REF_PRESENT
concurrent_unordered_base& operator=(const concurrent_unordered_base& r ight) { concurrent_unordered_base& operator=(const concurrent_unordered_base& r ight) {
if (this != &right) if (this != &right)
internal_copy(right); internal_copy(right);
return (*this); return (*this);
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT #if __TBB_CPP11_RVALUE_REF_PRESENT
concurrent_unordered_base& operator=(concurrent_unordered_base&& other) concurrent_unordered_base& operator=(concurrent_unordered_base&& other)
{ {
skipping to change at line 832 skipping to change at line 828
swap(this->my_allocator, other.my_allocator); swap(this->my_allocator, other.my_allocator);
} }
} else { } else {
concurrent_unordered_base moved_copy(std::move(other),this- >my_allocator); concurrent_unordered_base moved_copy(std::move(other),this- >my_allocator);
this->swap(moved_copy); this->swap(moved_copy);
} }
} }
return *this; return *this;
} }
#endif //__TBB_CPP11_RVALUE_REF_PRESENT #endif // __TBB_CPP11_RVALUE_REF_PRESENT
#if __TBB_INITIALIZER_LISTS_PRESENT #if __TBB_INITIALIZER_LISTS_PRESENT
//! assignment operator from initializer_list //! assignment operator from initializer_list
concurrent_unordered_base& operator=(std::initializer_list<value_type> il) concurrent_unordered_base& operator=(std::initializer_list<value_type> il)
{ {
this->clear(); this->clear();
this->insert(il.begin(),il.end()); this->insert(il.begin(),il.end());
return (*this); return (*this);
} }
#endif //# __TBB_INITIALIZER_LISTS_PRESENT #endif // __TBB_INITIALIZER_LISTS_PRESENT
~concurrent_unordered_base() { ~concurrent_unordered_base() {
// Delete all node segments // Delete all node segments
internal_clear(); internal_clear();
} }
public: public:
allocator_type get_allocator() const { allocator_type get_allocator() const {
return my_solist.get_allocator(); return my_solist.get_allocator();
} }
skipping to change at line 993 skipping to change at line 989
// Modifiers // Modifiers
std::pair<iterator, bool> insert(const value_type& value) { std::pair<iterator, bool> insert(const value_type& value) {
return internal_insert(value); return internal_insert(value);
} }
iterator insert(const_iterator, const value_type& value) { iterator insert(const_iterator, const value_type& value) {
// Ignore hint // Ignore hint
return insert(value).first; return insert(value).first;
} }
#if __TBB_CPP11_RVALUE_REF_PRESENT
std::pair<iterator, bool> insert(value_type&& value) {
return internal_insert(std::move(value));
}
iterator insert(const_iterator, value_type&& value) {
// Ignore hint
return insert(std::move(value)).first;
}
#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
template<typename... Args>
std::pair<iterator, bool> emplace(Args&&... args) {
nodeptr_t pnode = my_solist.create_node_v(tbb::internal::forward<Ar
gs>(args)...);
const sokey_t hashed_element_key = (sokey_t) my_hash_compare(get_ke
y(pnode->my_element));
const sokey_t order_key = split_order_key_regular(hashed_element_ke
y);
pnode->init(order_key);
return internal_insert(pnode->my_element, pnode);
}
template<typename... Args>
iterator emplace_hint(const_iterator, Args&&... args) {
// Ignore hint
return emplace(tbb::internal::forward<Args>(args)...).first;
}
#endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
#endif // __TBB_CPP11_RVALUE_REF_PRESENT
template<class Iterator> template<class Iterator>
void insert(Iterator first, Iterator last) { void insert(Iterator first, Iterator last) {
for (Iterator it = first; it != last; ++it) for (Iterator it = first; it != last; ++it)
insert(*it); insert(*it);
} }
#if __TBB_INITIALIZER_LISTS_PRESENT #if __TBB_INITIALIZER_LISTS_PRESENT
//! Insert initializer list //! Insert initializer list
void insert(std::initializer_list<value_type> il) { void insert(std::initializer_list<value_type> il) {
insert(il.begin(), il.end()); insert(il.begin(), il.end());
skipping to change at line 1246 skipping to change at line 1272
for (size_type index = 0; index < pointers_per_table; ++index) for (size_type index = 0; index < pointers_per_table; ++index)
{ {
raw_iterator * iterator_pointer = my_buckets[index]; raw_iterator * iterator_pointer = my_buckets[index];
my_buckets[index] = right.my_buckets[index]; my_buckets[index] = right.my_buckets[index];
right.my_buckets[index] = iterator_pointer; right.my_buckets[index] = iterator_pointer;
} }
} }
//TODO: why not use std::distance? //TODO: why not use std::distance?
// Hash APIs // Hash APIs
size_type internal_distance(const_iterator first, const_iterator last) const static size_type internal_distance(const_iterator first, const_iterator last)
{ {
size_type num = 0; size_type num = 0;
for (const_iterator it = first; it != last; ++it) for (const_iterator it = first; it != last; ++it)
++num; ++num;
return num; return num;
} }
// Insert an element in the hash given its value // Insert an element in the hash given its value
std::pair<iterator, bool> internal_insert(const value_type& value) template< typename ValueType>
std::pair<iterator, bool> internal_insert( __TBB_FORWARDING_REF(ValueTy
pe) value, nodeptr_t pnode = NULL)
{ {
sokey_t order_key = (sokey_t) my_hash_compare(get_key(value)); sokey_t order_key = (sokey_t) my_hash_compare(get_key(value));
size_type bucket = order_key % my_number_of_buckets; size_type bucket = order_key % my_number_of_buckets;
//TODO:refactor the get_bucket related staff into separate function something like aqcuire_bucket(key_type)
// If bucket is empty, initialize it first // If bucket is empty, initialize it first
if (!is_initialized(bucket)) if (!is_initialized(bucket))
init_bucket(bucket); init_bucket(bucket);
size_type new_count = 0; size_type new_count = 0;
order_key = split_order_key_regular(order_key); order_key = split_order_key_regular(order_key);
raw_iterator it = get_bucket(bucket); raw_iterator it = get_bucket(bucket);
raw_iterator last = my_solist.raw_end(); raw_iterator last = my_solist.raw_end();
raw_iterator where = it; raw_iterator where = it;
__TBB_ASSERT(where != last, "Invalid head node"); __TBB_ASSERT(where != last, "Invalid head node");
// First node is a dummy node // First node is a dummy node
++where; ++where;
for (;;) for (;;)
{ {
if (where == last || solist_t::get_order_key(where) > order_key ) if (where == last || solist_t::get_order_key(where) > order_key )
{ {
if (!pnode)
pnode = my_solist.create_node(order_key, tbb::internal
::forward<ValueType>(value));
// Try to insert it in the right place // Try to insert it in the right place
std::pair<iterator, bool> result = my_solist.try_insert(it, where, value, order_key, &new_count); std::pair<iterator, bool> result = my_solist.try_insert(it, where, pnode, &new_count);
if (result.second) if (result.second)
{ {
// Insertion succeeded, adjust the table size, if neede d // Insertion succeeded, adjust the table size, if neede d
adjust_table_size(new_count, my_number_of_buckets); adjust_table_size(new_count, my_number_of_buckets);
return result; return result;
} }
else else
{ {
// Insertion failed: either the same node was inserted by another thread, or // Insertion failed: either the same node was inserted by another thread, or
skipping to change at line 1304 skipping to change at line 1335
// Proceed with the search from the previous location w here order key was // Proceed with the search from the previous location w here order key was
// known to be larger (note: this is legal only because there is no safe // known to be larger (note: this is legal only because there is no safe
// concurrent erase operation supported). // concurrent erase operation supported).
where = it; where = it;
++where; ++where;
continue; continue;
} }
} }
else if (!allow_multimapping && solist_t::get_order_key(where) == order_key && my_hash_compare(get_key(*where), get_key(value)) == 0) else if (!allow_multimapping && solist_t::get_order_key(where) == order_key && my_hash_compare(get_key(*where), get_key(value)) == 0)
{ {
if (pnode)
my_solist.destroy_node(pnode);
// Element already in the list, return it // Element already in the list, return it
return std::pair<iterator, bool>(my_solist.get_iterator(whe re), false); return std::pair<iterator, bool>(my_solist.get_iterator(whe re), false);
} }
// Move the iterator forward // Move the iterator forward
it = where; it = where;
++where; ++where;
} }
} }
skipping to change at line 1351 skipping to change at line 1384
return my_solist.get_iterator(it); return my_solist.get_iterator(it);
} }
} }
return end(); return end();
} }
// Erase an element from the list. This is not a concurrency safe funct ion. // Erase an element from the list. This is not a concurrency safe funct ion.
iterator internal_erase(const_iterator it) iterator internal_erase(const_iterator it)
{ {
key_type key = get_key(*it); //const reference extends lifetime of possible temporary coming fro
m get_key
const key_type& key = get_key(*it);
sokey_t order_key = (sokey_t) my_hash_compare(key); sokey_t order_key = (sokey_t) my_hash_compare(key);
size_type bucket = order_key % my_number_of_buckets; size_type bucket = order_key % my_number_of_buckets;
// If bucket is empty, initialize it first // If bucket is empty, initialize it first
if (!is_initialized(bucket)) if (!is_initialized(bucket))
init_bucket(bucket); init_bucket(bucket);
order_key = split_order_key_regular(order_key); order_key = split_order_key_regular(order_key);
raw_iterator previous = get_bucket(bucket); raw_iterator previous = get_bucket(bucket);
skipping to change at line 1568 skipping to change at line 1602
public: public:
tbb_hash() {} tbb_hash() {}
size_t operator()(const Key& key) const size_t operator()(const Key& key) const
{ {
return tbb_hasher(key); return tbb_hasher(key);
} }
}; };
} // namespace tbb } // namespace tbb
#endif// __TBB__concurrent_unordered_impl_H #endif // __TBB__concurrent_unordered_impl_H
 End of changes. 29 change blocks. 
43 lines changed or deleted 82 lines changed or added


 _flow_graph_impl.h   _flow_graph_impl.h 
skipping to change at line 294 skipping to change at line 294
void remove( T &n ) { void remove( T &n ) {
typename my_mutex_type::scoped_lock lock( my_mutex ); typename my_mutex_type::scoped_lock lock( my_mutex );
for ( size_t i = internal_size(); i != 0; --i ) { for ( size_t i = internal_size(); i != 0; --i ) {
T &s = internal_pop(); T &s = internal_pop();
if ( &s == &n ) return; // only remove one predecessor pe r request if ( &s == &n ) return; // only remove one predecessor pe r request
internal_push(s); internal_push(s);
} }
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<T *> predecessor_vector_type; typedef typename edge_container<T>::edge_list_type predecessor_list _type;
void internal_add_built_predecessor( T &n ) { void internal_add_built_predecessor( T &n ) {
typename my_mutex_type::scoped_lock lock( my_mutex ); typename my_mutex_type::scoped_lock lock( my_mutex );
my_built_predecessors.add_edge(n); my_built_predecessors.add_edge(n);
} }
void internal_delete_built_predecessor( T &n ) { void internal_delete_built_predecessor( T &n ) {
typename my_mutex_type::scoped_lock lock( my_mutex ); typename my_mutex_type::scoped_lock lock( my_mutex );
my_built_predecessors.delete_edge(n); my_built_predecessors.delete_edge(n);
} }
void copy_predecessors( predecessor_vector_type &v) { void copy_predecessors( predecessor_list_type &v) {
typename my_mutex_type::scoped_lock lock( my_mutex ); typename my_mutex_type::scoped_lock lock( my_mutex );
my_built_predecessors.copy_edges(v); my_built_predecessors.copy_edges(v);
} }
size_t predecessor_count() { size_t predecessor_count() {
typename my_mutex_type::scoped_lock lock(my_mutex); typename my_mutex_type::scoped_lock lock(my_mutex);
return (size_t)(my_built_predecessors.edge_count()); return (size_t)(my_built_predecessors.edge_count());
} }
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
skipping to change at line 500 skipping to change at line 500
typedef std::list< pointer_type > my_successors_type; typedef std::list< pointer_type > my_successors_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
edge_container<receiver<T> > my_built_successors; edge_container<receiver<T> > my_built_successors;
#endif #endif
my_successors_type my_successors; my_successors_type my_successors;
sender<T> *my_owner; sender<T> *my_owner;
public: public:
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<pointer_type> successor_vector_type; typedef typename edge_container<receiver<T> >::edge_list_type succe ssor_list_type;
void internal_add_built_successor( receiver<T> &r) { void internal_add_built_successor( receiver<T> &r) {
typename my_mutex_type::scoped_lock l(my_mutex, true); typename my_mutex_type::scoped_lock l(my_mutex, true);
my_built_successors.add_edge( r ); my_built_successors.add_edge( r );
} }
void internal_delete_built_successor( receiver<T> &r) { void internal_delete_built_successor( receiver<T> &r) {
typename my_mutex_type::scoped_lock l(my_mutex, true); typename my_mutex_type::scoped_lock l(my_mutex, true);
my_built_successors.delete_edge(r); my_built_successors.delete_edge(r);
} }
void copy_successors( successor_vector_type &v) { void copy_successors( successor_list_type &v) {
typename my_mutex_type::scoped_lock l(my_mutex, false); typename my_mutex_type::scoped_lock l(my_mutex, false);
my_built_successors.copy_edges(v); my_built_successors.copy_edges(v);
} }
size_t successor_count() { size_t successor_count() {
typename my_mutex_type::scoped_lock l(my_mutex,false); typename my_mutex_type::scoped_lock l(my_mutex,false);
return my_built_successors.edge_count(); return my_built_successors.edge_count();
} }
void reset( __TBB_PFG_RESET_ARG(reset_flags f)) { void reset( __TBB_PFG_RESET_ARG(reset_flags f)) {
skipping to change at line 572 skipping to change at line 572
}; };
//! An abstract cache of successors, specialized to continue_msg //! An abstract cache of successors, specialized to continue_msg
template<> template<>
class successor_cache< continue_msg > : tbb::internal::no_copy { class successor_cache< continue_msg > : tbb::internal::no_copy {
protected: protected:
typedef spin_rw_mutex my_mutex_type; typedef spin_rw_mutex my_mutex_type;
my_mutex_type my_mutex; my_mutex_type my_mutex;
typedef receiver<continue_msg> successor_type;
typedef receiver<continue_msg> *pointer_type; typedef receiver<continue_msg> *pointer_type;
typedef std::list< pointer_type > my_successors_type; typedef std::list< pointer_type > my_successors_type;
my_successors_type my_successors; my_successors_type my_successors;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
edge_container<receiver<continue_msg> > my_built_successors; edge_container<successor_type> my_built_successors;
typedef edge_container<successor_type>::edge_list_type successor_li
st_type;
#endif #endif
sender<continue_msg> *my_owner; sender<continue_msg> *my_owner;
public: public:
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<pointer_type> successor_vector_type; void internal_add_built_successor( successor_type &r) {
void internal_add_built_successor( receiver<continue_msg> &r) {
my_mutex_type::scoped_lock l(my_mutex, true); my_mutex_type::scoped_lock l(my_mutex, true);
my_built_successors.add_edge( r ); my_built_successors.add_edge( r );
} }
void internal_delete_built_successor( receiver<continue_msg> &r) { void internal_delete_built_successor( successor_type &r) {
my_mutex_type::scoped_lock l(my_mutex, true); my_mutex_type::scoped_lock l(my_mutex, true);
my_built_successors.delete_edge(r); my_built_successors.delete_edge(r);
} }
void copy_successors( successor_vector_type &v) { void copy_successors( successor_list_type &v) {
my_mutex_type::scoped_lock l(my_mutex, false); my_mutex_type::scoped_lock l(my_mutex, false);
my_built_successors.copy_edges(v); my_built_successors.copy_edges(v);
} }
size_t successor_count() { size_t successor_count() {
my_mutex_type::scoped_lock l(my_mutex,false); my_mutex_type::scoped_lock l(my_mutex,false);
return my_built_successors.edge_count(); return my_built_successors.edge_count();
} }
void reset( __TBB_PFG_RESET_ARG(reset_flags f)) { void reset( __TBB_PFG_RESET_ARG(reset_flags f)) {
skipping to change at line 617 skipping to change at line 618
my_built_successors.sender_extract(*my_owner); my_built_successors.sender_extract(*my_owner);
} }
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
successor_cache( ) : my_owner(NULL) {} successor_cache( ) : my_owner(NULL) {}
void set_owner( sender<continue_msg> *owner ) { my_owner = owner; } void set_owner( sender<continue_msg> *owner ) { my_owner = owner; }
virtual ~successor_cache() {} virtual ~successor_cache() {}
void register_successor( receiver<continue_msg> &r ) { void register_successor( successor_type &r ) {
my_mutex_type::scoped_lock l(my_mutex, true); my_mutex_type::scoped_lock l(my_mutex, true);
my_successors.push_back( &r ); my_successors.push_back( &r );
if ( my_owner && r.is_continue_receiver() ) { if ( my_owner && r.is_continue_receiver() ) {
r.register_predecessor( *my_owner ); r.register_predecessor( *my_owner );
} }
} }
void remove_successor( receiver<continue_msg> &r ) { void remove_successor( successor_type &r ) {
my_mutex_type::scoped_lock l(my_mutex, true); my_mutex_type::scoped_lock l(my_mutex, true);
for ( my_successors_type::iterator i = my_successors.begin(); for ( my_successors_type::iterator i = my_successors.begin();
i != my_successors.end(); ++i ) { i != my_successors.end(); ++i ) {
if ( *i == & r ) { if ( *i == & r ) {
// TODO: Check if we need to test for continue_receiver before // TODO: Check if we need to test for continue_receiver before
// removing from r. // removing from r.
if ( my_owner ) if ( my_owner )
r.remove_predecessor( *my_owner ); r.remove_predecessor( *my_owner );
my_successors.erase(i); my_successors.erase(i);
break; break;
 End of changes. 11 change blocks. 
11 lines changed or deleted 13 lines changed or added


 _flow_graph_indexer_impl.h   _flow_graph_indexer_impl.h 
skipping to change at line 98 skipping to change at line 98
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
indexer_input_port() : my_pred_mutex() {} indexer_input_port() : my_pred_mutex() {}
indexer_input_port( const indexer_input_port & /*other*/ ) : receiv er<T>(), my_pred_mutex() { indexer_input_port( const indexer_input_port & /*other*/ ) : receiv er<T>(), my_pred_mutex() {
} }
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
void set_up(void *p, forward_function_ptr f) { void set_up(void *p, forward_function_ptr f) {
my_indexer_ptr = p; my_indexer_ptr = p;
my_try_put_task = f; my_try_put_task = f;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<sender<T> *> predecessor_vector_type; typedef typename receiver<T>::predecessor_list_type predecessor_lis t_type;
/*override*/size_t predecessor_count() { /*override*/size_t predecessor_count() {
spin_mutex::scoped_lock l(my_pred_mutex); spin_mutex::scoped_lock l(my_pred_mutex);
return my_built_predecessors.edge_count(); return my_built_predecessors.edge_count();
} }
/*override*/void internal_add_built_predecessor(sender<T> &p) { /*override*/void internal_add_built_predecessor(sender<T> &p) {
spin_mutex::scoped_lock l(my_pred_mutex); spin_mutex::scoped_lock l(my_pred_mutex);
my_built_predecessors.add_edge(p); my_built_predecessors.add_edge(p);
} }
/*override*/void internal_delete_built_predecessor(sender<T> &p) { /*override*/void internal_delete_built_predecessor(sender<T> &p) {
spin_mutex::scoped_lock l(my_pred_mutex); spin_mutex::scoped_lock l(my_pred_mutex);
my_built_predecessors.delete_edge(p); my_built_predecessors.delete_edge(p);
} }
/*override*/void copy_predecessors( predecessor_vector_type &v) { /*override*/void copy_predecessors( predecessor_list_type &v) {
spin_mutex::scoped_lock l(my_pred_mutex); spin_mutex::scoped_lock l(my_pred_mutex);
return my_built_predecessors.copy_edges(v); return my_built_predecessors.copy_edges(v);
} }
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
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_c ache; template<typename X, typename Y> friend class internal::broadcast_c ache;
template<typename X, typename Y> friend class internal::round_robin _cache; template<typename X, typename Y> friend class internal::round_robin _cache;
task *try_put_task(const T &v) { task *try_put_task(const T &v) {
return my_try_put_task(v, my_indexer_ptr); return my_try_put_task(v, my_indexer_ptr);
skipping to change at line 160 skipping to change at line 160
public sender<OutputType> { public sender<OutputType> {
protected: protected:
using graph_node::my_graph; using graph_node::my_graph;
public: public:
static const size_t N = tbb::flow::tuple_size<InputTuple>::value; static const size_t N = tbb::flow::tuple_size<InputTuple>::value;
typedef OutputType output_type; typedef OutputType output_type;
typedef StructTypes tuple_types; typedef StructTypes tuple_types;
typedef receiver<output_type> successor_type; typedef receiver<output_type> successor_type;
typedef indexer_node_FE<InputTuple, output_type,StructTypes> input_ ports_type; typedef indexer_node_FE<InputTuple, output_type,StructTypes> input_ ports_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<successor_type *> successor_vector_type; typedef typename sender<output_type>::successor_list_type successor _list_type;
#endif #endif
private: private:
// ----------- Aggregator ------------ // ----------- Aggregator ------------
enum op_type { reg_succ, rem_succ, try__put_task enum op_type { reg_succ, rem_succ, try__put_task
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
, add_blt_succ, del_blt_succ, , add_blt_succ, del_blt_succ,
blt_succ_cnt, blt_succ_cpy blt_succ_cnt, blt_succ_cpy
#endif #endif
}; };
skipping to change at line 183 skipping to change at line 183
class indexer_node_base_operation : public aggregated_operation<ind exer_node_base_operation> { class indexer_node_base_operation : public aggregated_operation<ind exer_node_base_operation> {
public: public:
char type; char type;
union { union {
output_type const *my_arg; output_type const *my_arg;
successor_type *my_succ; successor_type *my_succ;
task *bypass_t; task *bypass_t;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
size_t cnt_val; size_t cnt_val;
successor_vector_type *succv; successor_list_type *succv;
#endif #endif
}; };
indexer_node_base_operation(const output_type* e, op_type t) : indexer_node_base_operation(const output_type* e, op_type t) :
type(char(t)), my_arg(e) {} type(char(t)), my_arg(e) {}
indexer_node_base_operation(const successor_type &s, op_type t) : type(char(t)), indexer_node_base_operation(const successor_type &s, op_type t) : type(char(t)),
my_succ(const_cast<successor_type *>(&s)) {} my_succ(const_cast<successor_type *>(&s)) {}
indexer_node_base_operation(op_type t) : type(char(t)) {} indexer_node_base_operation(op_type t) : type(char(t)) {}
}; };
typedef internal::aggregating_functor<my_class, indexer_node_base_o peration> my_handler; typedef internal::aggregating_functor<my_class, indexer_node_base_o peration> my_handler;
skipping to change at line 288 skipping to change at line 288
indexer_node_base_operation op_data(r, del_blt_succ); indexer_node_base_operation op_data(r, del_blt_succ);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
size_t successor_count() { size_t successor_count() {
indexer_node_base_operation op_data(blt_succ_cnt); indexer_node_base_operation op_data(blt_succ_cnt);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.cnt_val; return op_data.cnt_val;
} }
void copy_successors( successor_vector_type &v) { void copy_successors( successor_list_type &v) {
indexer_node_base_operation op_data(blt_succ_cpy); indexer_node_base_operation op_data(blt_succ_cpy);
op_data.succv = &v; op_data.succv = &v;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
protected: protected:
/*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) { /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) {
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
my_successors.reset(f); my_successors.reset(f);
indexer_helper<StructTypes,N>::reset_inputs(this->my_inputs, f) ; indexer_helper<StructTypes,N>::reset_inputs(this->my_inputs, f) ;
 End of changes. 5 change blocks. 
5 lines changed or deleted 5 lines changed or added


 _flow_graph_join_impl.h   _flow_graph_join_impl.h 
skipping to change at line 204 skipping to change at line 204
} }
}; };
//! The two-phase join port //! The two-phase join port
template< typename T > template< typename T >
class reserving_port : public receiver<T> { class reserving_port : public receiver<T> {
public: public:
typedef T input_type; typedef T input_type;
typedef sender<T> predecessor_type; typedef sender<T> predecessor_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type; typedef typename receiver<input_type>::predecessor_list_type predec essor_list_type;
#endif #endif
private: private:
// ----------- Aggregator ------------ // ----------- Aggregator ------------
enum op_type { reg_pred, rem_pred, res_item, rel_res, con_res enum op_type { reg_pred, rem_pred, res_item, rel_res, con_res
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
, add_blt_pred, del_blt_pred, blt_pred_cnt, blt_pred_cpy , add_blt_pred, del_blt_pred, blt_pred_cnt, blt_pred_cpy
#endif #endif
}; };
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
typedef reserving_port<T> my_class; typedef reserving_port<T> my_class;
class reserving_port_operation : public aggregated_operation<reserv ing_port_operation> { class reserving_port_operation : public aggregated_operation<reserv ing_port_operation> {
public: public:
char type; char type;
union { union {
T *my_arg; T *my_arg;
predecessor_type *my_pred; predecessor_type *my_pred;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
size_t cnt_val; size_t cnt_val;
predecessor_vector_type *pvec; predecessor_list_type *plist;
#endif #endif
}; };
reserving_port_operation(const T& e, op_type t) : reserving_port_operation(const T& e, op_type t) :
type(char(t)), my_arg(const_cast<T*>(&e)) {} type(char(t)), my_arg(const_cast<T*>(&e)) {}
reserving_port_operation(const predecessor_type &s, op_type t) : type(char(t)), reserving_port_operation(const predecessor_type &s, op_type t) : type(char(t)),
my_pred(const_cast<predecessor_type *>(&s)) {} my_pred(const_cast<predecessor_type *>(&s)) {}
reserving_port_operation(op_type t) : type(char(t)) {} reserving_port_operation(op_type t) : type(char(t)) {}
}; };
typedef internal::aggregating_functor<my_class, reserving_port_oper ation> my_handler; typedef internal::aggregating_functor<my_class, reserving_port_oper ation> my_handler;
skipping to change at line 296 skipping to change at line 296
break; break;
case del_blt_pred: case del_blt_pred:
my_predecessors.internal_delete_built_predecessor(*(cur rent->my_pred)); my_predecessors.internal_delete_built_predecessor(*(cur rent->my_pred));
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case blt_pred_cnt: case blt_pred_cnt:
current->cnt_val = my_predecessors.predecessor_count(); current->cnt_val = my_predecessors.predecessor_count();
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case blt_pred_cpy: case blt_pred_cpy:
my_predecessors.copy_predecessors(*(current->pvec)); my_predecessors.copy_predecessors(*(current->plist));
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
} }
} }
} }
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_c ache; template<typename X, typename Y> friend class internal::broadcast_c ache;
skipping to change at line 383 skipping to change at line 383
reserving_port_operation op_data(src, del_blt_pred); reserving_port_operation op_data(src, del_blt_pred);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
/*override*/size_t predecessor_count() { /*override*/size_t predecessor_count() {
reserving_port_operation op_data(blt_pred_cnt); reserving_port_operation op_data(blt_pred_cnt);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.cnt_val; return op_data.cnt_val;
} }
/*override*/void copy_predecessors(predecessor_vector_type &v) { /*override*/void copy_predecessors(predecessor_list_type &l) {
reserving_port_operation op_data(blt_pred_cpy); reserving_port_operation op_data(blt_pred_cpy);
op_data.pvec = &v; op_data.plist = &l;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
/*override*/void reset_receiver( __TBB_PFG_RESET_ARG(reset_flags f) ) { /*override*/void reset_receiver( __TBB_PFG_RESET_ARG(reset_flags f) ) {
my_predecessors.reset(__TBB_PFG_RESET_ARG(f)); my_predecessors.reset(__TBB_PFG_RESET_ARG(f));
reserved = false; reserved = false;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
__TBB_ASSERT(!(f&rf_extract) || my_predecessors.empty(), "port edges not removed"); __TBB_ASSERT(!(f&rf_extract) || my_predecessors.empty(), "port edges not removed");
#endif #endif
skipping to change at line 412 skipping to change at line 412
}; };
//! queueing join_port //! queueing join_port
template<typename T> template<typename T>
class queueing_port : public receiver<T>, public item_buffer<T> { class queueing_port : public receiver<T>, public item_buffer<T> {
public: public:
typedef T input_type; typedef T input_type;
typedef sender<T> predecessor_type; typedef sender<T> predecessor_type;
typedef queueing_port<T> my_node_type; typedef queueing_port<T> my_node_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type; typedef typename receiver<input_type>::predecessor_list_type predec essor_list_type;
#endif #endif
// ----------- Aggregator ------------ // ----------- Aggregator ------------
private: private:
enum op_type { get__item, res_port, try__put_task enum op_type { get__item, res_port, try__put_task
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
, add_blt_pred, del_blt_pred, blt_pred_cnt, blt_pred_cpy , add_blt_pred, del_blt_pred, blt_pred_cnt, blt_pred_cpy
#endif #endif
}; };
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
typedef queueing_port<T> my_class; typedef queueing_port<T> my_class;
class queueing_port_operation : public aggregated_operation<queuein g_port_operation> { class queueing_port_operation : public aggregated_operation<queuein g_port_operation> {
public: public:
char type; char type;
T my_val; T my_val;
T *my_arg; T *my_arg;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
sender<T> *pred; sender<T> *pred;
size_t cnt_val; size_t cnt_val;
predecessor_vector_type *pvec; predecessor_list_type *plist;
#endif #endif
task * bypass_t; task * bypass_t;
// constructor for value parameter // constructor for value parameter
queueing_port_operation(const T& e, op_type t) : queueing_port_operation(const T& e, op_type t) :
type(char(t)), my_val(e) type(char(t)), my_val(e)
, bypass_t(NULL) , bypass_t(NULL)
{} {}
// constructor for pointer parameter // constructor for pointer parameter
queueing_port_operation(const T* p, op_type t) : queueing_port_operation(const T* p, op_type t) :
type(char(t)), my_arg(const_cast<T*>(p)) type(char(t)), my_arg(const_cast<T*>(p))
skipping to change at line 505 skipping to change at line 505
break; break;
case del_blt_pred: case del_blt_pred:
my_built_predecessors.delete_edge(*(current->pred)); my_built_predecessors.delete_edge(*(current->pred));
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case blt_pred_cnt: case blt_pred_cnt:
current->cnt_val = my_built_predecessors.edge_count(); current->cnt_val = my_built_predecessors.edge_count();
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case blt_pred_cpy: case blt_pred_cpy:
my_built_predecessors.copy_edges(*(current->pvec)); my_built_predecessors.copy_edges(*(current->plist));
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
} }
} }
} }
// ------------ End Aggregator --------------- // ------------ End Aggregator ---------------
protected: protected:
template< typename R, typename B > friend class run_and_put_task; template< typename R, typename B > friend class run_and_put_task;
skipping to change at line 578 skipping to change at line 578
op_data.pred = &p; op_data.pred = &p;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
/*override*/size_t predecessor_count() { /*override*/size_t predecessor_count() {
queueing_port_operation op_data(blt_pred_cnt); queueing_port_operation op_data(blt_pred_cnt);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.cnt_val; return op_data.cnt_val;
} }
/*override*/void copy_predecessors(predecessor_vector_type &v) { /*override*/void copy_predecessors(predecessor_list_type &l) {
queueing_port_operation op_data(blt_pred_cpy); queueing_port_operation op_data(blt_pred_cpy);
op_data.pvec = &v; op_data.plist = &l;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
/*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags f)) { /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags f)) {
item_buffer<T>::reset(); item_buffer<T>::reset();
if (f & rf_extract) if (f & rf_extract)
my_built_predecessors.receiver_extract(*this); my_built_predecessors.receiver_extract(*this);
} }
#else #else
/*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags /*f */)) { item_buffer<T>::reset(); } /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags /*f */)) { item_buffer<T>::reset(); }
skipping to change at line 611 skipping to change at line 611
template< typename T > template< typename T >
class tag_matching_port : public receiver<T>, public tagged_buffer< tag _value, T, NO_TAG > { class tag_matching_port : public receiver<T>, public tagged_buffer< tag _value, T, NO_TAG > {
public: public:
typedef T input_type; typedef T input_type;
typedef sender<T> predecessor_type; typedef sender<T> predecessor_type;
typedef tag_matching_port<T> my_node_type; // for forwarding, if n eeded typedef tag_matching_port<T> my_node_type; // for forwarding, if n eeded
typedef function_body<input_type, tag_value> my_tag_func_type; typedef function_body<input_type, tag_value> my_tag_func_type;
typedef tagged_buffer<tag_value,T,NO_TAG> my_buffer_type; typedef tagged_buffer<tag_value,T,NO_TAG> my_buffer_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type; typedef typename receiver<input_type>::predecessor_list_type predec essor_list_type;
#endif #endif
private: private:
// ----------- Aggregator ------------ // ----------- Aggregator ------------
private: private:
enum op_type { try__put, get__item, res_port, enum op_type { try__put, get__item, res_port,
add_blt_pred, del_blt_pred, blt_pred_cnt, blt_pred_cpy add_blt_pred, del_blt_pred, blt_pred_cnt, blt_pred_cpy
}; };
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
typedef tag_matching_port<T> my_class; typedef tag_matching_port<T> my_class;
class tag_matching_port_operation : public aggregated_operation<tag _matching_port_operation> { class tag_matching_port_operation : public aggregated_operation<tag _matching_port_operation> {
public: public:
char type; char type;
T my_val; T my_val;
T *my_arg; T *my_arg;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
predecessor_type *pred; predecessor_type *pred;
size_t cnt_val; size_t cnt_val;
predecessor_vector_type *pvec; predecessor_list_type *plist;
#endif #endif
tag_value my_tag_value; tag_value my_tag_value;
// constructor for value parameter // constructor for value parameter
tag_matching_port_operation(const T& e, op_type t) : tag_matching_port_operation(const T& e, op_type t) :
type(char(t)), my_val(e) {} type(char(t)), my_val(e) {}
// constructor for pointer parameter // constructor for pointer parameter
tag_matching_port_operation(const T* p, op_type t) : tag_matching_port_operation(const T* p, op_type t) :
type(char(t)), my_arg(const_cast<T*>(p)) {} type(char(t)), my_arg(const_cast<T*>(p)) {}
// constructor with no parameter // constructor with no parameter
tag_matching_port_operation(op_type t) : type(char(t)) {} tag_matching_port_operation(op_type t) : type(char(t)) {}
skipping to change at line 685 skipping to change at line 685
break; break;
case del_blt_pred: case del_blt_pred:
my_built_predecessors.delete_edge(*(current->pred)); my_built_predecessors.delete_edge(*(current->pred));
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case blt_pred_cnt: case blt_pred_cnt:
current->cnt_val = my_built_predecessors.edge_count(); current->cnt_val = my_built_predecessors.edge_count();
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case blt_pred_cpy: case blt_pred_cpy:
my_built_predecessors.copy_edges(*(current->pvec)); my_built_predecessors.copy_edges(*(current->plist));
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
#endif #endif
} }
} }
} }
// ------------ End Aggregator --------------- // ------------ End Aggregator ---------------
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_c ache; template<typename X, typename Y> friend class internal::broadcast_c ache;
skipping to change at line 770 skipping to change at line 770
op_data.pred = &p; op_data.pred = &p;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
/*override*/size_t predecessor_count() { /*override*/size_t predecessor_count() {
tag_matching_port_operation op_data(blt_pred_cnt); tag_matching_port_operation op_data(blt_pred_cnt);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.cnt_val; return op_data.cnt_val;
} }
/*override*/void copy_predecessors(predecessor_vector_type &v) { /*override*/void copy_predecessors(predecessor_list_type &l) {
tag_matching_port_operation op_data(blt_pred_cpy); tag_matching_port_operation op_data(blt_pred_cpy);
op_data.pvec = &v; op_data.plist = &l;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
#endif #endif
// reset_port is called when item is accepted by successor, but // reset_port is called when item is accepted by successor, but
// is initiated by join_node. // is initiated by join_node.
void reset_port() { void reset_port() {
tag_matching_port_operation op_data(res_port); tag_matching_port_operation op_data(res_port);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return; return;
skipping to change at line 1179 skipping to change at line 1179
public: public:
typedef OutputTuple output_type; typedef OutputTuple output_type;
typedef receiver<output_type> successor_type; typedef receiver<output_type> successor_type;
typedef join_node_FE<JP, InputTuple, OutputTuple> input_ports_type; typedef join_node_FE<JP, InputTuple, OutputTuple> input_ports_type;
using input_ports_type::tuple_build_may_succeed; using input_ports_type::tuple_build_may_succeed;
using input_ports_type::try_to_make_tuple; using input_ports_type::try_to_make_tuple;
using input_ports_type::tuple_accepted; using input_ports_type::tuple_accepted;
using input_ports_type::tuple_rejected; using input_ports_type::tuple_rejected;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<successor_type *> successor_vector_type; typedef typename sender<output_type>::successor_list_type successor _list_type;
#endif #endif
private: private:
// ----------- Aggregator ------------ // ----------- Aggregator ------------
enum op_type { reg_succ, rem_succ, try__get, do_fwrd, do_fwrd_bypas s enum op_type { reg_succ, rem_succ, try__get, do_fwrd, do_fwrd_bypas s
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
, add_blt_succ, del_blt_succ, blt_succ_cnt, blt_succ_cpy , add_blt_succ, del_blt_succ, blt_succ_cnt, blt_succ_cpy
#endif #endif
}; };
enum op_stat {WAIT=0, SUCCEEDED, FAILED}; enum op_stat {WAIT=0, SUCCEEDED, FAILED};
typedef join_node_base<JP,InputTuple,OutputTuple> my_class; typedef join_node_base<JP,InputTuple,OutputTuple> my_class;
class join_node_base_operation : public aggregated_operation<join_n ode_base_operation> { class join_node_base_operation : public aggregated_operation<join_n ode_base_operation> {
public: public:
char type; char type;
union { union {
output_type *my_arg; output_type *my_arg;
successor_type *my_succ; successor_type *my_succ;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
size_t cnt_val; size_t cnt_val;
successor_vector_type *svec; successor_list_type *slist;
#endif #endif
}; };
task *bypass_t; task *bypass_t;
join_node_base_operation(const output_type& e, op_type t) : typ e(char(t)), join_node_base_operation(const output_type& e, op_type t) : typ e(char(t)),
my_arg(const_cast<output_type*>(&e)), bypass_t(NULL) {} my_arg(const_cast<output_type*>(&e)), bypass_t(NULL) {}
join_node_base_operation(const successor_type &s, op_type t) : type(char(t)), join_node_base_operation(const successor_type &s, op_type t) : type(char(t)),
my_succ(const_cast<successor_type *>(&s)), bypass_t(NULL) { } my_succ(const_cast<successor_type *>(&s)), bypass_t(NULL) { }
join_node_base_operation(op_type t) : type(char(t)), bypass_t(N ULL) {} join_node_base_operation(op_type t) : type(char(t)), bypass_t(N ULL) {}
}; };
skipping to change at line 1288 skipping to change at line 1288
break; break;
case del_blt_succ: case del_blt_succ:
my_successors.internal_delete_built_successor(*(current ->my_succ)); my_successors.internal_delete_built_successor(*(current ->my_succ));
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case blt_succ_cnt: case blt_succ_cnt:
current->cnt_val = my_successors.successor_count(); current->cnt_val = my_successors.successor_count();
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
case blt_succ_cpy: case blt_succ_cpy:
my_successors.copy_successors(*(current->svec)); my_successors.copy_successors(*(current->slist));
__TBB_store_with_release(current->status, SUCCEEDED); __TBB_store_with_release(current->status, SUCCEEDED);
break; break;
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
} }
} }
} }
// ---------- end aggregator ----------- // ---------- end aggregator -----------
public: public:
join_node_base(graph &g) : graph_node(g), input_ports_type(g), forw arder_busy(false) { join_node_base(graph &g) : graph_node(g), input_ports_type(g), forw arder_busy(false) {
my_successors.set_owner(this); my_successors.set_owner(this);
skipping to change at line 1353 skipping to change at line 1353
join_node_base_operation op_data(r, del_blt_succ); join_node_base_operation op_data(r, del_blt_succ);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
/*override*/size_t successor_count() { /*override*/size_t successor_count() {
join_node_base_operation op_data(blt_succ_cnt); join_node_base_operation op_data(blt_succ_cnt);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.cnt_val; return op_data.cnt_val;
} }
/*override*/ void copy_successors(successor_vector_type &v) { /*override*/ void copy_successors(successor_list_type &l) {
join_node_base_operation op_data(blt_succ_cpy); join_node_base_operation op_data(blt_succ_cpy);
op_data.svec = &v; op_data.slist = &l;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
protected: protected:
/*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) { /*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags f)) {
input_ports_type::reset(__TBB_PFG_RESET_ARG(f)); input_ports_type::reset(__TBB_PFG_RESET_ARG(f));
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
my_successors.reset(f); my_successors.reset(f);
 End of changes. 20 change blocks. 
20 lines changed or deleted 20 lines changed or added


 _flow_graph_node_impl.h   _flow_graph_node_impl.h 
skipping to change at line 70 skipping to change at line 70
}; };
typedef function_input_base<Input, A, ImplType> my_class; typedef function_input_base<Input, A, ImplType> my_class;
public: public:
//! The input type of this receiver //! The input type of this receiver
typedef Input input_type; typedef Input input_type;
typedef sender<Input> predecessor_type; typedef sender<Input> predecessor_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type; typedef typename receiver<input_type>::predecessor_list_type predec essor_list_type;
#endif #endif
//! Constructor for function_input_base //! Constructor for function_input_base
function_input_base( graph &g, size_t max_concurrency, function_inp ut_queue<input_type,A> *q = NULL ) function_input_base( graph &g, size_t max_concurrency, function_inp ut_queue<input_type,A> *q = NULL )
: my_graph(g), my_max_concurrency(max_concurrency), my_concurre ncy(0), : my_graph(g), my_max_concurrency(max_concurrency), my_concurre ncy(0),
my_queue(q), forwarder_busy(false) { my_queue(q), forwarder_busy(false) {
my_predecessors.set_owner(this); my_predecessors.set_owner(this);
my_aggregator.initialize_handler(my_handler(this)); my_aggregator.initialize_handler(my_handler(this));
} }
skipping to change at line 147 skipping to change at line 147
op_data.r = &src; op_data.r = &src;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
/*override*/ size_t predecessor_count() { /*override*/ size_t predecessor_count() {
my_operation op_data(blt_pred_cnt); my_operation op_data(blt_pred_cnt);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.cnt_val; return op_data.cnt_val;
} }
/*override*/ void copy_predecessors(predecessor_vector_type &v) { /*override*/ void copy_predecessors(predecessor_list_type &v) {
my_operation op_data(blt_pred_cpy); my_operation op_data(blt_pred_cpy);
op_data.predv = &v; op_data.predv = &v;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
protected: protected:
void reset_function_input_base( __TBB_PFG_RESET_ARG(reset_flags f)) { void reset_function_input_base( __TBB_PFG_RESET_ARG(reset_flags f)) {
my_concurrency = 0; my_concurrency = 0;
skipping to change at line 191 skipping to change at line 191
friend class forward_task_bypass< my_class >; friend class forward_task_bypass< my_class >;
class my_operation : public aggregated_operation< my_operation > { class my_operation : public aggregated_operation< my_operation > {
public: public:
char type; char type;
union { union {
input_type *elem; input_type *elem;
predecessor_type *r; predecessor_type *r;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
size_t cnt_val; size_t cnt_val;
predecessor_vector_type *predv; predecessor_list_type *predv;
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
}; };
tbb::task *bypass_t; tbb::task *bypass_t;
my_operation(const input_type& e, op_type t) : my_operation(const input_type& e, op_type t) :
type(char(t)), elem(const_cast<input_type*>(&e)) {} type(char(t)), elem(const_cast<input_type*>(&e)) {}
my_operation(op_type t) : type(char(t)), r(NULL) {} my_operation(op_type t) : type(char(t)), r(NULL) {}
}; };
bool forwarder_busy; bool forwarder_busy;
typedef internal::aggregating_functor<my_class, my_operation> my_ha ndler; typedef internal::aggregating_functor<my_class, my_operation> my_ha ndler;
skipping to change at line 666 skipping to change at line 666
class function_output : public sender<Output> { class function_output : public sender<Output> {
public: public:
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
template<int N> friend struct reset_element; template<int N> friend struct reset_element;
#endif #endif
typedef Output output_type; typedef Output output_type;
typedef receiver<output_type> successor_type; typedef receiver<output_type> successor_type;
typedef broadcast_cache<output_type> broadcast_cache_type; typedef broadcast_cache<output_type> broadcast_cache_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<successor_type *> successor_vector_type; typedef typename sender<output_type>::successor_list_type successor _list_type;
#endif #endif
function_output() { my_successors.set_owner(this); } function_output() { my_successors.set_owner(this); }
function_output(const function_output & /*other*/) : sender<output_ type>() { function_output(const function_output & /*other*/) : sender<output_ type>() {
my_successors.set_owner(this); my_successors.set_owner(this);
} }
//! Adds a new successor to this node //! Adds a new successor to this node
/* override */ bool register_successor( receiver<output_type> &r ) { /* override */ bool register_successor( receiver<output_type> &r ) {
successors().register_successor( r ); successors().register_successor( r );
skipping to change at line 699 skipping to change at line 699
} }
/*override*/ void internal_delete_built_successor( receiver<output_ type> &r) { /*override*/ void internal_delete_built_successor( receiver<output_ type> &r) {
successors().internal_delete_built_successor( r ); successors().internal_delete_built_successor( r );
} }
/*override*/ size_t successor_count() { /*override*/ size_t successor_count() {
return successors().successor_count(); return successors().successor_count();
} }
/*override*/ void copy_successors( successor_vector_type &v) { /*override*/ void copy_successors( successor_list_type &v) {
successors().copy_successors(v); successors().copy_successors(v);
} }
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
// for multifunction_node. The function_body that implements // for multifunction_node. The function_body that implements
// the node will have an input and an output tuple of ports. To pu t // the node will have an input and an output tuple of ports. To pu t
// an item to a successor, the body should // an item to a successor, the body should
// //
// get<I>(output_ports).try_put(output_value); // get<I>(output_ports).try_put(output_value);
// //
 End of changes. 5 change blocks. 
5 lines changed or deleted 5 lines changed or added


 _flow_graph_trace_impl.h   _flow_graph_trace_impl.h 
skipping to change at line 56 skipping to change at line 56
}; };
template < typename TypesTuple, typename PortsTuple > template < typename TypesTuple, typename PortsTuple >
struct fgt_internal_input_helper<TypesTuple,PortsTuple,1> { struct fgt_internal_input_helper<TypesTuple,PortsTuple,1> {
static void register_port( void *node, PortsTuple &ports ) { static void register_port( void *node, PortsTuple &ports ) {
fgt_internal_create_input_port( node, (void*)static_cast< tbb::flow ::interface7::receiver< typename tbb::flow::tuple_element<0,TypesTuple>::ty pe > * >(&(tbb::flow::get<0>(ports))), fgt_internal_create_input_port( node, (void*)static_cast< tbb::flow ::interface7::receiver< typename tbb::flow::tuple_element<0,TypesTuple>::ty pe > * >(&(tbb::flow::get<0>(ports))),
FLOW_INPUT_PORT_0 ); FLOW_INPUT_PORT_0 );
} }
}; };
//for cases where the ports tuple are already receivers
template < typename PortsTuple, int N >
struct fgt_internal_input_helper< PortsTuple, PortsTuple, N> {
static void register_port( void *node, PortsTuple &ports ) {
fgt_internal_create_input_port( node,&(tbb::flow::get<N-1>(ports)),
static_cast<tbb::internal::string_index>(FLOW_INPUT_PORT_0 + N - 1) );
fgt_internal_input_helper<PortsTuple, PortsTuple, N-1>::register_po
rt( node, ports );
}
};
template < typename PortsTuple >
struct fgt_internal_input_helper<PortsTuple, PortsTuple,1> {
static void register_port( void *node, PortsTuple &ports ) {
fgt_internal_create_input_port( node, &(tbb::flow::get<0>(ports)),
FLOW_INPUT_PORT_0 );
}
};
template < typename TypesTuple, typename PortsTuple, int N > template < typename TypesTuple, typename PortsTuple, int N >
struct fgt_internal_output_helper { struct fgt_internal_output_helper {
static void register_port( void *node, PortsTuple &ports ) { static void register_port( void *node, PortsTuple &ports ) {
fgt_internal_create_output_port( node, (void*)static_cast< tbb::flo w::interface7::sender< typename tbb::flow::tuple_element<N-1,TypesTuple>::t ype > * >(&(tbb::flow::get<N-1>(ports))), fgt_internal_create_output_port( node, (void*)static_cast< tbb::flo w::interface7::sender< typename tbb::flow::tuple_element<N-1,TypesTuple>::t ype > * >(&(tbb::flow::get<N-1>(ports))),
static_cast<tbb::internal::string_ index>(FLOW_OUTPUT_PORT_0 + N - 1) ); static_cast<tbb::internal::string_ index>(FLOW_OUTPUT_PORT_0 + N - 1) );
fgt_internal_output_helper<TypesTuple, PortsTuple, N-1>::register_p ort( node, ports ); fgt_internal_output_helper<TypesTuple, PortsTuple, N-1>::register_p ort( node, ports );
} }
}; };
template < typename TypesTuple, typename PortsTuple > template < typename TypesTuple, typename PortsTuple >
struct fgt_internal_output_helper<TypesTuple,PortsTuple,1> { struct fgt_internal_output_helper<TypesTuple,PortsTuple,1> {
static void register_port( void *node, PortsTuple &ports ) { static void register_port( void *node, PortsTuple &ports ) {
fgt_internal_create_output_port( node, (void*)static_cast< tbb::flo w::interface7::sender< typename tbb::flow::tuple_element<0,TypesTuple>::typ e > * >(&(tbb::flow::get<0>(ports))), fgt_internal_create_output_port( node, (void*)static_cast< tbb::flo w::interface7::sender< typename tbb::flow::tuple_element<0,TypesTuple>::typ e > * >(&(tbb::flow::get<0>(ports))),
FLOW_OUTPUT_PORT_0 ); FLOW_OUTPUT_PORT_0 );
} }
}; };
//for cases where the ports tuple are already senders
template < typename PortsTuple, int N >
struct fgt_internal_output_helper<PortsTuple, PortsTuple, N> {
static void register_port( void *node, PortsTuple &ports ) {
fgt_internal_create_output_port( node,&(tbb::flow::get<N-1>(ports))
, static_cast<tbb::internal::string_index>(FLOW_OUTPUT_PORT_0 + N - 1) );
fgt_internal_output_helper<PortsTuple, PortsTuple, N-1>::register_p
ort( node, ports );
}
};
template < typename PortsTuple >
struct fgt_internal_output_helper<PortsTuple,PortsTuple,1> {
static void register_port( void *node, PortsTuple &ports ) {
fgt_internal_create_output_port( node,&(tbb::flow::get<0>(ports)),
FLOW_OUTPUT_PORT_0 );
}
};
template< typename NodeType > template< typename NodeType >
void fgt_multioutput_node_desc( const NodeType *node, const char *desc ) { void fgt_multioutput_node_desc( const NodeType *node, const char *desc ) {
void *addr = (void *)( static_cast< tbb::flow::interface7::receiver< t ypename NodeType::input_type > * >(const_cast< NodeType *>(node)) ); void *addr = (void *)( static_cast< tbb::flow::interface7::receiver< t ypename NodeType::input_type > * >(const_cast< NodeType *>(node)) );
itt_metadata_str_add( ITT_DOMAIN_FLOW, addr, FLOW_NODE, FLOW_OBJECT_NAM E, desc ); itt_metadata_str_add( ITT_DOMAIN_FLOW, addr, FLOW_NODE, FLOW_OBJECT_NAM E, desc );
} }
template< typename NodeType > template< typename NodeType >
void fgt_multiinput_multioutput_node_desc( const NodeType *node, const char
*desc ) {
void *addr = (void *)(node);
itt_metadata_str_add( ITT_DOMAIN_FLOW, addr, FLOW_NODE, FLOW_OBJECT_NAM
E, desc );
}
template< typename NodeType >
static inline void fgt_node_desc( const NodeType *node, const char *desc ) { static inline void fgt_node_desc( const NodeType *node, const char *desc ) {
void *addr = (void *)( static_cast< tbb::flow::interface7::sender< typ ename NodeType::output_type > * >(const_cast< NodeType *>(node)) ); void *addr = (void *)( static_cast< tbb::flow::interface7::sender< typ ename NodeType::output_type > * >(const_cast< NodeType *>(node)) );
itt_metadata_str_add( ITT_DOMAIN_FLOW, addr, FLOW_NODE, FLOW_OBJECT_NAM E, desc ); itt_metadata_str_add( ITT_DOMAIN_FLOW, addr, FLOW_NODE, FLOW_OBJECT_NAM E, desc );
} }
static inline void fgt_graph_desc( void *g, const char *desc ) { static inline void fgt_graph_desc( void *g, const char *desc ) {
itt_metadata_str_add( ITT_DOMAIN_FLOW, g, FLOW_GRAPH, FLOW_OBJECT_NAME, desc ); itt_metadata_str_add( ITT_DOMAIN_FLOW, g, FLOW_GRAPH, FLOW_OBJECT_NAME, desc );
} }
static inline void fgt_body( void *node, void *body ) { static inline void fgt_body( void *node, void *body ) {
 End of changes. 3 change blocks. 
0 lines changed or deleted 46 lines changed or added


 _flow_graph_types_impl.h   _flow_graph_types_impl.h 
skipping to change at line 341 skipping to change at line 341
typedef typename pick_tuple_max<N-1, Tuple, Selector>::type LeftMaxType ; typedef typename pick_tuple_max<N-1, Tuple, Selector>::type LeftMaxType ;
typedef typename tbb::flow::tuple_element<N-1, Tuple>::type ThisType; typedef typename tbb::flow::tuple_element<N-1, Tuple>::type ThisType;
typedef typename pick_max<Selector, LeftMaxType, ThisType>::type type; typedef typename pick_max<Selector, LeftMaxType, ThisType>::type type;
}; };
template< class Tuple, template<class> class Selector > struct pick_tuple_m ax<0, Tuple, Selector> { template< class Tuple, template<class> class Selector > struct pick_tuple_m ax<0, Tuple, Selector> {
typedef typename tbb::flow::tuple_element<0, Tuple>::type type; typedef typename tbb::flow::tuple_element<0, Tuple>::type type;
}; };
// is the specified type included in a tuple? // is the specified type included in a tuple?
template<class U, class V> struct is_same_type { static const bool val
ue = false; };
template<class W> struct is_same_type<W,W> { static const bool val
ue = true; };
template<class Q, size_t N, class Tuple> template<class Q, size_t N, class Tuple>
struct is_element_of { struct is_element_of {
typedef typename tbb::flow::tuple_element<N-1, Tuple>::type T_i; typedef typename tbb::flow::tuple_element<N-1, Tuple>::type T_i;
static const bool value = is_same_type<Q,T_i>::value || is_element_of<Q ,N-1,Tuple>::value; static const bool value = tbb::internal::is_same_type<Q,T_i>::value || is_element_of<Q,N-1,Tuple>::value;
}; };
template<class Q, class Tuple> template<class Q, class Tuple>
struct is_element_of<Q,0,Tuple> { struct is_element_of<Q,0,Tuple> {
typedef typename tbb::flow::tuple_element<0, Tuple>::type T_i; typedef typename tbb::flow::tuple_element<0, Tuple>::type T_i;
static const bool value = is_same_type<Q,T_i>::value; static const bool value = tbb::internal::is_same_type<Q,T_i>::value;
}; };
// allow the construction of types that are listed tuple. If a disallowed type // allow the construction of types that are listed tuple. If a disallowed type
// construction is written, a method involving this type is created. The // construction is written, a method involving this type is created. The
// type has no definition, so a syntax error is generated. // type has no definition, so a syntax error is generated.
template<typename T> struct ERROR_Type_Not_allowed_In_Tagged_Msg_Not_Member _Of_Tuple; template<typename T> struct ERROR_Type_Not_allowed_In_Tagged_Msg_Not_Member _Of_Tuple;
template<typename T, bool BUILD_IT> struct do_if; template<typename T, bool BUILD_IT> struct do_if;
template<typename T> template<typename T>
struct do_if<T, true> { struct do_if<T, true> {
skipping to change at line 390 skipping to change at line 386
// //
// the object can only be tested for type, and a read-only reference can be fetched by cast_to<T>(). // the object can only be tested for type, and a read-only reference can be fetched by cast_to<T>().
using tbb::internal::punned_cast; using tbb::internal::punned_cast;
struct tagged_null_type {}; struct tagged_null_type {};
template<typename TagType, typename T0, typename T1=tagged_null_type, typen ame T2=tagged_null_type, typename T3=tagged_null_type, template<typename TagType, typename T0, typename T1=tagged_null_type, typen ame T2=tagged_null_type, typename T3=tagged_null_type,
typename T4=tagged_null_type, typename T5=tagged _null_type, typename T6=tagged_null_type, typename T4=tagged_null_type, typename T5=tagged _null_type, typename T6=tagged_null_type,
typename T7=tagged_null_type, typename T8=tagged _null_type, typename T9=tagged_null_type> typename T7=tagged_null_type, typename T8=tagged _null_type, typename T9=tagged_null_type>
class tagged_msg { class tagged_msg {
typedef tbb::flow::tuple<T0, T1, T2, T3, T4 typedef tbb::flow::tuple<T0, T1, T2, T3, T4
//TODO: Should we reject lists longer than a tuple can ho ld?
#if __TBB_VARIADIC_MAX >= 6 #if __TBB_VARIADIC_MAX >= 6
, T5 , T5
#endif #endif
#if __TBB_VARIADIC_MAX >= 7 #if __TBB_VARIADIC_MAX >= 7
, T6 , T6
#endif #endif
#if __TBB_VARIADIC_MAX >= 8 #if __TBB_VARIADIC_MAX >= 8
, T7 , T7
#endif #endif
#if __TBB_VARIADIC_MAX >= 9 #if __TBB_VARIADIC_MAX >= 9
skipping to change at line 488 skipping to change at line 485
template<typename V> template<typename V>
const V& cast_to() const {return my_msg.template variant_cast_to<V>();} const V& cast_to() const {return my_msg.template variant_cast_to<V>();}
template<typename V> template<typename V>
bool is_a() const {return my_msg.template variant_is_a<V>();} bool is_a() const {return my_msg.template variant_is_a<V>();}
bool is_default_constructed() const {return my_msg.variant_is_default_c onstructed();} bool is_default_constructed() const {return my_msg.variant_is_default_c onstructed();}
}; //class tagged_msg }; //class tagged_msg
// template to simplify cast and test for tagged_msg in template contexts // template to simplify cast and test for tagged_msg in template contexts
template<typename T, typename V> template<typename V, typename T>
const T& cast_to(V const &v) { return v.template cast_to<T>(); } const V& cast_to(T const &t) { return t.template cast_to<V>(); }
template<typename T, typename V> template<typename V, typename T>
bool is_a(V const &v) { return v.template is_a<T>(); } bool is_a(T const &t) { return t.template is_a<V>(); }
} // namespace internal } // namespace internal
#endif /* __TBB__flow_graph_types_impl_H */ #endif /* __TBB__flow_graph_types_impl_H */
 End of changes. 6 change blocks. 
12 lines changed or deleted 7 lines changed or added


 _tbb_strings.h   _tbb_strings.h 
skipping to change at line 66 skipping to change at line 66
TBB_STRING_RESOURCE(FLOW_OUTPUT_PORT_3, "output_port_3") TBB_STRING_RESOURCE(FLOW_OUTPUT_PORT_3, "output_port_3")
TBB_STRING_RESOURCE(FLOW_OUTPUT_PORT_4, "output_port_4") TBB_STRING_RESOURCE(FLOW_OUTPUT_PORT_4, "output_port_4")
TBB_STRING_RESOURCE(FLOW_OUTPUT_PORT_5, "output_port_5") TBB_STRING_RESOURCE(FLOW_OUTPUT_PORT_5, "output_port_5")
TBB_STRING_RESOURCE(FLOW_OUTPUT_PORT_6, "output_port_6") TBB_STRING_RESOURCE(FLOW_OUTPUT_PORT_6, "output_port_6")
TBB_STRING_RESOURCE(FLOW_OUTPUT_PORT_7, "output_port_7") TBB_STRING_RESOURCE(FLOW_OUTPUT_PORT_7, "output_port_7")
TBB_STRING_RESOURCE(FLOW_OUTPUT_PORT_8, "output_port_8") TBB_STRING_RESOURCE(FLOW_OUTPUT_PORT_8, "output_port_8")
TBB_STRING_RESOURCE(FLOW_OUTPUT_PORT_9, "output_port_9") TBB_STRING_RESOURCE(FLOW_OUTPUT_PORT_9, "output_port_9")
TBB_STRING_RESOURCE(FLOW_OBJECT_NAME, "object_name") TBB_STRING_RESOURCE(FLOW_OBJECT_NAME, "object_name")
TBB_STRING_RESOURCE(FLOW_NULL, "null") TBB_STRING_RESOURCE(FLOW_NULL, "null")
TBB_STRING_RESOURCE(FLOW_INDEXER_NODE, "indexer_node") TBB_STRING_RESOURCE(FLOW_INDEXER_NODE, "indexer_node")
TBB_STRING_RESOURCE(FLOW_COMPOSITE_NODE, "composite_node")
 End of changes. 1 change blocks. 
0 lines changed or deleted 0 lines changed or added


 concurrent_vector.h   concurrent_vector.h 
skipping to change at line 965 skipping to change at line 965
const_reverse_iterator rbegin() const {return const_reverse_iterator(en d());} const_reverse_iterator rbegin() const {return const_reverse_iterator(en d());}
//! reverse end const iterator //! reverse end const iterator
const_reverse_iterator rend() const {return const_reverse_iterator(begi n());} const_reverse_iterator rend() const {return const_reverse_iterator(begi n());}
//! reverse start const iterator //! reverse start const iterator
const_reverse_iterator crbegin() const {return const_reverse_iterator(e nd());} const_reverse_iterator crbegin() const {return const_reverse_iterator(e nd());}
//! reverse end const iterator //! reverse end const iterator
const_reverse_iterator crend() const {return const_reverse_iterator(beg in());} const_reverse_iterator crend() const {return const_reverse_iterator(beg in());}
//! the first item //! the first item
reference front() { reference front() {
__TBB_ASSERT( size()>0, NULL); __TBB_ASSERT( size()>0, NULL);
return (my_segment[0].template load<relaxed>().template pointer<T>( const segment_value_t& segment_value = my_segment[0].template load<
))[0]; relaxed>();
return (segment_value.template pointer<T>())[0];
} }
//! the first item const //! the first item const
const_reference front() const { const_reference front() const {
__TBB_ASSERT( size()>0, NULL); __TBB_ASSERT( size()>0, NULL);
return static_cast<const T*>(my_segment[0].array)[0]; const segment_value_t& segment_value = my_segment[0].template load<
relaxed>();
return (segment_value.template pointer<const T>())[0];
} }
//! the last item //! the last item
reference back() { reference back() {
__TBB_ASSERT( size()>0, NULL); __TBB_ASSERT( size()>0, NULL);
return internal_subscript( size()-1 ); return internal_subscript( size()-1 );
} }
//! the last item const //! the last item const
const_reference back() const { const_reference back() const {
__TBB_ASSERT( size()>0, NULL); __TBB_ASSERT( size()>0, NULL);
return internal_subscript( size()-1 ); return internal_subscript( size()-1 );
 End of changes. 2 change blocks. 
3 lines changed or deleted 6 lines changed or added


 enumerable_thread_specific.h   enumerable_thread_specific.h 
skipping to change at line 30 skipping to change at line 30
#ifndef __TBB_enumerable_thread_specific_H #ifndef __TBB_enumerable_thread_specific_H
#define __TBB_enumerable_thread_specific_H #define __TBB_enumerable_thread_specific_H
#include "concurrent_vector.h" #include "concurrent_vector.h"
#include "tbb_thread.h" #include "tbb_thread.h"
#include "tbb_allocator.h" #include "tbb_allocator.h"
#include "tbb_profiling.h" #include "tbb_profiling.h"
#include "cache_aligned_allocator.h" #include "cache_aligned_allocator.h"
#include "aligned_space.h" #include "aligned_space.h"
#include "internal/_template_helpers.h"
#include <string.h> // for memcpy #include <string.h> // for memcpy
#if _WIN32||_WIN64 #if _WIN32||_WIN64
#include "machine/windows_api.h" #include "machine/windows_api.h"
#else #else
#include <pthread.h> #include <pthread.h>
#endif #endif
#define __TBB_ETS_USE_CPP11 \
(__TBB_CPP11_RVALUE_REF_PRESENT && __TBB_CPP11_VARIADIC_TEMPLATES_PRESE
NT \
&& __TBB_CPP11_DECLTYPE_PRESENT && __TBB_CPP11_LAMBDAS_PRESENT)
namespace tbb { namespace tbb {
//! enum for selecting between single key and key-per-instance versions //! enum for selecting between single key and key-per-instance versions
enum ets_key_usage_type { ets_key_per_instance, ets_no_key }; enum ets_key_usage_type { ets_key_per_instance, ets_no_key };
namespace interface6 { namespace interface6 {
// Forward declaration to use in internal classes
template <typename T, typename Allocator, ets_key_usage_type ETS_key_ty
pe>
class enumerable_thread_specific;
//! @cond //! @cond
namespace internal { namespace internal {
using namespace tbb::internal; using namespace tbb::internal;
template<ets_key_usage_type ETS_key_type> template<ets_key_usage_type ETS_key_type>
class ets_base: tbb::internal::no_copy { class ets_base: tbb::internal::no_copy {
protected: protected:
#if _WIN32||_WIN64 #if _WIN32||_WIN64
typedef DWORD key_type; typedef DWORD key_type;
skipping to change at line 82 skipping to change at line 91
return h>>(8*sizeof(size_t)-lg_size); return h>>(8*sizeof(size_t)-lg_size);
} }
}; };
struct slot { struct slot {
key_type key; key_type key;
void* ptr; void* ptr;
bool empty() const {return !key;} bool empty() const {return !key;}
bool match( key_type k ) const {return key==k;} bool match( key_type k ) const {return key==k;}
bool claim( key_type k ) { bool claim( key_type k ) {
__TBB_ASSERT(sizeof(tbb::atomic<key_type>)==sizeof(key_ type), NULL); __TBB_ASSERT(sizeof(tbb::atomic<key_type>)==sizeof(key_ type), NULL);
// TODO: maybe claim ptr, because key_type is not guara nteed to match word size
return tbb::internal::punned_cast<tbb::atomic<key_type> *>(&key)->compare_and_swap(k,0)==0; return tbb::internal::punned_cast<tbb::atomic<key_type> *>(&key)->compare_and_swap(k,0)==0;
} }
}; };
#if __TBB_PROTECTED_NESTED_CLASS_BROKEN #if __TBB_PROTECTED_NESTED_CLASS_BROKEN
protected: protected:
#endif #endif
static key_type key_of_current_thread() { static key_type key_of_current_thread() {
// TODO: replace key_type with tbb::tbb_thread::id
tbb::tbb_thread::id id = tbb::this_tbb_thread::get_id(); tbb::tbb_thread::id id = tbb::this_tbb_thread::get_id();
key_type k; key_type k;
memcpy( &k, &id, sizeof(k) ); memcpy( &k, &id, sizeof(k) );
return k; return k;
} }
//! Root of linked list of arrays of decreasing size. //! Root of linked list of arrays of decreasing size.
/** NULL if and only if my_count==0. /** NULL if and only if my_count==0.
Each array in the list is half the size of its predecessor. */ Each array in the list is half the size of its predecessor. */
atomic<array*> my_root; atomic<array*> my_root;
skipping to change at line 118 skipping to change at line 129
std::memset( a+1, 0, n*sizeof(slot) ); std::memset( a+1, 0, n*sizeof(slot) );
return a; return a;
} }
void free(array* a) { void free(array* a) {
size_t n = 1<<(a->lg_size); size_t n = 1<<(a->lg_size);
free_array( (void *)a, size_t(sizeof(array)+n*sizeof(slot)) ); free_array( (void *)a, size_t(sizeof(array)+n*sizeof(slot)) );
} }
static size_t hash( key_type k ) { static size_t hash( key_type k ) {
// Multiplicative hashing. Client should use *upper* bits. // Multiplicative hashing. Client should use *upper* bits.
// casts required for Mac gcc4.* compiler // casts required for Mac gcc4.* compiler
// TODO: casting of key_type to uintptr_t is not portable; implement and use hashing of thread::id
return uintptr_t(k)*tbb::internal::select_size_t_constant<0 x9E3779B9,0x9E3779B97F4A7C15ULL>::value; return uintptr_t(k)*tbb::internal::select_size_t_constant<0 x9E3779B9,0x9E3779B97F4A7C15ULL>::value;
} }
ets_base() {my_root=NULL; my_count=0;} ets_base() {my_root=NULL; my_count=0;}
virtual ~ets_base(); // g++ complains if this is not virtual.. . virtual ~ets_base(); // g++ complains if this is not virtual.. .
void* table_lookup( bool& exists ); void* table_lookup( bool& exists );
void table_clear(); void table_clear();
// table_find is used in copying ETS, so is not used in concurr ent context. So // table_find is used in copying ETS, so is not used in concurr ent context. So
// we don't need itt annotations for it. // we don't need itt annotations for it.
slot& table_find( key_type k ) { slot& table_find( key_type k ) {
skipping to change at line 352 skipping to change at line 364
enumerable_thread_specific_iterator &operator-=( ptrdiff_t offs et ) { enumerable_thread_specific_iterator &operator-=( ptrdiff_t offs et ) {
my_index -= offset; my_index -= offset;
my_value = NULL; my_value = NULL;
return *this; return *this;
} }
Value& operator*() const { Value& operator*() const {
Value* value = my_value; Value* value = my_value;
if( !value ) { if( !value ) {
value = my_value = reinterpret_cast<Value *>(&(*my_cont ainer)[my_index].value); value = my_value = (*my_container)[my_index].value();
} }
__TBB_ASSERT( value==reinterpret_cast<Value *>(&(*my_contai ner)[my_index].value), "corrupt cache" ); __TBB_ASSERT( value==(*my_container)[my_index].value(), "co rrupt cache" );
return *value; return *value;
} }
Value& operator[]( ptrdiff_t k ) const { Value& operator[]( ptrdiff_t k ) const {
return (*my_container)[my_index + k].value; return (*my_container)[my_index + k].value;
} }
Value* operator->() const {return &operator*();} Value* operator->() const {return &operator*();}
enumerable_thread_specific_iterator& operator++() { enumerable_thread_specific_iterator& operator++() {
skipping to change at line 589 skipping to change at line 601
} }
// != // !=
template<typename SegmentedContainer, typename T, typename U> template<typename SegmentedContainer, typename T, typename U>
bool operator!=( const segmented_iterator<SegmentedContainer,T>& i, bool operator!=( const segmented_iterator<SegmentedContainer,T>& i,
const segmented_iterator<SegmentedContainer,U>& j ) { const segmented_iterator<SegmentedContainer,U>& j ) {
return !(i==j); return !(i==j);
} }
template<typename T> template<typename T>
struct destruct_only: tbb::internal::no_copy {
tbb::aligned_space<T> value;
~destruct_only() {value.begin()[0].~T();}
};
template<typename T>
struct construct_by_default: tbb::internal::no_assign { struct construct_by_default: tbb::internal::no_assign {
void construct(void*where) {new(where) T();} // C++ note: the ( ) in T() ensure zero initialization. void construct(void*where) {new(where) T();} // C++ note: the ( ) in T() ensure zero initialization.
construct_by_default( int ) {} construct_by_default( int ) {}
}; };
template<typename T> template<typename T>
struct construct_by_exemplar: tbb::internal::no_assign { struct construct_by_exemplar: tbb::internal::no_assign {
const T exemplar; const T exemplar;
void construct(void*where) {new(where) T(exemplar);} void construct(void*where) {new(where) T(exemplar);}
construct_by_exemplar( const T& t ) : exemplar(t) {} construct_by_exemplar( const T& t ) : exemplar(t) {}
#if __TBB_ETS_USE_CPP11
construct_by_exemplar( T&& t ) : exemplar(std::move(t)) {}
#endif
}; };
template<typename T, typename Finit> template<typename T, typename Finit>
struct construct_by_finit: tbb::internal::no_assign { struct construct_by_finit: tbb::internal::no_assign {
Finit f; Finit f;
void construct(void* where) {new(where) T(f());} void construct(void* where) {new(where) T(f());}
construct_by_finit( const Finit& f_ ) : f(f_) {} construct_by_finit( const Finit& f_ ) : f(f_) {}
#if __TBB_ETS_USE_CPP11
construct_by_finit( Finit&& f_ ) : f(std::move(f_)) {}
#endif
}; };
#if __TBB_ETS_USE_CPP11
template<typename T, typename... P>
struct construct_by_args: tbb::internal::no_assign {
internal::stored_pack<P...> pack;
void construct(void* where) {
internal::call( [where](const typename strip<P>::type&... a
rgs ){
new(where) T(args...);
}, pack );
}
construct_by_args( P&& ... args ) : pack(std::forward<P>(args).
..) {}
};
#endif
// storage for initialization function pointer // storage for initialization function pointer
template<typename T> template<typename T>
class callback_base { class callback_base {
public: public:
// Clone *this // Clone *this
virtual callback_base* clone() = 0; virtual callback_base* clone() const = 0;
// Destruct and free *this // Destruct and free *this
virtual void destroy() = 0; virtual void destroy() = 0;
// Need virtual destructor to satisfy GCC compiler warning // Need virtual destructor to satisfy GCC compiler warning
virtual ~callback_base() { } virtual ~callback_base() { }
// Construct T at where // Construct T at where
virtual void construct(void* where) = 0; virtual void construct(void* where) = 0;
}; };
template <typename T, typename Constructor> template <typename T, typename Constructor>
class callback_leaf: public callback_base<T>, Constructor { class callback_leaf: public callback_base<T>, Constructor {
#if __TBB_ETS_USE_CPP11
template<typename... P> callback_leaf( P&& ... params ) : Const
ructor(std::forward<P>(params)...) {}
#else
template<typename X> callback_leaf( const X& x ) : Constructor( x) {} template<typename X> callback_leaf( const X& x ) : Constructor( x) {}
#endif
typedef typename tbb::tbb_allocator<callback_leaf> my_allocator _type; typedef typename tbb::tbb_allocator<callback_leaf> my_allocator _type;
/*override*/ callback_base<T>* clone() { /*override*/ callback_base<T>* clone() const {
return make(*this); return make(*this);
} }
/*override*/ void destroy() { /*override*/ void destroy() {
my_allocator_type().destroy(this); my_allocator_type().destroy(this);
my_allocator_type().deallocate(this,1); my_allocator_type().deallocate(this,1);
} }
/*override*/ void construct(void* where) { /*override*/ void construct(void* where) {
Constructor::construct(where); Constructor::construct(where);
} }
public: public:
#if __TBB_ETS_USE_CPP11
template<typename... P>
static callback_base<T>* make( P&& ... params ) {
void* where = my_allocator_type().allocate(1);
return new(where) callback_leaf( std::forward<P>(params)...
);
}
#else
template<typename X> template<typename X>
static callback_base<T>* make( const X& x ) { static callback_base<T>* make( const X& x ) {
void* where = my_allocator_type().allocate(1); void* where = my_allocator_type().allocate(1);
return new(where) callback_leaf(x); return new(where) callback_leaf(x);
} }
#endif
}; };
//! Template for adding padding in order to avoid false sharing //! Template for recording construction of objects in table
/** ModularSize should be sizeof(U) modulo the cache line size. /** All maintenance of the space will be done explicitly on push_ba
All maintenance of the space will be done explicitly on push_ba ck,
ck,
and all thread local copies must be destroyed before the concur rent and all thread local copies must be destroyed before the concur rent
vector is deleted. vector is deleted.
The flag is_built is initialized to false. When the local is
successfully-constructed, set the flag to true. If the constru
ctor
throws, the flag will be false.
*/ */
template<typename U, size_t ModularSize> template<typename U>
struct ets_element { struct ets_element {
ets_element() { /* avoid cl warning C4345 about default initial tbb::aligned_space<U> my_space;
ization of POD types */ } bool is_built;
char value[ModularSize==0 ? sizeof(U) : sizeof(U)+(tbb::interna ets_element() { is_built = false; } // not currently-built
l::NFS_MaxLineSize-ModularSize)]; U *value() { return my_space.begin(); }
void unconstruct() { void unconstruct() {
tbb::internal::punned_cast<U*>(&value)->~U(); if(is_built) {
} my_space.begin()->~U();
is_built = false;
}
}
~ets_element() {unconstruct();}
};
// A predicate that can be used for a compile-time compatibility ch
eck of ETS instances
// Ideally, it should have been declared inside the ETS class, but
unfortunately
// in that case VS2013 does not enable the variadic constructor.
template<typename T, typename ETS> struct is_compatible_ets { stati
c const bool value = false; };
template<typename T, typename U, typename A, ets_key_usage_type C>
struct is_compatible_ets< T, enumerable_thread_specific<U,A,C> > {
static const bool value = internal::is_same_type<T,U>::value; };
#if __TBB_ETS_USE_CPP11
// A predicate that checks whether, for a variable 'foo' of type T,
foo() is a valid expression
template <typename T>
class is_callable_no_args {
private:
typedef char yes[1];
typedef char no [2];
template<typename U> static yes& decide( decltype(declval<U>()(
))* );
template<typename U> static no& decide(...);
public:
static const bool value = (sizeof(decide<T>(NULL)) == sizeof(ye
s));
}; };
#endif
} // namespace internal } // namespace internal
//! @endcond //! @endcond
//! The enumerable_thread_specific container //! The enumerable_thread_specific container
/** enumerable_thread_specific has the following properties: /** enumerable_thread_specific has the following properties:
- thread-local copies are lazily created, with default, exemplar or function initialization. - thread-local copies are lazily created, with default, exemplar or function initialization.
- thread-local copies do not move (during lifetime, and excepting c lear()) so the address of a copy is invariant. - thread-local copies do not move (during lifetime, and excepting c lear()) so the address of a copy is invariant.
- the contained objects need not have operator=() defined if combin e is not used. - the contained objects need not have operator=() defined if combin e is not used.
- enumerable_thread_specific containers may be copy-constructed or assigned. - enumerable_thread_specific containers may be copy-constructed or assigned.
- thread-local copies can be managed by hash-table, or can be acces sed via TLS storage for speed. - thread-local copies can be managed by hash-table, or can be acces sed via TLS storage for speed.
- outside of parallel contexts, the contents of all thread-local co pies are accessible by iterator or using combine or combine_each methods - outside of parallel contexts, the contents of all thread-local co pies are accessible by iterator or using combine or combine_each methods
@par Segmented iterator @par Segmented iterator
When the thread-local objects are containers with input_iterators d efined, a segmented iterator may When the thread-local objects are containers with input_iterators d efined, a segmented iterator may
be used to iterate over all the elements of all thread-local copies . be used to iterate over all the elements of all thread-local copies .
@par combine and combine_each @par combine and combine_each
- Both methods are defined for enumerable_thread_specific. - Both methods are defined for enumerable_thread_specific.
- combine() requires the the type T have operator=() defined. - combine() requires the type T have operator=() defined.
- neither method modifies the contents of the object (though there is no guarantee that the applied methods do not modify the object.) - neither method modifies the contents of the object (though there is no guarantee that the applied methods do not modify the object.)
- Both are evaluated in serial context (the methods are assumed to be non-benign.) - Both are evaluated in serial context (the methods are assumed to be non-benign.)
@ingroup containers */ @ingroup containers */
template <typename T, template <typename T,
typename Allocator=cache_aligned_allocator<T>, typename Allocator=cache_aligned_allocator<T>,
ets_key_usage_type ETS_key_type=ets_no_key > ets_key_usage_type ETS_key_type=ets_no_key >
class enumerable_thread_specific: internal::ets_base<ETS_key_type> { class enumerable_thread_specific: internal::ets_base<ETS_key_type> {
template<typename U, typename A, ets_key_usage_type C> friend class enumerable_thread_specific; template<typename U, typename A, ets_key_usage_type C> friend class enumerable_thread_specific;
typedef internal::ets_element<T,sizeof(T)%tbb::internal::NFS_MaxLin eSize> padded_element; typedef internal::padded< internal::ets_element<T> > padded_element ;
//! A generic range, used to create range objects from the iterator s //! A generic range, used to create range objects from the iterator s
template<typename I> template<typename I>
class generic_range_type: public blocked_range<I> { class generic_range_type: public blocked_range<I> {
public: public:
typedef T value_type; typedef T value_type;
typedef T& reference; typedef T& reference;
typedef const T& const_reference; typedef const T& const_reference;
typedef I iterator; typedef I iterator;
typedef ptrdiff_t difference_type; typedef ptrdiff_t difference_type;
skipping to change at line 724 skipping to change at line 792
}; };
typedef typename Allocator::template rebind< padded_element >::othe r padded_allocator_type; typedef typename Allocator::template rebind< padded_element >::othe r padded_allocator_type;
typedef tbb::concurrent_vector< padded_element, padded_allocator_ty pe > internal_collection_type; typedef tbb::concurrent_vector< padded_element, padded_allocator_ty pe > internal_collection_type;
internal::callback_base<T> *my_construct_callback; internal::callback_base<T> *my_construct_callback;
internal_collection_type my_locals; internal_collection_type my_locals;
/*override*/ void* create_local() { /*override*/ void* create_local() {
void* lref = &*my_locals.grow_by(1); padded_element* lref = &*my_locals.grow_by(1);
my_construct_callback->construct(lref); my_construct_callback->construct(lref->value());
lref->is_built = true;
return lref; return lref;
} }
void unconstruct_locals() { void unconstruct_locals() {
for(typename internal_collection_type::iterator cvi = my_locals .begin(); cvi != my_locals.end(); ++cvi) { for(typename internal_collection_type::iterator cvi = my_locals .begin(); cvi != my_locals.end(); ++cvi) {
cvi->unconstruct(); cvi->unconstruct();
} }
} }
typedef typename Allocator::template rebind< uintptr_t >::other arr ay_allocator_type; typedef typename Allocator::template rebind< uintptr_t >::other arr ay_allocator_type;
skipping to change at line 774 skipping to change at line 843
// Parallel range types // Parallel range types
typedef generic_range_type< iterator > range_type; typedef generic_range_type< iterator > range_type;
typedef generic_range_type< const_iterator > const_range_type; typedef generic_range_type< const_iterator > const_range_type;
//! Default constructor. Each local instance of T is default const ructed. //! Default constructor. Each local instance of T is default const ructed.
enumerable_thread_specific() : my_construct_callback( enumerable_thread_specific() : my_construct_callback(
internal::callback_leaf<T,internal::construct_by_default<T> >:: make(/*dummy argument*/0) internal::callback_leaf<T,internal::construct_by_default<T> >:: make(/*dummy argument*/0)
){} ){}
//! Constructor with initializer functor. Each local instance of T is constructed by T(finit()). //! Constructor with initializer functor. Each local instance of T is constructed by T(finit()).
template <typename Finit> template <typename Finit
#if __TBB_ETS_USE_CPP11
, typename = typename internal::enable_if<internal::is_ca
llable_no_args<typename internal::strip<Finit>::type>::value>::type
#endif
>
enumerable_thread_specific( Finit finit ) : my_construct_callback( enumerable_thread_specific( Finit finit ) : my_construct_callback(
internal::callback_leaf<T,internal::construct_by_finit<T,Finit> >::make( finit ) internal::callback_leaf<T,internal::construct_by_finit<T,Finit> >::make( tbb::internal::move(finit) )
){} ){}
//! Constructor with exemplar. Each local instance of T is copy-con structed from the exemplar. //! Constructor with exemplar. Each local instance of T is copy-con structed from the exemplar.
enumerable_thread_specific( const T& exemplar ) : my_construct_call back( enumerable_thread_specific( const T& exemplar ) : my_construct_call back(
internal::callback_leaf<T,internal::construct_by_exemplar<T> >: :make( exemplar ) internal::callback_leaf<T,internal::construct_by_exemplar<T> >: :make( exemplar )
){} ){}
#if __TBB_ETS_USE_CPP11
enumerable_thread_specific( T&& exemplar ) : my_construct_callback(
internal::callback_leaf<T,internal::construct_by_exemplar<T> >:
:make( std::move(exemplar) )
){}
//! Variadic constructor with initializer arguments. Each local in
stance of T is constructed by T(args...)
template <typename P1, typename... P,
typename = typename internal::enable_if<!internal::is_cal
lable_no_args<typename internal::strip<P1>::type>::value
&& !internal::is_
compatible_ets<T, typename internal::strip<P1>::type>::value
&& !internal::is_
same_type<T, typename internal::strip<P1>::type>::value
>::type>
enumerable_thread_specific( P1&& arg1, P&& ... args ) : my_construc
t_callback(
internal::callback_leaf<T,internal::construct_by_args<T,P1,P...
> >::make( std::forward<P1>(arg1), std::forward<P>(args)... )
){}
#endif
//! Destructor //! Destructor
~enumerable_thread_specific() { ~enumerable_thread_specific() {
my_construct_callback->destroy(); my_construct_callback->destroy();
this->clear(); // deallocation before the derived class is fin ished destructing this->clear(); // deallocation before the derived class is fin ished destructing
// So free(array *) is still accessible // So free(array *) is still accessible
} }
//! returns reference to local, discarding exists //! returns reference to local, discarding exists
reference local() { reference local() {
bool exists; bool exists;
skipping to change at line 852 skipping to change at line 941
template<typename Alloc, ets_key_usage_type Cachetype> template<typename Alloc, ets_key_usage_type Cachetype>
enumerable_thread_specific( const enumerable_thread_specific<T, All oc, Cachetype>& other ) : internal::ets_base<ETS_key_type> () enumerable_thread_specific( const enumerable_thread_specific<T, All oc, Cachetype>& other ) : internal::ets_base<ETS_key_type> ()
{ {
internal_copy(other); internal_copy(other);
} }
enumerable_thread_specific( const enumerable_thread_specific& other ) : internal::ets_base<ETS_key_type> () enumerable_thread_specific( const enumerable_thread_specific& other ) : internal::ets_base<ETS_key_type> ()
{ {
internal_copy(other); internal_copy(other);
} }
// TODO: add move constructors
private: private:
template<typename A2, ets_key_usage_type C2> template<typename A2, ets_key_usage_type C2>
enumerable_thread_specific & enumerable_thread_specific &
internal_assign(const enumerable_thread_specific<T, A2, C2>& other) { internal_assign(const enumerable_thread_specific<T, A2, C2>& other) {
if(static_cast<void *>( this ) != static_cast<const void *>( &o ther )) { if(static_cast<void *>( this ) != static_cast<const void *>( &o ther )) {
this->clear(); this->clear();
my_construct_callback->destroy(); my_construct_callback->destroy();
my_construct_callback = 0; my_construct_callback = 0;
skipping to change at line 879 skipping to change at line 969
// assignment // assignment
enumerable_thread_specific& operator=(const enumerable_thread_speci fic& other) { enumerable_thread_specific& operator=(const enumerable_thread_speci fic& other) {
return internal_assign(other); return internal_assign(other);
} }
template<typename Alloc, ets_key_usage_type Cachetype> template<typename Alloc, ets_key_usage_type Cachetype>
enumerable_thread_specific& operator=(const enumerable_thread_speci fic<T, Alloc, Cachetype>& other) enumerable_thread_specific& operator=(const enumerable_thread_speci fic<T, Alloc, Cachetype>& other)
{ {
return internal_assign(other); return internal_assign(other);
} }
// TODO: add move assignments
// combine_func_t has signature T(T,T) or T(const T&, const T&) // combine_func_t has signature T(T,T) or T(const T&, const T&)
template <typename combine_func_t> template <typename combine_func_t>
T combine(combine_func_t f_combine) { T combine(combine_func_t f_combine) {
if(begin() == end()) { if(begin() == end()) {
internal::destruct_only<T> location; internal::ets_element<T> location;
my_construct_callback->construct(location.value.begin()); my_construct_callback->construct(location.value());
return *location.value.begin(); location.is_built = true;
return *location.value();
} }
const_iterator ci = begin(); const_iterator ci = begin();
T my_result = *ci; T my_result = *ci;
while(++ci != end()) while(++ci != end())
my_result = f_combine( my_result, *ci ); my_result = f_combine( my_result, *ci );
return my_result; return my_result;
} }
// combine_func_t has signature void(T) or void(const T&) // combine_func_t takes T by value or by [const] reference, and ret urns nothing
template <typename combine_func_t> template <typename combine_func_t>
void combine_each(combine_func_t f_combine) { void combine_each(combine_func_t f_combine) {
for(const_iterator ci = begin(); ci != end(); ++ci) { for(iterator ci = begin(); ci != end(); ++ci) {
f_combine( *ci ); f_combine( *ci );
} }
} }
}; // enumerable_thread_specific }; // enumerable_thread_specific
template <typename T, typename Allocator, ets_key_usage_type ETS_key_ty pe> template <typename T, typename Allocator, ets_key_usage_type ETS_key_ty pe>
template<typename A2, ets_key_usage_type C2> template<typename A2, ets_key_usage_type C2>
void enumerable_thread_specific<T,Allocator,ETS_key_type>::internal_cop y( const enumerable_thread_specific<T, A2, C2>& other) { void enumerable_thread_specific<T,Allocator,ETS_key_type>::internal_cop y( const enumerable_thread_specific<T, A2, C2>& other) {
#if __TBB_ETS_USE_CPP11
__TBB_STATIC_ASSERT( (internal::is_compatible_ets<T, typename inter
nal::strip<decltype(other)>::type>::value), "Maybe is_compatible_ets works
incorrectly" );
#endif
// Initialize my_construct_callback first, so that it is valid even if rest of this routine throws an exception. // Initialize my_construct_callback first, so that it is valid even if rest of this routine throws an exception.
my_construct_callback = other.my_construct_callback->clone(); my_construct_callback = other.my_construct_callback->clone();
typedef internal::ets_base<ets_no_key> base; typedef internal::ets_base<ets_no_key> base;
__TBB_ASSERT(my_locals.size()==0,NULL); __TBB_ASSERT(my_locals.size()==0,NULL);
this->table_reserve_for_copy( other ); this->table_reserve_for_copy( other );
for( base::array* r=other.my_root; r; r=r->next ) { for( base::array* r=other.my_root; r; r=r->next ) {
for( size_t i=0; i<r->size(); ++i ) { for( size_t i=0; i<r->size(); ++i ) {
base::slot& s1 = r->at(i); base::slot& s1 = r->at(i);
if( !s1.empty() ) { if( !s1.empty() ) {
 End of changes. 36 change blocks. 
32 lines changed or deleted 149 lines changed or added


 flow_graph.h   flow_graph.h 
skipping to change at line 33 skipping to change at line 33
#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 "cache_aligned_allocator.h" #include "cache_aligned_allocator.h"
#include "tbb_exception.h" #include "tbb_exception.h"
#include "internal/_template_helpers.h"
#include "internal/_aggregator_impl.h" #include "internal/_aggregator_impl.h"
#include "tbb_profiling.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.
skipping to change at line 82 skipping to change at line 83
//! An enumeration the provides the two most common concurrency levels: unl imited and serial //! An enumeration the provides the two most common concurrency levels: unl imited and serial
enum concurrency { unlimited = 0, serial = 1 }; enum concurrency { unlimited = 0, serial = 1 };
namespace interface7 { namespace interface7 {
namespace internal { namespace internal {
template<typename T, typename M> class successor_cache; template<typename T, typename M> class successor_cache;
template<typename T, typename M> class broadcast_cache; template<typename T, typename M> class broadcast_cache;
template<typename T, typename M> class round_robin_cache; template<typename T, typename M> class round_robin_cache;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
template< typename C> class edge_container;
#endif
} }
//A generic null type
struct null_type {};
//! An empty class used for messages that mean "I'm done" //! An empty class used for messages that mean "I'm done"
class continue_msg {}; class continue_msg {};
template< typename T > class sender; template< typename T > class sender;
template< typename T > class receiver; template< typename T > class receiver;
class continue_receiver; class continue_receiver;
//! Pure virtual template class that defines a sender of messages of type T //! Pure virtual template class that defines a sender of messages of type T
template< typename T > template< typename T >
class sender { class sender {
skipping to change at line 123 skipping to change at line 131
virtual bool try_reserve( T & ) { return false; } virtual bool try_reserve( T & ) { return false; }
//! Releases the reserved item //! Releases the reserved item
virtual bool try_release( ) { return false; } virtual bool try_release( ) { return false; }
//! Consumes the reserved item //! Consumes the reserved item
virtual bool try_consume( ) { return false; } virtual bool try_consume( ) { return false; }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
//! interface to record edges for traversal & deletion //! interface to record edges for traversal & deletion
typedef typename internal::edge_container<successor_type>::edge_list_t ype successor_list_type;
virtual void internal_add_built_successor( successor_type & ) = 0 ; virtual void internal_add_built_successor( successor_type & ) = 0 ;
virtual void internal_delete_built_successor( successor_type & ) = 0 ; virtual void internal_delete_built_successor( successor_type & ) = 0 ;
virtual void copy_successors( std::vector<successor_type *> &) = 0 ; virtual void copy_successors( successor_list_type &) = 0 ;
virtual size_t successor_count() = 0 ; virtual size_t successor_count() = 0 ;
#endif #endif
}; };
template< typename T > class limiter_node; // needed for resetting decreme nter template< typename T > class limiter_node; // needed for resetting decreme nter
template< typename R, typename B > class run_and_put_task; template< typename R, typename B > class run_and_put_task;
static tbb::task * const SUCCESSFULLY_ENQUEUED = (task *)-1; static tbb::task * const SUCCESSFULLY_ENQUEUED = (task *)-1;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
skipping to change at line 202 skipping to change at line 211
virtual task *try_put_task(const T& t) = 0; virtual task *try_put_task(const T& t) = 0;
public: public:
//! Add a predecessor to the node //! Add a predecessor to the node
virtual bool register_predecessor( predecessor_type & ) { return false; } virtual bool register_predecessor( predecessor_type & ) { return false; }
//! Remove a predecessor from the node //! Remove a predecessor from the node
virtual bool remove_predecessor( predecessor_type & ) { return false; } virtual bool remove_predecessor( predecessor_type & ) { return false; }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef typename internal::edge_container<predecessor_type>::edge_list_ type predecessor_list_type;
virtual void internal_add_built_predecessor( predecessor_type & ) = 0; virtual void internal_add_built_predecessor( predecessor_type & ) = 0;
virtual void internal_delete_built_predecessor( predecessor_type & ) = 0; virtual void internal_delete_built_predecessor( predecessor_type & ) = 0;
virtual void copy_predecessors( std::vector<predecessor_type *> & ) = 0; virtual void copy_predecessors( predecessor_list_type & ) = 0;
virtual size_t predecessor_count() = 0; virtual size_t predecessor_count() = 0;
#endif #endif
protected: protected:
//! put receiver back in initial state //! put receiver back in initial state
template<typename U> friend class limiter_node; template<typename U> friend class limiter_node;
virtual void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags f = rf_rese t_protocol ) ) = 0; virtual void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags f = rf_rese t_protocol ) ) = 0;
template<typename TT, typename M> template<typename TT, typename M>
friend class internal::successor_cache; friend class internal::successor_cache;
virtual bool is_continue_receiver() { return false; } virtual bool is_continue_receiver() { return false; }
}; };
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
//* holder of edges both for caches and for those nodes which do not have p redecessor caches. //* holder of edges both for caches and for those nodes which do not have p redecessor caches.
// C == receiver< ... > or sender< ... >, depending. // C == receiver< ... > or sender< ... >, depending.
namespace internal {
template<typename C> template<typename C>
class edge_container { class edge_container {
public: public:
typedef std::vector<C *> edge_vector; typedef std::list<C *, tbb::tbb_allocator<C *> > edge_list_type;
void add_edge( C &s) { void add_edge( C &s) {
built_edges.push_back( &s ); built_edges.push_back( &s );
} }
void delete_edge( C &s) { void delete_edge( C &s) {
for ( typename edge_vector::iterator i = built_edges.begin(); i != built_edges.end(); ++i ) { for ( typename edge_list_type::iterator i = built_edges.begin(); i != built_edges.end(); ++i ) {
if ( *i == &s ) { if ( *i == &s ) {
(void)built_edges.erase(i); (void)built_edges.erase(i);
return; // only remove one predecessor per request return; // only remove one predecessor per request
} }
} }
} }
void copy_edges( edge_vector &v) { void copy_edges( edge_list_type &v) {
v = built_edges; v = built_edges;
} }
size_t edge_count() { size_t edge_count() {
return (size_t)(built_edges.size()); return (size_t)(built_edges.size());
} }
void clear() { void clear() {
built_edges.clear(); built_edges.clear();
} }
template< typename S > void sender_extract( S &s ); template< typename S > void sender_extract( S &s );
template< typename R > void receiver_extract( R &r ); template< typename R > void receiver_extract( R &r );
private: private:
edge_vector built_edges; edge_list_type built_edges;
}; };
} // namespace internal
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
//! Base class for receivers of completion messages //! Base class for receivers of completion messages
/** These receivers automatically reset, but cannot be explicitly waited on */ /** These receivers automatically reset, but cannot be explicitly waited on */
class continue_receiver : public receiver< continue_msg > { class continue_receiver : public receiver< continue_msg > {
public: public:
//! The input type //! The input type
typedef continue_msg input_type; typedef continue_msg input_type;
skipping to change at line 304 skipping to change at line 316
/** Does not check to see if the removal of the predecessor now makes t he current count /** Does not check to see if the removal of the predecessor now makes t he current count
exceed the new threshold. So removing a predecessor while the grap h is active can cause exceed the new threshold. So removing a predecessor while the grap h is active can cause
unexpected results. */ unexpected results. */
/* override */ bool remove_predecessor( predecessor_type & ) { /* override */ bool remove_predecessor( predecessor_type & ) {
spin_mutex::scoped_lock l(my_mutex); spin_mutex::scoped_lock l(my_mutex);
--my_predecessor_count; --my_predecessor_count;
return true; return true;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type; typedef receiver<input_type>::predecessor_list_type predecessor_list_ty pe;
/*override*/ void internal_add_built_predecessor( predecessor_type &s) { /*override*/ void internal_add_built_predecessor( predecessor_type &s) {
spin_mutex::scoped_lock l(my_mutex); spin_mutex::scoped_lock l(my_mutex);
my_built_predecessors.add_edge( s ); my_built_predecessors.add_edge( s );
} }
/*override*/ void internal_delete_built_predecessor( predecessor_type & s) { /*override*/ void internal_delete_built_predecessor( predecessor_type & s) {
spin_mutex::scoped_lock l(my_mutex); spin_mutex::scoped_lock l(my_mutex);
my_built_predecessors.delete_edge(s); my_built_predecessors.delete_edge(s);
} }
/*override*/ void copy_predecessors( predecessor_vector_type &v) { /*override*/ void copy_predecessors( predecessor_list_type &v) {
spin_mutex::scoped_lock l(my_mutex); spin_mutex::scoped_lock l(my_mutex);
my_built_predecessors.copy_edges(v); my_built_predecessors.copy_edges(v);
} }
/*override*/ size_t predecessor_count() { /*override*/ size_t predecessor_count() {
spin_mutex::scoped_lock l(my_mutex); spin_mutex::scoped_lock l(my_mutex);
return my_built_predecessors.edge_count(); return my_built_predecessors.edge_count();
} }
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
skipping to change at line 346 skipping to change at line 358
return SUCCESSFULLY_ENQUEUED; return SUCCESSFULLY_ENQUEUED;
else else
my_current_count = 0; my_current_count = 0;
} }
task * res = execute(); task * res = execute();
if(!res) return SUCCESSFULLY_ENQUEUED; if(!res) return SUCCESSFULLY_ENQUEUED;
return res; return res;
} }
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
edge_container<predecessor_type> my_built_predecessors; internal::edge_container<predecessor_type> my_built_predecessors;
#endif #endif
spin_mutex my_mutex; spin_mutex my_mutex;
int my_predecessor_count; int my_predecessor_count;
int my_current_count; int my_current_count;
int my_initial_predecessor_count; int my_initial_predecessor_count;
// the friend declaration in the base class did not eliminate the "prot ected class" // the friend declaration in the base class did not eliminate the "prot ected class"
// error in gcc 4.1.2 // error in gcc 4.1.2
template<typename U> friend class limiter_node; template<typename U> friend class limiter_node;
/*override*/void reset_receiver( __TBB_PFG_RESET_ARG(reset_flags f) ) /*override*/void reset_receiver( __TBB_PFG_RESET_ARG(reset_flags f) )
{ {
skipping to change at line 767 skipping to change at line 779
class source_node : public graph_node, public sender< Output > { class source_node : public graph_node, public sender< Output > {
protected: protected:
using graph_node::my_graph; using graph_node::my_graph;
public: public:
//! The type of the output message, which is complete //! The type of the output message, which is complete
typedef Output output_type; typedef Output output_type;
//! The type of successors of this node //! The type of successors of this node
typedef receiver< Output > successor_type; typedef receiver< Output > successor_type;
//Source node has no input type
typedef null_type input_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<successor_type *> successor_vector_type; typedef typename sender<output_type>::successor_list_type successor_lis t_type;
#endif #endif
//! 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);
skipping to change at line 836 skipping to change at line 851
/*override*/void internal_delete_built_successor( successor_type &r) { /*override*/void internal_delete_built_successor( successor_type &r) {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
my_successors.internal_delete_built_successor(r); my_successors.internal_delete_built_successor(r);
} }
/*override*/size_t successor_count() { /*override*/size_t successor_count() {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
return my_successors.successor_count(); return my_successors.successor_count();
} }
/*override*/void copy_successors(successor_vector_type &v) { /*override*/void copy_successors(successor_list_type &v) {
spin_mutex::scoped_lock l(my_mutex); spin_mutex::scoped_lock l(my_mutex);
my_successors.copy_successors(v); my_successors.copy_successors(v);
} }
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
//! Request an item from the node //! Request an item from the node
/*override */ bool try_get( output_type &v ) { /*override */ bool try_get( output_type &v ) {
spin_mutex::scoped_lock lock(my_mutex); spin_mutex::scoped_lock lock(my_mutex);
if ( my_reserved ) if ( my_reserved )
return false; return false;
skipping to change at line 998 skipping to change at line 1013
protected: protected:
using graph_node::my_graph; using graph_node::my_graph;
public: public:
typedef Input input_type; typedef Input input_type;
typedef Output output_type; typedef Output output_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
typedef internal::function_input<input_type,output_type,Allocator> fInp ut_type; typedef internal::function_input<input_type,output_type,Allocator> fInp ut_type;
typedef internal::function_output<output_type> fOutput_type; typedef internal::function_output<output_type> fOutput_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
using typename internal::function_input<Input,Output,Allocator>::predec using typename internal::function_input<Input,Output,Allocator>::predec
essor_vector_type; essor_list_type;
using typename internal::function_output<Output>::successor_vector_type using typename internal::function_output<Output>::successor_list_type;
;
#endif #endif
//! 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 cator>(g, concurrency, body) { graph_node(g), internal::function_input<input_type,output_type,Allo 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), 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 ); static_cast<sender<output_type> *>(this), this->my_body );
} }
skipping to change at line 1057 skipping to change at line 1072
using graph_node::my_graph; using graph_node::my_graph;
public: public:
typedef Input input_type; typedef Input input_type;
typedef Output output_type; typedef Output output_type;
typedef sender< input_type > predecessor_type; typedef sender< input_type > predecessor_type;
typedef receiver< output_type > successor_type; typedef receiver< output_type > successor_type;
typedef internal::function_input<input_type,output_type,Allocator> fInp ut_type; typedef internal::function_input<input_type,output_type,Allocator> fInp ut_type;
typedef internal::function_input_queue<input_type, Allocator> queue_typ e; typedef internal::function_input_queue<input_type, Allocator> queue_typ e;
typedef internal::function_output<output_type> fOutput_type; typedef internal::function_output<output_type> fOutput_type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
using typename internal::function_input<Input,Output,Allocator>::predec using typename internal::function_input<Input,Output,Allocator>::predec
essor_vector_type; essor_list_type;
using typename internal::function_output<Output>::successor_vector_type using typename internal::function_output<Output>::successor_list_type;
;
#endif #endif
//! 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), 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 ); static_cast<sender<output_type> *>(this), this->my_body );
} }
skipping to change at line 1122 skipping to change at line 1137
Output // the tuple providing the types Output // the tuple providing the types
>::type, >::type,
Allocator Allocator
> { > {
protected: protected:
using graph_node::my_graph; using graph_node::my_graph;
private: private:
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 null_type output_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, 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->gra ph_node::my_graph, static_cast<receiver<input_type> *>(this),
skipping to change at line 1161 skipping to change at line 1177
}; // 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 null_type output_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, 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->gra ph_node::my_graph, static_cast<receiver<input_type> *>(this),
skipping to change at line 1201 skipping to change at line 1218
//! split_node: accepts a tuple as input, forwards each element of the tupl e to its //! split_node: accepts a tuple as input, forwards each element of the tupl e to its
// successors. The node has unlimited concurrency, so though it is marked as // successors. The node has unlimited concurrency, so though it is marked as
// "rejecting" it does not reject inputs. // "rejecting" it does not reject inputs.
template<typename TupleType, typename Allocator=cache_aligned_allocator<Tup leType> > template<typename TupleType, typename Allocator=cache_aligned_allocator<Tup leType> >
class split_node : public multifunction_node<TupleType, TupleType, rejectin g, Allocator> { class split_node : public multifunction_node<TupleType, TupleType, rejectin g, Allocator> {
static const int N = tbb::flow::tuple_size<TupleType>::value; static const int N = tbb::flow::tuple_size<TupleType>::value;
typedef multifunction_node<TupleType,TupleType,rejecting,Allocator> bas e_type; typedef multifunction_node<TupleType,TupleType,rejecting,Allocator> bas e_type;
public: public:
typedef typename base_type::output_ports_type output_ports_type; typedef typename base_type::output_ports_type output_ports_type;
typedef typename base_type::output_type output_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()) {
skipping to change at line 1301 skipping to change at line 1319
template< typename T > template< typename T >
class overwrite_node : public graph_node, public receiver<T>, public sender <T> { class overwrite_node : public graph_node, public receiver<T>, public sender <T> {
protected: 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;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type; typedef typename receiver<input_type>::predecessor_list_type predecesso
typedef std::vector<successor_type *> successor_vector_type; r_list_type;
typedef typename sender<output_type>::successor_list_type successor_lis
t_type;
#endif #endif
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, tbb::internal::fgt_node( tbb::internal::FLOW_OVERWRITE_NODE, &this- >my_graph,
static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) ); 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 ) :
skipping to change at line 1369 skipping to change at line 1387
/*override*/void internal_delete_built_successor( successor_type &s) { /*override*/void internal_delete_built_successor( successor_type &s) {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
my_successors.internal_delete_built_successor(s); my_successors.internal_delete_built_successor(s);
} }
/*override*/size_t successor_count() { /*override*/size_t successor_count() {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
return my_successors.successor_count(); return my_successors.successor_count();
} }
/*override*/ void copy_successors(successor_vector_type &v) { /*override*/ void copy_successors(successor_list_type &v) {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
my_successors.copy_successors(v); my_successors.copy_successors(v);
} }
/*override*/ void internal_add_built_predecessor( predecessor_type &p) { /*override*/ void internal_add_built_predecessor( predecessor_type &p) {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
my_built_predecessors.add_edge(p); my_built_predecessors.add_edge(p);
} }
/*override*/ void internal_delete_built_predecessor( predecessor_type & p) { /*override*/ void internal_delete_built_predecessor( predecessor_type & p) {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
my_built_predecessors.delete_edge(p); my_built_predecessors.delete_edge(p);
} }
/*override*/size_t predecessor_count() { /*override*/size_t predecessor_count() {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
return my_built_predecessors.edge_count(); return my_built_predecessors.edge_count();
} }
/*override*/void copy_predecessors(predecessor_vector_type &v) { /*override*/void copy_predecessors(predecessor_list_type &v) {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
my_built_predecessors.copy_edges(v); my_built_predecessors.copy_edges(v);
} }
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
/* override */ bool try_get( input_type &v ) { /* override */ bool try_get( input_type &v ) {
spin_mutex::scoped_lock l( my_mutex ); spin_mutex::scoped_lock l( my_mutex );
if ( my_buffer_is_valid ) { if ( my_buffer_is_valid ) {
v = my_buffer; v = my_buffer;
return true; return true;
skipping to change at line 1440 skipping to change at line 1458
my_successors.reset(f); my_successors.reset(f);
if (f&rf_extract) { if (f&rf_extract) {
my_built_predecessors.receiver_extract(*this); my_built_predecessors.receiver_extract(*this);
} }
#endif #endif
} }
spin_mutex my_mutex; spin_mutex my_mutex;
internal::broadcast_cache< input_type, null_rw_mutex > my_successors; internal::broadcast_cache< input_type, null_rw_mutex > my_successors;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
edge_container<sender<input_type> > my_built_predecessors; internal::edge_container<predecessor_type> my_built_predecessors;
#endif #endif
input_type my_buffer; input_type my_buffer;
bool my_buffer_is_valid; bool my_buffer_is_valid;
/*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags /*f*/)) {} /*override*/void reset_receiver(__TBB_PFG_RESET_ARG(reset_flags /*f*/)) {}
}; // overwrite_node }; // overwrite_node
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;
skipping to change at line 1504 skipping to change at line 1522
template <typename T> template <typename T>
class broadcast_node : public graph_node, public receiver<T>, public sender <T> { class broadcast_node : public graph_node, public receiver<T>, public sender <T> {
protected: 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;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type; typedef typename receiver<input_type>::predecessor_list_type predecesso
typedef std::vector<successor_type *> successor_vector_type; r_list_type;
typedef typename sender<output_type>::successor_list_type successor_lis
t_type;
#endif #endif
private: private:
internal::broadcast_cache<input_type> my_successors; internal::broadcast_cache<input_type> my_successors;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
edge_container<predecessor_type> my_built_predecessors; internal::edge_container<predecessor_type> my_built_predecessors;
spin_mutex pred_mutex; spin_mutex pred_mutex;
#endif #endif
public: public:
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, tbb::internal::fgt_node( tbb::internal::FLOW_BROADCAST_NODE, &this- >my_graph,
static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) ); static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) );
} }
skipping to change at line 1561 skipping to change at line 1579
} }
/*override*/ void internal_delete_built_successor(successor_type &r) { /*override*/ void internal_delete_built_successor(successor_type &r) {
my_successors.internal_delete_built_successor(r); my_successors.internal_delete_built_successor(r);
} }
/*override*/ size_t successor_count() { /*override*/ size_t successor_count() {
return my_successors.successor_count(); return my_successors.successor_count();
} }
/*override*/ void copy_successors(successor_vector_type &v) { /*override*/ void copy_successors(successor_list_type &v) {
my_successors.copy_successors(v); my_successors.copy_successors(v);
} }
/*override*/ void internal_add_built_predecessor( predecessor_type &p) { /*override*/ void internal_add_built_predecessor( predecessor_type &p) {
my_built_predecessors.add_edge(p); my_built_predecessors.add_edge(p);
} }
/*override*/ void internal_delete_built_predecessor( predecessor_type & p) { /*override*/ void internal_delete_built_predecessor( predecessor_type & p) {
my_built_predecessors.delete_edge(p); my_built_predecessors.delete_edge(p);
} }
/*override*/ size_t predecessor_count() { /*override*/ size_t predecessor_count() {
return my_built_predecessors.edge_count(); return my_built_predecessors.edge_count();
} }
/*override*/ void copy_predecessors(predecessor_vector_type &v) { /*override*/ void copy_predecessors(predecessor_list_type &v) {
my_built_predecessors.copy_edges(v); my_built_predecessors.copy_edges(v);
} }
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
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;
//! build a task to run the successor if possible. Default is old beha vior. //! build a task to run the successor if possible. Default is old beha vior.
/*override*/ task *try_put_task(const T& t) { /*override*/ task *try_put_task(const T& t) {
skipping to change at line 1617 skipping to change at line 1635
class buffer_node : public graph_node, public internal::reservable_item_buf fer<T, A>, public receiver<T>, public sender<T> { class buffer_node : public graph_node, public internal::reservable_item_buf fer<T, A>, public receiver<T>, public sender<T> {
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;
typedef buffer_node<T, A> my_class; typedef buffer_node<T, A> my_class;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<predecessor_type *> predecessor_vector_type; typedef typename receiver<input_type>::predecessor_list_type predecesso
typedef std::vector<successor_type *> successor_vector_type; r_list_type;
typedef typename sender<output_type>::successor_list_type successor_lis
t_type;
#endif #endif
protected: protected:
typedef size_t size_type; typedef size_t size_type;
internal::round_robin_cache< T, null_rw_mutex > my_successors; internal::round_robin_cache< T, null_rw_mutex > my_successors;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
edge_container<predecessor_type> my_built_predecessors; internal::edge_container<predecessor_type> my_built_predecessors;
#endif #endif
friend class internal::forward_task_bypass< buffer_node< T, A > >; friend class internal::forward_task_bypass< buffer_node< T, A > >;
enum op_type {reg_succ, rem_succ, req_item, res_item, rel_res, con_res, put_item, try_fwd_task enum op_type {reg_succ, rem_succ, req_item, res_item, rel_res, con_res, put_item, try_fwd_task
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
, add_blt_succ, del_blt_succ, , add_blt_succ, del_blt_succ,
add_blt_pred, del_blt_pred, add_blt_pred, del_blt_pred,
blt_succ_cnt, blt_pred_cnt, blt_succ_cnt, blt_pred_cnt,
blt_succ_cpy, blt_pred_cpy // create vector copies of preds and s uccs blt_succ_cpy, blt_pred_cpy // create vector copies of preds and s uccs
skipping to change at line 1651 skipping to change at line 1669
class buffer_operation : public internal::aggregated_operation< buffer_ operation > { class buffer_operation : public internal::aggregated_operation< buffer_ operation > {
public: public:
char type; char type;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
task * ltask; task * ltask;
union { union {
input_type *elem; input_type *elem;
successor_type *r; successor_type *r;
predecessor_type *p; predecessor_type *p;
size_t cnt_val; size_t cnt_val;
successor_vector_type *svec; successor_list_type *svec;
predecessor_vector_type *pvec; predecessor_list_type *pvec;
}; };
#else #else
T *elem; T *elem;
task * ltask; task * ltask;
successor_type *r; successor_type *r;
#endif #endif
buffer_operation(const T& e, op_type t) : type(char(t)) buffer_operation(const T& e, op_type t) : type(char(t))
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
, ltask(NULL), elem(const _cast<T*>(&e)) , ltask(NULL), elem(const _cast<T*>(&e))
skipping to change at line 1941 skipping to change at line 1959
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.cnt_val; return op_data.cnt_val;
} }
/*override*/ size_t successor_count() { /*override*/ size_t successor_count() {
buffer_operation op_data(blt_succ_cnt); buffer_operation op_data(blt_succ_cnt);
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
return op_data.cnt_val; return op_data.cnt_val;
} }
/*override*/ void copy_predecessors( predecessor_vector_type &v ) { /*override*/ void copy_predecessors( predecessor_list_type &v ) {
buffer_operation op_data(blt_pred_cpy); buffer_operation op_data(blt_pred_cpy);
op_data.pvec = &v; op_data.pvec = &v;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
/*override*/ void copy_successors( successor_vector_type &v ) { /*override*/ void copy_successors( successor_list_type &v ) {
buffer_operation op_data(blt_succ_cpy); buffer_operation op_data(blt_succ_cpy);
op_data.svec = &v; op_data.svec = &v;
my_aggregator.execute(&op_data); my_aggregator.execute(&op_data);
} }
#endif #endif
//! Removes a successor. //! Removes a successor.
/** Removes successor r from the list of successors. /** Removes successor r from the list of successors.
It also calls r.remove_predecessor(*this) to remove this node as a predecessor. */ It also calls r.remove_predecessor(*this) to remove this node as a predecessor. */
/* override */ bool remove_successor( successor_type &r ) { /* override */ bool remove_successor( successor_type &r ) {
skipping to change at line 2487 skipping to change at line 2505
template< typename T > template< typename T >
class limiter_node : public graph_node, public receiver< T >, public sender < T > { class limiter_node : public graph_node, public receiver< T >, public sender < T > {
protected: 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;
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
typedef std::vector<successor_type *> successor_vector_type; typedef typename receiver<input_type>::predecessor_list_type predecesso
typedef std::vector<predecessor_type *> predecessor_vector_type; r_list_type;
typedef typename sender<output_type>::successor_list_type successor_lis
t_type;
#endif #endif
private: private:
size_t my_threshold; size_t my_threshold;
size_t my_count; //number of successful puts size_t my_count; //number of successful puts
size_t my_tries; //number of active put attempts size_t my_tries; //number of active put attempts
internal::reservable_predecessor_cache< T, spin_mutex > my_predecessors ; internal::reservable_predecessor_cache< T, spin_mutex > 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;
skipping to change at line 2652 skipping to change at line 2670
/*override*/void internal_add_built_successor(receiver<output_type> &sr c) { /*override*/void internal_add_built_successor(receiver<output_type> &sr c) {
my_successors.internal_add_built_successor(src); my_successors.internal_add_built_successor(src);
} }
/*override*/void internal_delete_built_successor(receiver<output_type> &src) { /*override*/void internal_delete_built_successor(receiver<output_type> &src) {
my_successors.internal_delete_built_successor(src); my_successors.internal_delete_built_successor(src);
} }
/*override*/size_t successor_count() { return my_successors.successor_c ount(); } /*override*/size_t successor_count() { return my_successors.successor_c ount(); }
/*override*/ void copy_successors(successor_vector_type &v) { /*override*/ void copy_successors(successor_list_type &v) {
my_successors.copy_successors(v); my_successors.copy_successors(v);
} }
/*override*/void internal_add_built_predecessor(sender<output_type> &sr c) { /*override*/void internal_add_built_predecessor(sender<output_type> &sr c) {
my_predecessors.internal_add_built_predecessor(src); my_predecessors.internal_add_built_predecessor(src);
} }
/*override*/void internal_delete_built_predecessor(sender<output_type> &src) { /*override*/void internal_delete_built_predecessor(sender<output_type> &src) {
my_predecessors.internal_delete_built_predecessor(src); my_predecessors.internal_delete_built_predecessor(src);
} }
/*override*/size_t predecessor_count() { return my_predecessors.predece ssor_count(); } /*override*/size_t predecessor_count() { return my_predecessors.predece ssor_count(); }
/*override*/ void copy_predecessors(predecessor_vector_type &v) { /*override*/ void copy_predecessors(predecessor_list_type &v) {
my_predecessors.copy_predecessors(v); my_predecessors.copy_predecessors(v);
} }
#endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */ #endif /* TBB_PREVIEW_FLOW_GRAPH_FEATURES */
//! Adds src to the list of cached predecessors. //! Adds src to the list of cached predecessors.
/* override */ bool register_predecessor( predecessor_type &src ) { /* override */ bool register_predecessor( predecessor_type &src ) {
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_tries < my_threshold && !my_successors.empty() & & tp ) { if ( my_count + my_tries < my_threshold && !my_successors.empty() & & tp ) {
skipping to change at line 2889 skipping to change at line 2907
/* override */ void set_name( const char *name ) { /* override */ void set_name( const char *name ) {
tbb::internal::fgt_node_desc( this, name ); tbb::internal::fgt_node_desc( this, name );
} }
#endif #endif
}; };
// indexer node // indexer node
#include "internal/_flow_graph_indexer_impl.h" #include "internal/_flow_graph_indexer_impl.h"
struct indexer_null_type {}; template<typename T0, typename T1=null_type, typename T2=null_type, typenam
e T3=null_type,
template<typename T0, typename T1=indexer_null_type, typename T2=indexer_nu typename T4=null_type, typename T5=null_type, typenam
ll_type, typename T3=indexer_null_type, e T6=null_type,
typename T4=indexer_null_type, typename T5=indexer_nu typename T7=null_type, typename T8=null_type, typenam
ll_type, typename T6=indexer_null_type, e T9=null_type> class indexer_node;
typename T7=indexer_null_type, typename T8=indexer_nu
ll_type, typename T9=indexer_null_type> class indexer_node;
//indexer node specializations //indexer node specializations
template<typename T0> template<typename T0>
class indexer_node<T0> : public internal::unfolded_indexer_node<tuple<T0> > { class indexer_node<T0> : public internal::unfolded_indexer_node<tuple<T0> > {
private: private:
static const int N = 1; static const int N = 1;
public: public:
typedef tuple<T0> InputTuple; typedef tuple<T0> InputTuple;
typedef typename internal::tagged_msg<size_t, T0> output_type; typedef typename internal::tagged_msg<size_t, T0> output_type;
typedef typename internal::unfolded_indexer_node<InputTuple> unfolded_t ype; typedef typename internal::unfolded_indexer_node<InputTuple> unfolded_t ype;
skipping to change at line 3171 skipping to change at line 3187
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 ) {
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
s.internal_add_built_predecessor(p); s.internal_add_built_predecessor(p);
p.internal_add_built_successor(s); p.internal_add_built_successor(s);
#endif #endif
p.register_successor( s ); p.register_successor( s );
tbb::internal::fgt_make_edge( &p, &s ); tbb::internal::fgt_make_edge( &p, &s );
} }
//! Makes an edge between a single predecessor and a single successor #if __TBB_PREVIEW_COMPOSITE_NODE
//Makes an edge from port 0 of a multi-output predecessor to port 0 of a mu
lti-input successor.
template< typename T, typename V,
bool = tbb::internal::is_same_type< typename tuple_element<0,type
name T::output_ports_type>::type,
typename tuple_element<0,type
name V::input_ports_type>::type
>::value >
inline void make_edge( T& output, V& input) {
make_edge(get<0>(output.output_ports()), get<0>(input.input_ports()));
}
//Makes an edge from port 0 of a multi-output predecessor to a receiver.
template< typename T, typename R,
bool = tbb::internal::is_same_type<typename tuple_element<0,typen
ame T::output_ports_type>::type, receiver<R> >::value >
inline void make_edge( T& output, receiver<R>& input) {
make_edge(get<0>(output.output_ports()), input);
}
//Makes an edge from a sender to port 0 of a multi-input successor.
template<typename S, typename V,
bool = tbb::internal::is_same_type<sender<S>, typename tuple_elem
ent<0,typename V::input_ports_type>::type >::value >
inline void make_edge( sender<S>& output, V& input) {
make_edge(output, get<0>(input.input_ports()));
}
#endif
//! Removes 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 );
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
// TODO: should we try to remove p from the predecessor list of s, in c ase the edge is reversed? // TODO: should we try to remove p from the predecessor list of s, in c ase the edge is reversed?
p.internal_delete_built_successor(s); p.internal_delete_built_successor(s);
s.internal_delete_built_predecessor(p); s.internal_delete_built_predecessor(p);
#endif #endif
tbb::internal::fgt_remove_edge( &p, &s ); tbb::internal::fgt_remove_edge( &p, &s );
} }
#if __TBB_PREVIEW_COMPOSITE_NODE
//Removes an edge between port 0 of a multi-output predecessor and port 0 o
f a multi-input successor.
template< typename T, typename V,
bool = tbb::internal::is_same_type< typename tuple_element<0,type
name T::output_ports_type>::type,
typename tuple_element<0,type
name V::input_ports_type>::type
>::value >
inline void remove_edge( T& output, V& input) {
remove_edge(get<0>(output.output_ports()), get<0>(input.input_ports()))
;
}
//Removes an edge between port 0 of a multi-output predecessor and a receiv
er.
template< typename T, typename R,
bool = tbb::internal::is_same_type<typename tuple_element<0,typen
ame T::output_ports_type>::type, receiver<R> >::value >
inline void remove_edge( T& output, receiver<R>& input) {
remove_edge(get<0>(output.output_ports()), input);
}
//Removes an edge between a sender and port 0 of a multi-input successor.
template<typename S, typename V,
bool = tbb::internal::is_same_type<sender<S>, typename tuple_elem
ent<0,typename V::input_ports_type>::type >::value >
inline void remove_edge( sender<S>& output, V& input) {
remove_edge(output, get<0>(input.input_ports()));
}
#endif
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
template<typename C > template<typename C >
template< typename S > template< typename S >
void edge_container<C>::sender_extract( S &s ) { void internal::edge_container<C>::sender_extract( S &s ) {
edge_vector e = built_edges; edge_list_type e = built_edges;
for ( typename edge_vector::iterator i = e.begin(); i != e.end(); ++i ) for ( typename edge_list_type::iterator i = e.begin(); i != e.end(); ++
{ i ) {
remove_edge(s, **i); remove_edge(s, **i);
} }
} }
template<typename C > template<typename C >
template< typename R > template< typename R >
void edge_container<C>::receiver_extract( R &r ) { void internal::edge_container<C>::receiver_extract( R &r ) {
edge_vector e = built_edges; edge_list_type e = built_edges;
for ( typename edge_vector::iterator i = e.begin(); i != e.end(); ++i ) for ( typename edge_list_type::iterator i = e.begin(); i != e.end(); ++
{ i ) {
remove_edge(**i, r); remove_edge(**i, r);
} }
} }
#endif #endif
//! 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>();
} }
#if __TBB_PREVIEW_COMPOSITE_NODE
//composite_node
template< typename InputTuple, typename OutputTuple > class composite_node;
template< typename... InputTypes, typename... OutputTypes>
class composite_node <tbb::flow::tuple<InputTypes...>, tbb::flow::tuple<Out
putTypes...> > : public graph_node {
public:
typedef tbb::flow::tuple< receiver<InputTypes>&... > input_ports_type;
typedef tbb::flow::tuple< sender<OutputTypes>&... > output_ports_type;
private:
input_ports_type *my_input_ports;
output_ports_type *my_output_ports;
const char *type_name;
static const size_t NUM_INPUTS = sizeof...(InputTypes);
static const size_t NUM_OUTPUTS = sizeof...(OutputTypes);
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
//TODO: extend to include multiinput-multioutput nodes
template<typename NodeType>
auto sender_cast(const NodeType &n)-> sender< typename NodeType::output
_type >* {
return dynamic_cast< sender< typename NodeType::output_type > * >(c
onst_cast< NodeType *>(&n));
}
template<typename NodeType>
auto receiver_cast(const NodeType &n)-> receiver< typename NodeType::in
put_type >* {
return dynamic_cast< receiver< typename NodeType::input_type > * >(
const_cast< NodeType *>(&n)) ;
}
bool add_nodes_impl(bool) {return true; }
template< typename NodeType1, typename... NodeTypes >
bool add_nodes_impl(bool visible, const NodeType1& n1, const NodeTypes&
... n) {
// try to dynamic cast to sender< NodeType::output_type >; if succe
ssful, its a single-output node
void *addr = sender_cast(n1);
if(!addr)
addr = receiver_cast(n1);
if(addr) {
if (visible)
tbb::internal::itt_relation_add( tbb::internal::ITT_DOMAIN_
FLOW, this, tbb::internal::FLOW_NODE, tbb::internal::__itt_relation_is_pare
nt_of, addr, tbb::internal::FLOW_NODE );
else
tbb::internal::itt_relation_add( tbb::internal::ITT_DOMAIN_
FLOW, addr, tbb::internal::FLOW_NODE, tbb::internal::__itt_relation_is_chil
d_of, this, tbb::internal::FLOW_NODE );
return add_nodes_impl(visible, n...);
} else {
return false;
}
}
#endif
protected:
/*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags)) {}
public:
composite_node( graph &g, const char *my_type_name = " ") : graph_node(
g), type_name(my_type_name) {
my_input_ports = NULL;
my_output_ports = NULL;
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
tbb::internal::itt_make_task_group( tbb::internal::ITT_DOMAIN_FLOW,
this, tbb::internal::FLOW_NODE, &g, tbb::internal::FLOW_GRAPH, tbb::intern
al::FLOW_COMPOSITE_NODE );
tbb::internal::fgt_multiinput_multioutput_node_desc( this, type_nam
e );
#endif
}
void set_external_ports(input_ports_type&& input_ports_tuple, output_por
ts_type&& output_ports_tuple) {
__TBB_STATIC_ASSERT(NUM_INPUTS == tbb::flow::tuple_size<input_ports_
type>::value, "number of arguments does not match number of input ports");
__TBB_STATIC_ASSERT(NUM_OUTPUTS == tbb::flow::tuple_size<output_port
s_type>::value, "number of arguments does not match number of output ports"
);
my_input_ports = new input_ports_type(std::move(input_ports_tuple));
my_output_ports = new output_ports_type(std::move(output_ports_tuple)
);
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
tbb::internal::fgt_internal_input_helper<input_ports_type, input_port
s_type, NUM_INPUTS>::register_port( this, input_ports_tuple );
tbb::internal::fgt_internal_output_helper<output_ports_type, output_p
orts_type, NUM_OUTPUTS>::register_port( this, output_ports_tuple);
#endif
}
void set_external_ports(const input_ports_type& input_ports_tuple, const
output_ports_type& output_ports_tuple) {
__TBB_STATIC_ASSERT(NUM_INPUTS == tbb::flow::tuple_size<input_ports_
type>::value, "number of arguments does not match number of input ports");
__TBB_STATIC_ASSERT(NUM_OUTPUTS == tbb::flow::tuple_size<output_port
s_type>::value, "number of arguments does not match number of output ports"
);
my_input_ports = new input_ports_type(input_ports_tuple);
my_output_ports = new output_ports_type(output_ports_tuple);
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
tbb::internal::fgt_internal_input_helper<input_ports_type, input_port
s_type, NUM_INPUTS>::register_port( this, input_ports_tuple );
tbb::internal::fgt_internal_output_helper<output_ports_type, output_p
orts_type, NUM_OUTPUTS>::register_port( this, output_ports_tuple);
#endif
}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
template< typename... NodeTypes >
bool add_visible_nodes(const NodeTypes&... n) {
return add_nodes_impl(true, n...);
}
template< typename... NodeTypes >
bool add_nodes(const NodeTypes&... n) {
return add_nodes_impl(false, n...);
}
#else
template<typename... Nodes> bool add_nodes(Nodes&...) { return true; }
template<typename... Nodes> bool add_visible_nodes(Nodes&...) { return
true; }
#endif
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_multiinput_multioutput_node_desc( this, name );
}
#endif
input_ports_type input_ports() {
__TBB_ASSERT(my_input_ports, "input ports not set, call set_extern
al_ports to set input ports");
return *my_input_ports;
}
output_ports_type output_ports() {
__TBB_ASSERT(my_output_ports, "output ports not set, call set_exte
rnal_ports to set output ports");
return *my_output_ports;
}
virtual ~composite_node() {
if(my_input_ports) delete my_input_ports;
if(my_output_ports) delete my_output_ports;
}
};
//composite_node with only input ports
//TODO: trim specializations
template< typename... InputTypes>
class composite_node <tbb::flow::tuple<InputTypes...>, tbb::flow::tuple<> >
: public graph_node {
public:
typedef tbb::flow::tuple< receiver<InputTypes>&... > input_ports_type;
private:
input_ports_type *my_input_ports;
static const size_t NUM_INPUTS = sizeof...(InputTypes);
const char *type_name;
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
template<typename NodeType>
auto sender_cast(const NodeType &n)-> sender< typename NodeType::output
_type >* {
return dynamic_cast< sender< typename NodeType::output_type > * >(c
onst_cast< NodeType *>(&n));
}
template<typename NodeType>
auto receiver_cast(const NodeType &n)-> receiver< typename NodeType::in
put_type >* {
return dynamic_cast< receiver< typename NodeType::input_type > * >(
const_cast< NodeType *>(&n)) ;
}
bool add_nodes_impl(bool) { return true; }
template< typename NodeType1, typename... NodeTypes >
bool add_nodes_impl(bool visible, const NodeType1& n1, const NodeTypes&
... n) {
// try to dynamic cast to sender< NodeType::output_type >; if succe
ssful, its a single-output node
void *addr = sender_cast(n1);
if(!addr)
addr = receiver_cast(n1);
if(addr) {
if (visible)
tbb::internal::itt_relation_add( tbb::internal::ITT_DOMAIN_
FLOW, this, tbb::internal::FLOW_NODE, tbb::internal::__itt_relation_is_pare
nt_of, addr, tbb::internal::FLOW_NODE );
else
tbb::internal::itt_relation_add( tbb::internal::ITT_DOMAIN_
FLOW, addr, tbb::internal::FLOW_NODE, tbb::internal::__itt_relation_is_chil
d_of, this, tbb::internal::FLOW_NODE );
return add_nodes_impl(visible, n...);
} else {
return false;
}
}
#endif
protected:
/*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags)) {}
public:
composite_node( graph &g, const char *my_type_name = " ") : graph_node(
g), type_name(my_type_name) {
my_input_ports = NULL;
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
tbb::internal::itt_make_task_group( tbb::internal::ITT_DOMAIN_FLOW,
this, tbb::internal::FLOW_NODE, &g, tbb::internal::FLOW_GRAPH, tbb::intern
al::FLOW_COMPOSITE_NODE );
tbb::internal::fgt_multiinput_multioutput_node_desc( this, type_nam
e );
#endif
}
void set_external_ports(input_ports_type&& input_ports_tuple) {
__TBB_STATIC_ASSERT(NUM_INPUTS == tbb::flow::tuple_size<input_ports_
type>::value, "number of arguments does not match number of input ports");
my_input_ports = new input_ports_type(std::move(input_ports_tuple));
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
tbb::internal::fgt_internal_input_helper<input_ports_type, input_port
s_type, NUM_INPUTS>::register_port( this, input_ports_tuple );
#endif
}
void set_external_ports(const input_ports_type& input_ports_tuple) {
__TBB_STATIC_ASSERT(NUM_INPUTS == tbb::flow::tuple_size<input_ports_
type>::value, "number of arguments does not match number of input ports");
my_input_ports = new input_ports_type(input_ports_tuple);
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
tbb::internal::fgt_internal_input_helper<input_ports_type, input_port
s_type, NUM_INPUTS>::register_port( this, input_ports_tuple );
#endif
}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
template< typename... NodeTypes >
bool add_visible_nodes(const NodeTypes&... n) {
return add_nodes_impl(true, n...);
}
template< typename... NodeTypes >
bool add_nodes( const NodeTypes&... n) {
return add_nodes_impl(false, n...);
}
#else
template<typename... Nodes> bool add_nodes(Nodes&...) { return true; }
template<typename... Nodes> bool add_visible_nodes(Nodes&...) { return
true; }
#endif
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_multiinput_multioutput_node_desc( this, name );
}
#endif
input_ports_type input_ports() {
__TBB_ASSERT(my_input_ports, "input ports not set, call set_extern
al_ports to set input ports");
return *my_input_ports;
}
virtual ~composite_node() {
if(my_input_ports) delete my_input_ports;
}
};
//composite_nodes with only output_ports
template<typename... OutputTypes>
class composite_node <tbb::flow::tuple<>, tbb::flow::tuple<OutputTypes...>
> : public graph_node {
public:
typedef tbb::flow::tuple< sender<OutputTypes>&... > output_ports_type;
private:
output_ports_type *my_output_ports;
static const size_t NUM_OUTPUTS = sizeof...(OutputTypes);
const char *type_name;
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
template<typename NodeType>
auto sender_cast(const NodeType &n)-> sender< typename NodeType::output
_type >* {
return dynamic_cast< sender< typename NodeType::output_type > * >(c
onst_cast< NodeType *>(&n));
}
template<typename NodeType>
auto receiver_cast(const NodeType &n)-> receiver< typename NodeType::in
put_type >* {
return dynamic_cast< receiver< typename NodeType::input_type > * >(
const_cast< NodeType *>(&n)) ;
}
bool add_nodes_impl(bool) {return true;}
template< typename NodeType1, typename... NodeTypes >
bool add_nodes_impl(bool visible, const NodeType1& n1, const NodeTypes&
... n) {
// try to dynamic cast to sender< NodeType::output_type >; if succe
ssful, its a single-output node
void *addr = sender_cast(n1);
if(!addr)
addr = receiver_cast(n1);
if(addr) {
if (visible)
tbb::internal::itt_relation_add( tbb::internal::ITT_DOMAIN_
FLOW, this, tbb::internal::FLOW_NODE, tbb::internal::__itt_relation_is_pare
nt_of, addr, tbb::internal::FLOW_NODE );
else
tbb::internal::itt_relation_add( tbb::internal::ITT_DOMAIN_
FLOW, addr, tbb::internal::FLOW_NODE, tbb::internal::__itt_relation_is_chil
d_of, this, tbb::internal::FLOW_NODE );
return add_nodes_impl(visible, n...);
} else {
return false;
}
}
#endif
protected:
/*override*/void reset(__TBB_PFG_RESET_ARG(reset_flags)) {}
public:
composite_node( graph &g, const char *my_type_name = " ") : graph_node(
g), type_name(my_type_name) {
my_output_ports = NULL;
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
tbb::internal::itt_make_task_group( tbb::internal::ITT_DOMAIN_FLOW,
this, tbb::internal::FLOW_NODE, &g, tbb::internal::FLOW_GRAPH, tbb::intern
al::FLOW_COMPOSITE_NODE );
tbb::internal::fgt_multiinput_multioutput_node_desc( this, type_nam
e );
#endif
}
void set_external_ports(output_ports_type&& output_ports_tuple) {
__TBB_STATIC_ASSERT(NUM_OUTPUTS == tbb::flow::tuple_size<output_port
s_type>::value, "number of arguments does not match number of output ports"
);
my_output_ports = new output_ports_type(std::move(output_ports_tuple)
);
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
tbb::internal::fgt_internal_output_helper<output_ports_type, output_p
orts_type, NUM_OUTPUTS>::register_port( this, output_ports_tuple);
#endif
}
void set_external_ports(const output_ports_type& output_ports_tuple) {
__TBB_STATIC_ASSERT(NUM_OUTPUTS == tbb::flow::tuple_size<output_port
s_type>::value, "number of arguments does not match number of output ports"
);
my_output_ports = new output_ports_type(output_ports_tuple);
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
tbb::internal::fgt_internal_output_helper<output_ports_type, output_p
orts_type, NUM_OUTPUTS>::register_port( this, output_ports_tuple);
#endif
}
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
template<typename... NodeTypes >
bool add_visible_nodes(const NodeTypes&... n) {
return add_nodes_impl(true, n...);
}
template<typename... NodeTypes >
bool add_nodes(const NodeTypes&... n) {
return add_nodes_impl(false, n...);
}
#else
template<typename... Nodes> bool add_nodes(Nodes&...) { return true; }
template<typename... Nodes> bool add_visible_nodes(Nodes&...) { return
true; }
#endif
#if TBB_PREVIEW_FLOW_GRAPH_TRACE
/* override */ void set_name( const char *name ) {
tbb::internal::fgt_multiinput_multioutput_node_desc( this, name );
}
#endif
output_ports_type output_ports() {
__TBB_ASSERT(my_output_ports, "output ports not set, call set_exte
rnal_ports to set output ports");
return *my_output_ports;
}
virtual ~composite_node() {
if(my_output_ports) delete my_output_ports;
}
};
#endif // __TBB_PREVIEW_COMPOSITE_NODE
} // interface7 } // interface7
#if TBB_PREVIEW_FLOW_GRAPH_FEATURES #if TBB_PREVIEW_FLOW_GRAPH_FEATURES
using interface7::reset_flags; using interface7::reset_flags;
using interface7::rf_reset_protocol; using interface7::rf_reset_protocol;
using interface7::rf_reset_bodies; using interface7::rf_reset_bodies;
using interface7::rf_extract; using interface7::rf_extract;
#endif #endif
using interface7::graph; using interface7::graph;
skipping to change at line 3251 skipping to change at line 3664
using interface7::priority_queue_node; using interface7::priority_queue_node;
using interface7::limiter_node; using interface7::limiter_node;
using namespace interface7::internal::graph_policy_namespace; using namespace interface7::internal::graph_policy_namespace;
using interface7::join_node; using interface7::join_node;
using interface7::input_port; using interface7::input_port;
using interface7::copy_body; using interface7::copy_body;
using interface7::make_edge; using interface7::make_edge;
using interface7::remove_edge; using interface7::remove_edge;
using interface7::internal::NO_TAG; using interface7::internal::NO_TAG;
using interface7::internal::tag_value; using interface7::internal::tag_value;
#if __TBB_PREVIEW_COMPOSITE_NODE
using interface7::composite_node;
#endif
} // flow } // flow
} // tbb } // tbb
#undef __TBB_PFG_RESET_ARG #undef __TBB_PFG_RESET_ARG
#undef __TBB_COMMA #undef __TBB_COMMA
#endif // __TBB_flow_graph_H #endif // __TBB_flow_graph_H
 End of changes. 47 change blocks. 
58 lines changed or deleted 567 lines changed or added


 parallel_do.h   parallel_do.h 
skipping to change at line 25 skipping to change at line 25
functions from this file, or you compile this file and link it with oth er files to produce functions from this file, or you compile this file and link it with oth er files to produce
an executable, this file does not by itself cause the resulting execut able to be covered an executable, this file does not by itself cause the resulting execut able to be covered
by the GNU General Public License. This exception does not however inva lidate any other by the GNU General Public License. This exception does not however inva lidate any other
reasons why the executable file might be covered by the GNU General Pub lic License. reasons why the executable file might be covered by the GNU General Pub lic License.
*/ */
#ifndef __TBB_parallel_do_H #ifndef __TBB_parallel_do_H
#define __TBB_parallel_do_H #define __TBB_parallel_do_H
#include "internal/_range_iterator.h" #include "internal/_range_iterator.h"
#include "internal/_template_helpers.h"
#include "task.h" #include "task.h"
#include "aligned_space.h" #include "aligned_space.h"
#include <iterator> #include <iterator>
namespace tbb { namespace tbb {
//! @cond INTERNAL //! @cond INTERNAL
namespace internal { namespace internal {
template<typename Body, typename Item> class parallel_do_feeder_impl; template<typename Body, typename Item> class parallel_do_feeder_impl;
template<typename Body> class do_group_task; template<typename Body> class do_group_task;
//! Strips its template type argument from 'cv' and '&' qualifiers
template<typename T>
struct strip { typedef T type; };
template<typename T>
struct strip<T&> { typedef T type; };
template<typename T>
struct strip<const T&> { typedef T type; };
template<typename T>
struct strip<volatile T&> { typedef T type; };
template<typename T>
struct strip<const volatile T&> { typedef T type; };
// Most of the compilers remove cv-qualifiers from non-reference functi
on argument types.
// But unfortunately there are those that don't.
template<typename T>
struct strip<const T> { typedef T type; };
template<typename T>
struct strip<volatile T> { typedef T type; };
template<typename T>
struct strip<const volatile T> { typedef T type; };
} // namespace internal } // namespace internal
//! @endcond //! @endcond
//! Class the user supplied algorithm body uses to add new tasks //! Class the user supplied algorithm body uses to add new tasks
/** \param Item Work item type **/ /** \param Item Work item type **/
template<typename Item> template<typename Item>
class parallel_do_feeder: internal::no_copy class parallel_do_feeder: internal::no_copy
{ {
parallel_do_feeder() {} parallel_do_feeder() {}
virtual ~parallel_do_feeder () {} virtual ~parallel_do_feeder () {}
 End of changes. 2 change blocks. 
21 lines changed or deleted 1 lines changed or added


 partitioner.h   partitioner.h 
skipping to change at line 55 skipping to change at line 55
#define __TBB_NONUNIFORM_TASK_CREATION 1 #define __TBB_NONUNIFORM_TASK_CREATION 1
#ifdef __TBB_machine_time_stamp #ifdef __TBB_machine_time_stamp
#define __TBB_USE_MACHINE_TIME_STAMPS 1 #define __TBB_USE_MACHINE_TIME_STAMPS 1
#define __TBB_task_duration() __TBB_STATIC_THRESHOLD #define __TBB_task_duration() __TBB_STATIC_THRESHOLD
#endif // __TBB_machine_time_stamp #endif // __TBB_machine_time_stamp
#endif // __TBB_DEFINE_MIC #endif // __TBB_DEFINE_MIC
#include "task.h" #include "task.h"
#include "aligned_space.h" #include "aligned_space.h"
#include "atomic.h" #include "atomic.h"
#include "internal/_template_helpers.h"
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
// Workaround for overzealous compiler warnings // Workaround for overzealous compiler warnings
#pragma warning (push) #pragma warning (push)
#pragma warning (disable: 4244) #pragma warning (disable: 4244)
#endif #endif
namespace tbb { namespace tbb {
class auto_partitioner; class auto_partitioner;
skipping to change at line 337 skipping to change at line 338
} }
return false; return false;
} }
void align_depth(depth_t base) { void align_depth(depth_t base) {
__TBB_ASSERT(base <= my_max_depth, 0); __TBB_ASSERT(base <= my_max_depth, 0);
my_max_depth -= base; my_max_depth -= base;
} }
depth_t max_depth() { return my_max_depth; } depth_t max_depth() { return my_max_depth; }
}; };
//! Helper that enables one or the other code branches (see example in is_s
plittable_in_proportion)
template<bool C, typename T = void> struct enable_if { typedef T type; };
template<typename T> struct enable_if<false, T> { };
//! Class determines whether template parameter has static boolean constant //! Class determines whether template parameter has static boolean constant
//! 'is_splittable_in_proportion' initialized with value of 'true' or not. //! 'is_splittable_in_proportion' initialized with value of 'true' or not.
/** If template parameter has such field that has been initialized with non -zero /** If template parameter has such field that has been initialized with non -zero
* value then class field will be set to 'true', otherwise - 'false' * value then class field will be set to 'true', otherwise - 'false'
*/ */
template <typename Range> template <typename Range>
class is_splittable_in_proportion { class is_splittable_in_proportion {
private: private:
typedef char yes[1]; typedef char yes[1];
typedef char no [2]; typedef char no [2];
 End of changes. 2 change blocks. 
5 lines changed or deleted 1 lines changed or added


 tbb_config.h   tbb_config.h 
skipping to change at line 153 skipping to change at line 153
#define __TBB_INITIALIZER_LISTS_PRESENT __INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1400 && (_MSC_VER >= 1800 || __TBB_GCC_VERSION >= 40 400 || _LIBCPP_VERSION) #define __TBB_INITIALIZER_LISTS_PRESENT __INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1400 && (_MSC_VER >= 1800 || __TBB_GCC_VERSION >= 40 400 || _LIBCPP_VERSION)
#endif #endif
#define __TBB_CONSTEXPR_PRESENT __INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1400 #define __TBB_CONSTEXPR_PRESENT __INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1400
#define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT __INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1200 #define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT __INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1200
/** ICC seems to disable support of noexcept event in c++11 when compil ing in compatibility mode for gcc <4.6 **/ /** ICC seems to disable support of noexcept event in c++11 when compil ing in compatibility mode for gcc <4.6 **/
#define __TBB_NOEXCEPT_PRESENT __INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1300 && (__TBB_GCC_VERSION >= 40600 || _LIBCPP_VERSI ON || _MSC_VER) #define __TBB_NOEXCEPT_PRESENT __INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1300 && (__TBB_GCC_VERSION >= 40600 || _LIBCPP_VERSI ON || _MSC_VER)
#define __TBB_CPP11_STD_BEGIN_END_PRESENT (_MSC_VER >= 1700 || __GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1310 && (__TBB_GCC_VERSIO N >= 40600 || _LIBCPP_VERSION)) #define __TBB_CPP11_STD_BEGIN_END_PRESENT (_MSC_VER >= 1700 || __GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1310 && (__TBB_GCC_VERSIO N >= 40600 || _LIBCPP_VERSION))
#define __TBB_CPP11_AUTO_PRESENT (_MSC_VER >= 1600 || __GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1210) #define __TBB_CPP11_AUTO_PRESENT (_MSC_VER >= 1600 || __GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1210)
#define __TBB_CPP11_DECLTYPE_PRESENT (_MSC_VER >= 1600 || __GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1210) #define __TBB_CPP11_DECLTYPE_PRESENT (_MSC_VER >= 1600 || __GXX_EXPERIMENTAL_CXX0X__ && __INTEL_COMPILER >= 1210)
#define __TBB_CPP11_LAMBDAS_PRESENT (__INTEL_CXX11_MODE__ && __INTEL_COMPILER >= 1200)
#elif __clang__ #elif __clang__
//TODO: these options need to be rechecked //TODO: these options need to be rechecked
/** on OS X* the only way to get C++11 is to use clang. For library feature s (e.g. exception_ptr) libc++ is also /** on OS X* the only way to get C++11 is to use clang. For library feature s (e.g. exception_ptr) libc++ is also
* required. So there is no need to check GCC version for clang**/ * required. So there is no need to check GCC version for clang**/
#define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (__has_feature(__cxx #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (__has_feature(__cxx_
_variadic_templates__)) variadic_templates__))
#define __TBB_CPP11_RVALUE_REF_PRESENT (__has_feature(__cxx #define __TBB_CPP11_RVALUE_REF_PRESENT (__has_feature(__cxx_
_rvalue_references__) && (__TBB_GCC_VERSION >= 40300 || _LIBCPP_VERSION)) rvalue_references__) && (__TBB_GCC_VERSION >= 40300 || _LIBCPP_VERSION))
/** TODO: extend exception_ptr related conditions to cover libstdc++ **/ /** TODO: extend exception_ptr related conditions to cover libstdc++ **/
#define __TBB_EXCEPTION_PTR_PRESENT (__cplusplus >= 20110 3L && _LIBCPP_VERSION) #define __TBB_EXCEPTION_PTR_PRESENT (__cplusplus >= 20110 3L && _LIBCPP_VERSION)
#define __TBB_STATIC_ASSERT_PRESENT __has_feature(__cxx_s tatic_assert__) #define __TBB_STATIC_ASSERT_PRESENT __has_feature(__cxx_s tatic_assert__)
/**Clang (preprocessor) has problems with dealing with expression havin g __has_include in #ifs /**Clang (preprocessor) has problems with dealing with expression havin g __has_include in #ifs
* used inside C++ code. (At least version that comes with OS X 10.8 : Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)) **/ * used inside C++ code. (At least version that comes with OS X 10.8 : Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)) **/
#if (__GXX_EXPERIMENTAL_CXX0X__ && __has_include(<tuple>)) #if (__GXX_EXPERIMENTAL_CXX0X__ && __has_include(<tuple>))
#define __TBB_CPP11_TUPLE_PRESENT 1 #define __TBB_CPP11_TUPLE_PRESENT 1
#endif #endif
#if (__has_feature(__cxx_generalized_initializers__) && __has_include(< initializer_list>)) #if (__has_feature(__cxx_generalized_initializers__) && __has_include(< initializer_list>))
#define __TBB_INITIALIZER_LISTS_PRESENT 1 #define __TBB_INITIALIZER_LISTS_PRESENT 1
#endif #endif
#define __TBB_CONSTEXPR_PRESENT __has_feature(__cxx_c onstexpr__) #define __TBB_CONSTEXPR_PRESENT __has_feature(__cxx_c onstexpr__)
#define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (__has_feature(__cxx_ defaulted_functions__) && __has_feature(__cxx_deleted_functions__)) #define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (__has_feature(__cxx_ defaulted_functions__) && __has_feature(__cxx_deleted_functions__))
/**For some unknown reason __has_feature(__cxx_noexcept) does not yiel d true for all cases. Compiler bug ? **/ /**For some unknown reason __has_feature(__cxx_noexcept) does not yiel d true for all cases. Compiler bug ? **/
#define __TBB_NOEXCEPT_PRESENT (__cplusplus >= 20110 3L) #define __TBB_NOEXCEPT_PRESENT (__cplusplus >= 20110 3L)
#define __TBB_CPP11_STD_BEGIN_END_PRESENT (__has_feature(__cxx_ range_for__) && _LIBCPP_VERSION) #define __TBB_CPP11_STD_BEGIN_END_PRESENT (__has_feature(__cxx_ range_for__) && _LIBCPP_VERSION)
#define __TBB_CPP11_AUTO_PRESENT __has_feature(__cxx_a uto_type__) #define __TBB_CPP11_AUTO_PRESENT __has_feature(__cxx_a uto_type__)
#define __TBB_CPP11_DECLTYPE_PRESENT __has_feature(__cxx_d ecltype__) #define __TBB_CPP11_DECLTYPE_PRESENT __has_feature(__cxx_d ecltype__)
#define __TBB_CPP11_LAMBDAS_PRESENT __has_feature(cxx_lam bdas)
#elif __GNUC__ #elif __GNUC__
#define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __GXX_EXPERIMENTAL_CX X0X__ #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT __GXX_EXPERIMENTAL_CX X0X__
#define __TBB_CPP11_RVALUE_REF_PRESENT __GXX_EXPERIMENTAL_CX X0X__ #define __TBB_CPP11_RVALUE_REF_PRESENT __GXX_EXPERIMENTAL_CX X0X__
/** __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 here is a substitution for _GLIB CXX_ATOMIC_BUILTINS_4, which is a prerequisite /** __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 here is a substitution for _GLIB CXX_ATOMIC_BUILTINS_4, which is a prerequisite
for exception_ptr but cannot be used in this file because it is def ined in a header, not by the compiler. for exception_ptr but cannot be used in this file because it is def ined in a header, not by the compiler.
If the compiler has no atomic intrinsics, the C++ library should no t expect those as well. **/ If the compiler has no atomic intrinsics, the C++ library should no t expect those as well. **/
#define __TBB_EXCEPTION_PTR_PRESENT (__GXX_EXPERIMENTAL_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_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)
#define __TBB_NOEXCEPT_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40600) #define __TBB_NOEXCEPT_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40600)
#define __TBB_CPP11_STD_BEGIN_END_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40600) #define __TBB_CPP11_STD_BEGIN_END_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40600)
#define __TBB_CPP11_AUTO_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40400) #define __TBB_CPP11_AUTO_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40400)
#define __TBB_CPP11_DECLTYPE_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40400) #define __TBB_CPP11_DECLTYPE_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40400)
#define __TBB_CPP11_LAMBDAS_PRESENT (__GXX_EXPERIMENTAL_C XX0X__ && __TBB_GCC_VERSION >= 40500)
#elif _MSC_VER #elif _MSC_VER
#define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT (_MSC_VER >= 1800) #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_CPP11_TUPLE_PRESENT (_MSC_VER >= 1600) #define __TBB_CPP11_TUPLE_PRESENT (_MSC_VER >= 1600)
#define __TBB_INITIALIZER_LISTS_PRESENT (_MSC_VER >= 1800) #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 (_MSC_VER >= 1800) #define __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT (_MSC_VER >= 1800)
#define __TBB_NOEXCEPT_PRESENT 0 /*for _MSC_VER == 1 800*/ #define __TBB_NOEXCEPT_PRESENT 0 /*for _MSC_VER == 1 800*/
#define __TBB_CPP11_STD_BEGIN_END_PRESENT (_MSC_VER >= 1700) #define __TBB_CPP11_STD_BEGIN_END_PRESENT (_MSC_VER >= 1700)
#define __TBB_CPP11_AUTO_PRESENT (_MSC_VER >= 1600) #define __TBB_CPP11_AUTO_PRESENT (_MSC_VER >= 1600)
#define __TBB_CPP11_DECLTYPE_PRESENT (_MSC_VER >= 1600) #define __TBB_CPP11_DECLTYPE_PRESENT (_MSC_VER >= 1600)
#define __TBB_CPP11_LAMBDAS_PRESENT (_MSC_VER >= 1600)
#else #else
#define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 0 #define __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT 0
#define __TBB_CPP11_RVALUE_REF_PRESENT 0 #define __TBB_CPP11_RVALUE_REF_PRESENT 0
#define __TBB_EXCEPTION_PTR_PRESENT 0 #define __TBB_EXCEPTION_PTR_PRESENT 0
#define __TBB_STATIC_ASSERT_PRESENT 0 #define __TBB_STATIC_ASSERT_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
#define __TBB_NOEXCEPT_PRESENT 0 #define __TBB_NOEXCEPT_PRESENT 0
#define __TBB_CPP11_STD_BEGIN_END_PRESENT 0 #define __TBB_CPP11_STD_BEGIN_END_PRESENT 0
#define __TBB_CPP11_AUTO_PRESENT 0 #define __TBB_CPP11_AUTO_PRESENT 0
#define __TBB_CPP11_DECLTYPE_PRESENT 0 #define __TBB_CPP11_DECLTYPE_PRESENT 0
#define __TBB_CPP11_LAMBDAS_PRESENT 0
#endif #endif
// C++11 standard library features // C++11 standard library features
#define __TBB_CPP11_VARIADIC_TUPLE_PRESENT (!_MSC_VER || _MSC_VER >=1800)
#define __TBB_CPP11_TYPE_PROPERTIES_PRESENT (_LIBCPP_VERSION || _MS C_VER >= 1700) #define __TBB_CPP11_TYPE_PROPERTIES_PRESENT (_LIBCPP_VERSION || _MS C_VER >= 1700)
#define __TBB_TR1_TYPE_PROPERTIES_IN_STD_PRESENT (__GXX_EXPERIMENTAL_CXX 0X__ && __TBB_GCC_VERSION >= 40300 || _MSC_VER >= 1600) #define __TBB_TR1_TYPE_PROPERTIES_IN_STD_PRESENT (__GXX_EXPERIMENTAL_CXX 0X__ && __TBB_GCC_VERSION >= 40300 || _MSC_VER >= 1600)
// GCC has a partial support of type properties // GCC has a partial support of type properties
#define __TBB_CPP11_IS_COPY_CONSTRUCTIBLE_PRESENT (__GXX_EXPERIMENTAL_CXX 0X__ && __TBB_GCC_VERSION >= 40700 || __TBB_CPP11_TYPE_PROPERTIES_PRESENT) #define __TBB_CPP11_IS_COPY_CONSTRUCTIBLE_PRESENT (__GXX_EXPERIMENTAL_CXX 0X__ && __TBB_GCC_VERSION >= 40700 || __TBB_CPP11_TYPE_PROPERTIES_PRESENT)
// In GCC and MSVC, implementation of std::move_if_noexcept is not aligned with noexcept // In GCC and MSVC, implementation of std::move_if_noexcept is not aligned with noexcept
#define __TBB_MOVE_IF_NOEXCEPT_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_GCC_VERSION >= 40700 || _MSC_VER >= 1800 || __clang__ && _LIBCPP_ VERSION && __TBB_NOEXCEPT_PRESENT) #define __TBB_MOVE_IF_NOEXCEPT_PRESENT (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_GCC_VERSION >= 40700 || _MSC_VER >= 1800 || __clang__ && _LIBCPP_ VERSION && __TBB_NOEXCEPT_PRESENT)
//TODO: Probably more accurate way is to analyze version of stdlibc++ via__ GLIBCXX__ instead of __TBB_GCC_VERSION //TODO: Probably more accurate way is to analyze version of stdlibc++ via__ GLIBCXX__ instead of __TBB_GCC_VERSION
#define __TBB_ALLOCATOR_TRAITS_PRESENT (__cplusplus >= 201103L && _LIBCPP_VERSION || _MSC_VER >= 1700 || \ #define __TBB_ALLOCATOR_TRAITS_PRESENT (__cplusplus >= 201103L && _LIBCPP_VERSION || _MSC_VER >= 1700 || \
__GXX_EXPERIMENTAL_CXX 0X__ && __TBB_GCC_VERSION >= 40700 && !(__TBB_GCC_VERSION == 40700 && __TBB _DEFINE_MIC) \ __GXX_EXPERIMENTAL_CXX 0X__ && __TBB_GCC_VERSION >= 40700 && !(__TBB_GCC_VERSION == 40700 && __TBB _DEFINE_MIC) \
skipping to change at line 458 skipping to change at line 464
#ifndef __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES #ifndef __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES
#define __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES 1 #define __TBB_USE_PROPORTIONAL_SPLIT_IN_BLOCKED_RANGES 1
#endif #endif
#ifndef __TBB_ENABLE_RANGE_FEEDBACK #ifndef __TBB_ENABLE_RANGE_FEEDBACK
#define __TBB_ENABLE_RANGE_FEEDBACK 0 #define __TBB_ENABLE_RANGE_FEEDBACK 0
#endif #endif
#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 // VS11 setting, issue resolved in VS1
#else 2
#define __TBB_VARIADIC_MAX 10 #elif _MSC_VER == 1600
#endif #define __TBB_VARIADIC_MAX 10 // VS10 setting
#else
#define __TBB_VARIADIC_MAX 15
#endif
#endif #endif
/** __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
skipping to change at line 632 skipping to change at line 640
// With MSVC, when an array is passed by const reference to a template function, // With MSVC, when an array is passed by const reference to a template function,
// constness from the function parameter may get propagated to the temp late parameter. // constness from the function parameter may get propagated to the temp late parameter.
#define __TBB_CONST_REF_TO_ARRAY_TEMPLATE_PARAM_BROKEN 1 #define __TBB_CONST_REF_TO_ARRAY_TEMPLATE_PARAM_BROKEN 1
#endif #endif
// A compiler bug: a disabled copy constructor prevents use of the moving c onstructor // A compiler bug: a disabled copy constructor prevents use of the moving c onstructor
#define __TBB_IF_NO_COPY_CTOR_MOVE_SEMANTICS_BROKEN (_MSC_VER && (__INTEL_C OMPILER >= 1300 && __INTEL_COMPILER <= 1310) && !__INTEL_CXX11_MODE__) #define __TBB_IF_NO_COPY_CTOR_MOVE_SEMANTICS_BROKEN (_MSC_VER && (__INTEL_C OMPILER >= 1300 && __INTEL_COMPILER <= 1310) && !__INTEL_CXX11_MODE__)
// MSVC 2013 and ICC 15 seems do not generate implicit move constructor for empty derived class while should // MSVC 2013 and ICC 15 seems do not generate implicit move constructor for empty derived class while should
#define __TBB_CPP11_IMPLICIT_MOVE_MEMBERS_GENERATION_FOR_DERIVED_BROKEN (_ _TBB_CPP11_RVALUE_REF_PRESENT && \ #define __TBB_CPP11_IMPLICIT_MOVE_MEMBERS_GENERATION_FOR_DERIVED_BROKEN (_ _TBB_CPP11_RVALUE_REF_PRESENT && \
( !__INTEL_COMPILER && _MSC_VER && _MSC_VER <=1800 || __INTEL_COMPILE ( !__INTEL_COMPILER && _MSC_VER && _MSC_VER <= 1800 || __INTEL_COMPIL
R && __INTEL_COMPILER <= 1500 )) ER && __INTEL_COMPILER <= 1500 ))
#define __TBB_CPP11_DECLVAL_BROKEN (_MSC_VER == 1600 || (__GNUC__ && __TBB_
GCC_VERSION < 40500) )
//The implicit upcasting of the tuple of a reference of a derived class to
a base class fails on icc 13.X
//if the system's gcc environment is 4.8
#if (__INTEL_COMPILER >=1300 && __INTEL_COMPILER <=1310) && __TBB_GCC_VERSI
ON>=40700 && __GXX_EXPERIMENTAL_CXX0X__
#define __TBB_UPCAST_OF_TUPLE_OF_REF_BROKEN 1
#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) #define __TBB_ALLOCATOR_CONSTRUCT_VARIADIC (__TBB_CPP11_VARIADIC_TEMPL ATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT)
#define __TBB_VARIADIC_PARALLEL_INVOKE (TBB_PREVIEW_VARIADIC_PARAL LEL_INVOKE && __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_ REF_PRESENT) #define __TBB_VARIADIC_PARALLEL_INVOKE (TBB_PREVIEW_VARIADIC_PARAL LEL_INVOKE && __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_ REF_PRESENT)
#define __TBB_PREVIEW_COMPOSITE_NODE (TBB_PREVIEW_FLOW_GRAPH_NOD
ES && __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT \
&& __TBB_CPP11_RVALUE_REF_
PRESENT && __TBB_CPP11_AUTO_PRESENT) \
&& __TBB_CPP11_VARIADIC_TU
PLE_PRESENT && !__TBB_UPCAST_OF_TUPLE_OF_REF_BROKEN
#endif /* __TBB_tbb_config_H */ #endif /* __TBB_tbb_config_H */
 End of changes. 11 change blocks. 
12 lines changed or deleted 38 lines changed or added


 tbb_stddef.h   tbb_stddef.h 
skipping to change at line 29 skipping to change at line 29
*/ */
#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 3 #define TBB_VERSION_MINOR 3
// Engineering-focused interface version // Engineering-focused interface version
#define TBB_INTERFACE_VERSION 8003 #define TBB_INTERFACE_VERSION 8004
#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
skipping to change at line 135 skipping to change at line 135
#endif #endif
#if !defined(_MSC_VER) || _MSC_VER>=1600 #if !defined(_MSC_VER) || _MSC_VER>=1600
#include <stdint.h> #include <stdint.h>
#endif #endif
//! Type for an assertion handler //! Type for an assertion handler
typedef void(*assertion_handler_type)( const char* filename, int line, cons t char* expression, const char * comment ); typedef void(*assertion_handler_type)( const char* filename, int line, cons t char* expression, const char * comment );
#if TBB_USE_ASSERT #if TBB_USE_ASSERT
#define __TBB_ASSERT_NS(predicate,message,ns) ((predicate)?((void)0) : ns::assertion_failure(__FILE__,__LINE__,#predicate,message))
//! Assert that x is true. //! Assert that x is true.
#define __TBB_ASSERT_NS(predicate,message,ns) ((predicate)?((void)0) : ns::assertion_failure(__FILE__,__LINE__,#predicate,message))
/** If x is false, print assertion failure message. /** If x is false, print assertion failure message.
If the comment argument is not NULL, it is printed as part of the f ailure message. If the comment argument is not NULL, it is printed as part of the f ailure message.
The comment argument has no other effect. */ The comment argument has no other effect. */
#if __TBBMALLOC_BUILD #if __TBBMALLOC_BUILD
namespace rml { namespace internal { namespace rml { namespace internal {
#define __TBB_ASSERT(predicate,message) __TBB_ASSERT_NS(predicate,messa ge,rml::internal) #define __TBB_ASSERT(predicate,message) __TBB_ASSERT_NS(predicate,messa ge,rml::internal)
#else #else
namespace tbb { namespace tbb {
#define __TBB_ASSERT(predicate,message) __TBB_ASSERT_NS(predicate,messa ge,tbb) #define __TBB_ASSERT(predicate,message) __TBB_ASSERT_NS(predicate,messa ge,tbb)
#endif #endif
#define __TBB_ASSERT_EX __TBB_ASSERT #define __TBB_ASSERT_EX __TBB_ASSERT
//! Set assertion handler and return previous value of it. //! Set assertion handler and return previous value of it.
assertion_handler_type __TBB_EXPORTED_FUNC set_assertion_handler( asser tion_handler_type new_handler ); assertion_handler_type __TBB_EXPORTED_FUNC set_assertion_handler( asser tion_handler_type new_handler );
//! Process an assertion failure. //! Process an assertion failure.
/** Normally called from __TBB_ASSERT macro. /** Normally called from __TBB_ASSERT macro.
If assertion handler is null, print message for assertion failure a nd abort. If assertion handler is null, print message for assertion failure a nd abort.
Otherwise call the assertion handler. */ Otherwise call the assertion handler. */
void __TBB_EXPORTED_FUNC assertion_failure( const char* filename, int l ine, const char* expression, const char* comment ); void __TBB_EXPORTED_FUNC assertion_failure( const char* filename, int l ine, const char* expression, const char* comment );
#if __TBBMALLOC_BUILD #if __TBBMALLOC_BUILD
}} // namespace rml::internal }} // namespace rml::internal
#else #else
} // namespace tbb } // namespace tbb
#endif #endif
#else /* !TBB_USE_ASSERT */ #else /* !TBB_USE_ASSERT */
//! No-op version of __TBB_ASSERT. //! No-op version of __TBB_ASSERT.
#define __TBB_ASSERT(predicate,comment) ((void)0) #define __TBB_ASSERT(predicate,comment) ((void)0)
//! "Extended" version is useful to suppress warnings if a variable is only used with an assert //! "Extended" version is useful to suppress warnings if a variable is only used with an assert
#define __TBB_ASSERT_EX(predicate,comment) ((void)(1 && (predicate))) #define __TBB_ASSERT_EX(predicate,comment) ((void)(1 && (predicate)))
#endif /* !TBB_USE_ASSERT */ #endif /* !TBB_USE_ASSERT */
//! The namespace tbb contains all components of the library. //! The namespace tbb contains all components of the library.
skipping to change at line 474 skipping to change at line 475
//! A template to select either 32-bit or 64-bit constant as compile time, depending on machine word size. //! A template to select either 32-bit or 64-bit constant as compile time, depending on machine word size.
template <unsigned u, unsigned long long ull > template <unsigned u, unsigned long long ull >
struct select_size_t_constant { struct select_size_t_constant {
//Explicit cast is needed to avoid compiler warnings about possible tru ncation. //Explicit cast is needed to avoid compiler warnings about possible tru ncation.
//The value of the right size, which is selected by ?:, is anyway not truncated or promoted. //The value of the right size, which is selected by ?:, is anyway not truncated or promoted.
static const size_t value = (size_t)((sizeof(size_t)==sizeof(u)) ? u : ull); static const size_t value = (size_t)((sizeof(size_t)==sizeof(u)) ? u : ull);
}; };
#if __TBB_CPP11_RVALUE_REF_PRESENT #if __TBB_CPP11_RVALUE_REF_PRESENT
using std::move; using std::move;
using std::forward;
#elif defined(_LIBCPP_NAMESPACE) #elif defined(_LIBCPP_NAMESPACE)
// libc++ defines "pre-C++11 move" similarly to our; use it to avoid name c onflicts in some cases. // libc++ defines "pre-C++11 move and forward" similarly to ours; use it to avoid name conflicts in some cases.
using std::_LIBCPP_NAMESPACE::move; using std::_LIBCPP_NAMESPACE::move;
using std::_LIBCPP_NAMESPACE::forward;
#else #else
// It is assumed that cv qualifiers, if any, are part of the deduced type.
template <typename T> template <typename T>
T& move( T& x ) { return x; } T& move( T& x ) { return x; }
template <typename T>
T& forward( T& x ) { return x; }
#endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
// Helper macros to simplify writing templates working with both C++03 and
C++11.
#if __TBB_CPP11_RVALUE_REF_PRESENT
#define __TBB_FORWARDING_REF(A) A&&
#else
// It is assumed that cv qualifiers, if any, are part of a deduced type.
// Thus this macro should not be used in public interfaces.
#define __TBB_FORWARDING_REF(A) A&
#endif
#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
#define __TBB_PARAMETER_PACK ...
#define __TBB_PACK_EXPANSION(A) A...
#else
#define __TBB_PARAMETER_PACK
#define __TBB_PACK_EXPANSION(A) A
#endif /* __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT */
#if __TBB_CPP11_DECLTYPE_PRESENT
#if __TBB_CPP11_DECLVAL_BROKEN
// Ad-hoc implementation of std::declval
template <class T> __TBB_FORWARDING_REF(T) declval() /*noexcept*/;
#else
using std::declval;
#endif
#endif #endif
template <bool condition> template <bool condition>
struct STATIC_ASSERTION_FAILED; struct STATIC_ASSERTION_FAILED;
template <> template <>
struct STATIC_ASSERTION_FAILED<false> { enum {value=1};}; struct STATIC_ASSERTION_FAILED<false> { enum {value=1};};
template<> template<>
struct STATIC_ASSERTION_FAILED<true>; //intentionally left undefined to cau se compile time error struct STATIC_ASSERTION_FAILED<true>; //intentionally left undefined to cau se compile time error
 End of changes. 11 change blocks. 
4 lines changed or deleted 36 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/