_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 | |||