Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0baaad609a | ||
|
|
cb8fa21a84 | ||
|
|
912cd2b0b3 | ||
|
|
e8666c0b9c | ||
|
|
71b04524d0 | ||
|
|
aa247fa816 | ||
|
|
13544f9432 | ||
|
|
635761449f | ||
|
|
6bfd29bde7 | ||
|
|
e6459e22ae | ||
|
|
85792ca411 | ||
|
|
3fbdbb8b2e | ||
|
|
3c91aea522 | ||
|
|
2eccd5f998 | ||
|
|
cc3a9aa992 | ||
|
|
104fb5c9de | ||
|
|
f10350212b |
@@ -28,6 +28,7 @@ Here are [Release Notes](RELEASE_NOTES.md) and [System Requirements](SYSTEM_REQU
|
||||
* [oneTBB Developer Guide and Reference](https://oneapi-src.github.io/oneTBB)
|
||||
* [Migrating from TBB to oneTBB](https://oneapi-src.github.io/oneTBB/main/tbb_userguide/Migration_Guide.html)
|
||||
* [README for the CMake build system](cmake/README.md)
|
||||
* [oneTBB Testing Approach](https://oneapi-src.github.io/oneTBB/main/intro/testing_approach.html)
|
||||
* [Basic support for the Bazel build system](Bazel.md)
|
||||
* [oneTBB Discussions](https://github.com/oneapi-src/oneTBB/discussions)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
# Copyright (c) 2020-2022 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -32,9 +32,15 @@ if (NOT TBB_STRICT AND COMMAND tbb_remove_compile_flag)
|
||||
endif()
|
||||
|
||||
# Enable Intel(R) Transactional Synchronization Extensions (-mrtm) and WAITPKG instructions support (-mwaitpkg) on relevant processors
|
||||
if (NOT "${CMAKE_OSX_ARCHITECTURES}" MATCHES "^arm64$" AND CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64|amd64|AMD64)") # OSX systems are 64-bit only
|
||||
if (CMAKE_OSX_ARCHITECTURES)
|
||||
set(_tbb_target_architectures "${CMAKE_OSX_ARCHITECTURES}")
|
||||
else()
|
||||
set(_tbb_target_architectures "${CMAKE_SYSTEM_PROCESSOR}")
|
||||
endif()
|
||||
if ("${_tbb_target_architectures}" MATCHES "(x86_64|amd64|AMD64)") # OSX systems are 64-bit only
|
||||
set(TBB_COMMON_COMPILE_FLAGS ${TBB_COMMON_COMPILE_FLAGS} -mrtm $<$<NOT:$<VERSION_LESS:${CMAKE_CXX_COMPILER_VERSION},12.0>>:-mwaitpkg>)
|
||||
endif()
|
||||
unset(_tbb_target_architectures)
|
||||
|
||||
# TBB malloc settings
|
||||
set(TBBMALLOC_LIB_COMPILE_FLAGS -fno-rtti -fno-exceptions)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
/main/intro/notation
|
||||
/main/intro/intro_os
|
||||
/main/intro/Benefits
|
||||
/main/intro/testing_approach
|
||||
|
||||
|
||||
.. toctree::
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
.. _testing_approach:
|
||||
|
||||
Testing Approach
|
||||
================
|
||||
|
||||
There are four main types of errors/hazards you can encounter in the development of libraries for parallelism:
|
||||
|
||||
* Interface correspondence to specification
|
||||
* Memory errors
|
||||
* Data race
|
||||
* Race conditions and deadlocks
|
||||
|
||||
|short_name| testing approach is designed to provide high coverage of these error types.
|
||||
All types of errors are covered with unit testing and review.
|
||||
|
||||
Code coverage metrics are tracked to ensure high code coverage with tests. Uncovered branches are analyzed manually.
|
||||
Memory errors and data races are additionally covered by special tools that include thread and memory sanitizers.
|
||||
|
||||
Race conditions and deadlocks are the most complicated errors.
|
||||
They are covered by:
|
||||
|
||||
* **Unit tests** that, however, have limited capability to catch such errors
|
||||
* **Integration tests**. Multiple different functionalities are heavily combined to emulate user use cases that may trigger such errors based on prior knowledge and expertise.
|
||||
* **Stress testing with different possible combinations**. It ensures that even rarely triggered error conditions are caught by testing.
|
||||
|
||||
.. note:: Every fix is required to be covered by a test to guarantee the detection of such issues in the future.
|
||||
|
||||
Continuous Integration triggers all the tests on each commit. This ensures that:
|
||||
|
||||
* Issues are detected, starting from the early development phase and up to the moment of integration of changes into the library.
|
||||
* The highest quality of the library is maintained even in such error-prone domains as parallelism.
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
Copyright (c) 2005-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -223,6 +223,16 @@ concurrent_unordered_map( std::initializer_list<std::pair<Key, T>>, std::size_t,
|
||||
-> concurrent_unordered_map<std::remove_const_t<Key>, T, Hash,
|
||||
std::equal_to<std::remove_const_t<Key>>, Alloc>;
|
||||
|
||||
#if __APPLE__ && __TBB_CLANG_VERSION == 100000
|
||||
// An explicit deduction guide is required for copy/move constructor with allocator for APPLE LLVM 10.0.0
|
||||
// due to an issue with generating an implicit deduction guide for these constructors under several strange surcumstances.
|
||||
// Currently the issue takes place because the last template parameter for Traits is boolean, it should not affect the deduction guides
|
||||
// The issue reproduces only on this version of the compiler
|
||||
template <typename Key, typename T, typename Hash, typename KeyEq, typename Alloc>
|
||||
concurrent_unordered_map( concurrent_unordered_map<Key, T, Hash, KeyEq, Alloc>, Alloc )
|
||||
-> concurrent_unordered_map<Key, T, Hash, KeyEq, Alloc>;
|
||||
#endif
|
||||
|
||||
#endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
|
||||
|
||||
template <typename Key, typename T, typename Hash, typename KeyEqual, typename Allocator>
|
||||
@@ -372,6 +382,15 @@ concurrent_unordered_multimap( std::initializer_list<std::pair<Key, T>>, std::si
|
||||
-> concurrent_unordered_multimap<std::remove_const_t<Key>, T, Hash,
|
||||
std::equal_to<std::remove_const_t<Key>>, Alloc>;
|
||||
|
||||
#if __APPLE__ && __TBB_CLANG_VERSION == 100000
|
||||
// An explicit deduction guide is required for copy/move constructor with allocator for APPLE LLVM 10.0.0
|
||||
// due to an issue with generating an implicit deduction guide for these constructors under several strange surcumstances.
|
||||
// Currently the issue takes place because the last template parameter for Traits is boolean, it should not affect the deduction guides
|
||||
// The issue reproduces only on this version of the compiler
|
||||
template <typename Key, typename T, typename Hash, typename KeyEq, typename Alloc>
|
||||
concurrent_unordered_multimap( concurrent_unordered_multimap<Key, T, Hash, KeyEq, Alloc>, Alloc )
|
||||
-> concurrent_unordered_multimap<Key, T, Hash, KeyEq, Alloc>;
|
||||
#endif
|
||||
#endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
|
||||
|
||||
template <typename Key, typename T, typename Hash, typename KeyEqual, typename Allocator>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
Copyright (c) 2005-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -163,6 +163,15 @@ template <typename T, typename Hash, typename Alloc,
|
||||
concurrent_unordered_set( std::initializer_list<T>, std::size_t, Hash, Alloc )
|
||||
-> concurrent_unordered_set<T, Hash, std::equal_to<T>, Alloc>;
|
||||
|
||||
#if __APPLE__ && __TBB_CLANG_VERSION == 100000
|
||||
// An explicit deduction guide is required for copy/move constructor with allocator for APPLE LLVM 10.0.0
|
||||
// due to an issue with generating an implicit deduction guide for these constructors under several strange surcumstances.
|
||||
// Currently the issue takes place because the last template parameter for Traits is boolean, it should not affect the deduction guides
|
||||
// The issue reproduces only on this version of the compiler
|
||||
template <typename T, typename Hash, typename KeyEq, typename Alloc>
|
||||
concurrent_unordered_set( concurrent_unordered_set<T, Hash, KeyEq, Alloc>, Alloc )
|
||||
-> concurrent_unordered_set<T, Hash, KeyEq, Alloc>;
|
||||
#endif
|
||||
#endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
|
||||
|
||||
template <typename Key, typename Hash, typename KeyEqual, typename Allocator>
|
||||
@@ -292,6 +301,15 @@ template <typename T, typename Hash, typename Alloc,
|
||||
concurrent_unordered_multiset( std::initializer_list<T>, std::size_t, Hash, Alloc )
|
||||
-> concurrent_unordered_multiset<T, Hash, std::equal_to<T>, Alloc>;
|
||||
|
||||
#if __APPLE__ && __TBB_CLANG_VERSION == 100000
|
||||
// An explicit deduction guide is required for copy/move constructor with allocator for APPLE LLVM 10.0.0
|
||||
// due to an issue with generating an implicit deduction guide for these constructors under several strange surcumstances.
|
||||
// Currently the issue takes place because the last template parameter for Traits is boolean, it should not affect the deduction guides
|
||||
// The issue reproduces only on this version of the compiler
|
||||
template <typename T, typename Hash, typename KeyEq, typename Alloc>
|
||||
concurrent_unordered_multiset( concurrent_unordered_multiset<T, Hash, KeyEq, Alloc>, Alloc )
|
||||
-> concurrent_unordered_multiset<T, Hash, KeyEq, Alloc>;
|
||||
#endif
|
||||
#endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
|
||||
|
||||
template <typename Key, typename Hash, typename KeyEqual, typename Allocator>
|
||||
|
||||
@@ -276,18 +276,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
padded_page* get_tail_page() {
|
||||
return tail_page.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
padded_page* get_head_page() {
|
||||
return head_page.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void set_tail_page( padded_page* pg ) {
|
||||
tail_page.store(pg, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void clear(queue_allocator_type& allocator, padded_page* new_head = nullptr, padded_page* new_tail = nullptr) {
|
||||
padded_page* curr_page = get_head_page();
|
||||
size_type index = (head_counter.load(std::memory_order_relaxed) / queue_rep_type::n_queue) % items_per_page;
|
||||
|
||||
@@ -203,146 +203,23 @@
|
||||
broadcast_cache<output_type, null_rw_mutex> my_successors;
|
||||
}; //indexer_node_base
|
||||
|
||||
|
||||
template<int N, typename InputTuple> struct input_types;
|
||||
|
||||
template<typename InputTuple>
|
||||
struct input_types<1, InputTuple> {
|
||||
typedef typename std::tuple_element<0, InputTuple>::type first_type;
|
||||
typedef tagged_msg<size_t, first_type > type;
|
||||
};
|
||||
|
||||
template<typename InputTuple>
|
||||
struct input_types<2, InputTuple> {
|
||||
typedef typename std::tuple_element<0, InputTuple>::type first_type;
|
||||
typedef typename std::tuple_element<1, InputTuple>::type second_type;
|
||||
typedef tagged_msg<size_t, first_type, second_type> type;
|
||||
};
|
||||
|
||||
template<typename InputTuple>
|
||||
struct input_types<3, InputTuple> {
|
||||
typedef typename std::tuple_element<0, InputTuple>::type first_type;
|
||||
typedef typename std::tuple_element<1, InputTuple>::type second_type;
|
||||
typedef typename std::tuple_element<2, InputTuple>::type third_type;
|
||||
typedef tagged_msg<size_t, first_type, second_type, third_type> type;
|
||||
};
|
||||
|
||||
template<typename InputTuple>
|
||||
struct input_types<4, InputTuple> {
|
||||
typedef typename std::tuple_element<0, InputTuple>::type first_type;
|
||||
typedef typename std::tuple_element<1, InputTuple>::type second_type;
|
||||
typedef typename std::tuple_element<2, InputTuple>::type third_type;
|
||||
typedef typename std::tuple_element<3, InputTuple>::type fourth_type;
|
||||
typedef tagged_msg<size_t, first_type, second_type, third_type,
|
||||
fourth_type> type;
|
||||
};
|
||||
|
||||
template<typename InputTuple>
|
||||
struct input_types<5, InputTuple> {
|
||||
typedef typename std::tuple_element<0, InputTuple>::type first_type;
|
||||
typedef typename std::tuple_element<1, InputTuple>::type second_type;
|
||||
typedef typename std::tuple_element<2, InputTuple>::type third_type;
|
||||
typedef typename std::tuple_element<3, InputTuple>::type fourth_type;
|
||||
typedef typename std::tuple_element<4, InputTuple>::type fifth_type;
|
||||
typedef tagged_msg<size_t, first_type, second_type, third_type,
|
||||
fourth_type, fifth_type> type;
|
||||
};
|
||||
|
||||
template<typename InputTuple>
|
||||
struct input_types<6, InputTuple> {
|
||||
typedef typename std::tuple_element<0, InputTuple>::type first_type;
|
||||
typedef typename std::tuple_element<1, InputTuple>::type second_type;
|
||||
typedef typename std::tuple_element<2, InputTuple>::type third_type;
|
||||
typedef typename std::tuple_element<3, InputTuple>::type fourth_type;
|
||||
typedef typename std::tuple_element<4, InputTuple>::type fifth_type;
|
||||
typedef typename std::tuple_element<5, InputTuple>::type sixth_type;
|
||||
typedef tagged_msg<size_t, first_type, second_type, third_type,
|
||||
fourth_type, fifth_type, sixth_type> type;
|
||||
};
|
||||
|
||||
template<typename InputTuple>
|
||||
struct input_types<7, InputTuple> {
|
||||
typedef typename std::tuple_element<0, InputTuple>::type first_type;
|
||||
typedef typename std::tuple_element<1, InputTuple>::type second_type;
|
||||
typedef typename std::tuple_element<2, InputTuple>::type third_type;
|
||||
typedef typename std::tuple_element<3, InputTuple>::type fourth_type;
|
||||
typedef typename std::tuple_element<4, InputTuple>::type fifth_type;
|
||||
typedef typename std::tuple_element<5, InputTuple>::type sixth_type;
|
||||
typedef typename std::tuple_element<6, InputTuple>::type seventh_type;
|
||||
typedef tagged_msg<size_t, first_type, second_type, third_type,
|
||||
fourth_type, fifth_type, sixth_type,
|
||||
seventh_type> type;
|
||||
};
|
||||
|
||||
|
||||
template<typename InputTuple>
|
||||
struct input_types<8, InputTuple> {
|
||||
typedef typename std::tuple_element<0, InputTuple>::type first_type;
|
||||
typedef typename std::tuple_element<1, InputTuple>::type second_type;
|
||||
typedef typename std::tuple_element<2, InputTuple>::type third_type;
|
||||
typedef typename std::tuple_element<3, InputTuple>::type fourth_type;
|
||||
typedef typename std::tuple_element<4, InputTuple>::type fifth_type;
|
||||
typedef typename std::tuple_element<5, InputTuple>::type sixth_type;
|
||||
typedef typename std::tuple_element<6, InputTuple>::type seventh_type;
|
||||
typedef typename std::tuple_element<7, InputTuple>::type eighth_type;
|
||||
typedef tagged_msg<size_t, first_type, second_type, third_type,
|
||||
fourth_type, fifth_type, sixth_type,
|
||||
seventh_type, eighth_type> type;
|
||||
};
|
||||
|
||||
|
||||
template<typename InputTuple>
|
||||
struct input_types<9, InputTuple> {
|
||||
typedef typename std::tuple_element<0, InputTuple>::type first_type;
|
||||
typedef typename std::tuple_element<1, InputTuple>::type second_type;
|
||||
typedef typename std::tuple_element<2, InputTuple>::type third_type;
|
||||
typedef typename std::tuple_element<3, InputTuple>::type fourth_type;
|
||||
typedef typename std::tuple_element<4, InputTuple>::type fifth_type;
|
||||
typedef typename std::tuple_element<5, InputTuple>::type sixth_type;
|
||||
typedef typename std::tuple_element<6, InputTuple>::type seventh_type;
|
||||
typedef typename std::tuple_element<7, InputTuple>::type eighth_type;
|
||||
typedef typename std::tuple_element<8, InputTuple>::type nineth_type;
|
||||
typedef tagged_msg<size_t, first_type, second_type, third_type,
|
||||
fourth_type, fifth_type, sixth_type,
|
||||
seventh_type, eighth_type, nineth_type> type;
|
||||
};
|
||||
|
||||
template<typename InputTuple>
|
||||
struct input_types<10, InputTuple> {
|
||||
typedef typename std::tuple_element<0, InputTuple>::type first_type;
|
||||
typedef typename std::tuple_element<1, InputTuple>::type second_type;
|
||||
typedef typename std::tuple_element<2, InputTuple>::type third_type;
|
||||
typedef typename std::tuple_element<3, InputTuple>::type fourth_type;
|
||||
typedef typename std::tuple_element<4, InputTuple>::type fifth_type;
|
||||
typedef typename std::tuple_element<5, InputTuple>::type sixth_type;
|
||||
typedef typename std::tuple_element<6, InputTuple>::type seventh_type;
|
||||
typedef typename std::tuple_element<7, InputTuple>::type eighth_type;
|
||||
typedef typename std::tuple_element<8, InputTuple>::type nineth_type;
|
||||
typedef typename std::tuple_element<9, InputTuple>::type tenth_type;
|
||||
typedef tagged_msg<size_t, first_type, second_type, third_type,
|
||||
fourth_type, fifth_type, sixth_type,
|
||||
seventh_type, eighth_type, nineth_type,
|
||||
tenth_type> type;
|
||||
};
|
||||
|
||||
// type generators
|
||||
template<typename OutputTuple>
|
||||
struct indexer_types : public input_types<std::tuple_size<OutputTuple>::value, OutputTuple> {
|
||||
static const int N = std::tuple_size<OutputTuple>::value;
|
||||
typedef typename input_types<N, OutputTuple>::type output_type;
|
||||
typedef typename wrap_tuple_elements<N,indexer_input_port,OutputTuple>::type input_ports_type;
|
||||
typedef indexer_node_FE<input_ports_type,output_type,OutputTuple> indexer_FE_type;
|
||||
typedef indexer_node_base<input_ports_type, output_type, OutputTuple> indexer_base_type;
|
||||
template<typename T0, typename... TN>
|
||||
struct indexer_types {
|
||||
using output_type = tagged_msg<std::size_t, T0, TN...>;
|
||||
using input_ports_type = std::tuple<indexer_input_port<T0>, indexer_input_port<TN>...>;
|
||||
using indexer_FE_type = indexer_node_FE<input_ports_type, output_type, std::tuple<T0, TN...>>;
|
||||
using indexer_base_type = indexer_node_base<input_ports_type, output_type, std::tuple<T0, TN...>>;
|
||||
};
|
||||
|
||||
template<class OutputTuple>
|
||||
class unfolded_indexer_node : public indexer_types<OutputTuple>::indexer_base_type {
|
||||
template<typename T0, typename... TN>
|
||||
class unfolded_indexer_node : public indexer_types<T0, TN...>::indexer_base_type {
|
||||
public:
|
||||
typedef typename indexer_types<OutputTuple>::input_ports_type input_ports_type;
|
||||
typedef OutputTuple tuple_types;
|
||||
typedef typename indexer_types<OutputTuple>::output_type output_type;
|
||||
typedef std::tuple<T0, TN...> tuple_types;
|
||||
typedef typename indexer_types<T0, TN...>::input_ports_type input_ports_type;
|
||||
typedef typename indexer_types<T0, TN...>::output_type output_type;
|
||||
private:
|
||||
typedef typename indexer_types<OutputTuple>::indexer_base_type base_type;
|
||||
typedef typename indexer_types<T0, TN...>::indexer_base_type base_type;
|
||||
public:
|
||||
unfolded_indexer_node(graph& g) : base_type(g) {}
|
||||
unfolded_indexer_node(const unfolded_indexer_node &other) : base_type(other) {}
|
||||
|
||||
@@ -1192,38 +1192,22 @@
|
||||
}; // join_node_base
|
||||
|
||||
// join base class type generator
|
||||
template<int N, template<class> class PT, typename OutputTuple, typename JP>
|
||||
template<template<class> class PT, typename OutputTuple, typename JP>
|
||||
struct join_base {
|
||||
typedef join_node_base<JP, typename wrap_tuple_elements<N,PT,OutputTuple>::type, OutputTuple> type;
|
||||
typedef join_node_base<JP, typename wrap_tuple_elements<PT,OutputTuple>::type, OutputTuple> type;
|
||||
};
|
||||
|
||||
template<int N, typename OutputTuple, typename K, typename KHash>
|
||||
struct join_base<N, key_matching_port, OutputTuple, key_matching<K,KHash> > {
|
||||
template<typename OutputTuple, typename K, typename KHash>
|
||||
struct join_base<key_matching_port, OutputTuple, key_matching<K,KHash> > {
|
||||
typedef key_matching<K, KHash> key_traits_type;
|
||||
typedef K key_type;
|
||||
typedef KHash key_hash_compare;
|
||||
typedef join_node_base< key_traits_type,
|
||||
// ports type
|
||||
typename wrap_key_tuple_elements<N,key_matching_port,key_traits_type,OutputTuple>::type,
|
||||
typename wrap_key_tuple_elements<key_matching_port,key_traits_type,OutputTuple>::type,
|
||||
OutputTuple > type;
|
||||
};
|
||||
|
||||
//! unfolded_join_node : passes input_ports_type to join_node_base. We build the input port type
|
||||
// using tuple_element. The class PT is the port type (reserving_port, queueing_port, key_matching_port)
|
||||
// and should match the typename.
|
||||
|
||||
template<int N, template<class> class PT, typename OutputTuple, typename JP>
|
||||
class unfolded_join_node : public join_base<N,PT,OutputTuple,JP>::type {
|
||||
public:
|
||||
typedef typename wrap_tuple_elements<N, PT, OutputTuple>::type input_ports_type;
|
||||
typedef OutputTuple output_type;
|
||||
private:
|
||||
typedef join_node_base<JP, input_ports_type, output_type > base_type;
|
||||
public:
|
||||
unfolded_join_node(graph &g) : base_type(g) {}
|
||||
unfolded_join_node(const unfolded_join_node &other) : base_type(other) {}
|
||||
};
|
||||
|
||||
#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING
|
||||
template <typename K, typename T>
|
||||
struct key_from_message_body {
|
||||
@@ -1239,463 +1223,53 @@
|
||||
}
|
||||
};
|
||||
#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */
|
||||
|
||||
//! unfolded_join_node : passes input_ports_type to join_node_base. We build the input port type
|
||||
// using tuple_element. The class PT is the port type (reserving_port, queueing_port, key_matching_port)
|
||||
// and should match the typename.
|
||||
|
||||
template<template<class> class PT, typename OutputTuple, typename JP>
|
||||
class unfolded_join_node : public join_base<PT, OutputTuple, JP>::type {
|
||||
public:
|
||||
using input_ports_type = typename wrap_tuple_elements<PT, OutputTuple>::type;
|
||||
using output_type = OutputTuple;
|
||||
private:
|
||||
using base_type = join_node_base<JP, input_ports_type, output_type>;
|
||||
public:
|
||||
unfolded_join_node(graph& g) : base_type(g) {}
|
||||
unfolded_join_node(const unfolded_join_node &other) : base_type(other) {}
|
||||
};
|
||||
|
||||
// key_matching unfolded_join_node. This must be a separate specialization because the constructors
|
||||
// differ.
|
||||
|
||||
template<typename OutputTuple, typename K, typename KHash>
|
||||
class unfolded_join_node<2,key_matching_port,OutputTuple,key_matching<K,KHash> > : public
|
||||
join_base<2,key_matching_port,OutputTuple,key_matching<K,KHash> >::type {
|
||||
typedef typename std::tuple_element<0, OutputTuple>::type T0;
|
||||
typedef typename std::tuple_element<1, OutputTuple>::type T1;
|
||||
template<typename K, typename KHash, typename...Types>
|
||||
class unfolded_join_node<key_matching_port, std::tuple<Types...>, key_matching<K, KHash>>
|
||||
: public join_base<key_matching_port, std::tuple<Types...>, key_matching<K, KHash>>::type
|
||||
{
|
||||
public:
|
||||
typedef typename wrap_key_tuple_elements<2,key_matching_port,key_matching<K,KHash>,OutputTuple>::type input_ports_type;
|
||||
typedef OutputTuple output_type;
|
||||
using input_ports_type = typename wrap_key_tuple_elements<key_matching_port,
|
||||
key_matching<K, KHash>,
|
||||
std::tuple<Types...>>::type;
|
||||
using output_type = std::tuple<Types...>;
|
||||
private:
|
||||
typedef join_node_base<key_matching<K,KHash>, input_ports_type, output_type > base_type;
|
||||
typedef type_to_key_function_body<T0, K> *f0_p;
|
||||
typedef type_to_key_function_body<T1, K> *f1_p;
|
||||
typedef std::tuple< f0_p, f1_p > func_initializer_type;
|
||||
using base_type = join_node_base<key_matching<K, KHash>, input_ports_type, output_type>;
|
||||
using func_initializer_type = std::tuple<type_to_key_function_body<Types, K>*...>;
|
||||
public:
|
||||
#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING
|
||||
unfolded_join_node(graph &g) : base_type(g,
|
||||
func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, key_from_message_body<K,T0> >(key_from_message_body<K,T0>()),
|
||||
new type_to_key_function_body_leaf<T1, K, key_from_message_body<K,T1> >(key_from_message_body<K,T1>())
|
||||
) ) {
|
||||
}
|
||||
#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */
|
||||
template<typename Body0, typename Body1>
|
||||
unfolded_join_node(graph &g, Body0 body0, Body1 body1) : base_type(g,
|
||||
func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, Body0>(body0),
|
||||
new type_to_key_function_body_leaf<T1, K, Body1>(body1)
|
||||
) ) {
|
||||
static_assert(std::tuple_size<OutputTuple>::value == 2, "wrong number of body initializers");
|
||||
}
|
||||
unfolded_join_node(const unfolded_join_node &other) : base_type(other) {}
|
||||
};
|
||||
|
||||
template<typename OutputTuple, typename K, typename KHash>
|
||||
class unfolded_join_node<3,key_matching_port,OutputTuple,key_matching<K,KHash> > : public
|
||||
join_base<3,key_matching_port,OutputTuple,key_matching<K,KHash> >::type {
|
||||
typedef typename std::tuple_element<0, OutputTuple>::type T0;
|
||||
typedef typename std::tuple_element<1, OutputTuple>::type T1;
|
||||
typedef typename std::tuple_element<2, OutputTuple>::type T2;
|
||||
public:
|
||||
typedef typename wrap_key_tuple_elements<3,key_matching_port,key_matching<K,KHash>,OutputTuple>::type input_ports_type;
|
||||
typedef OutputTuple output_type;
|
||||
private:
|
||||
typedef join_node_base<key_matching<K,KHash>, input_ports_type, output_type > base_type;
|
||||
typedef type_to_key_function_body<T0, K> *f0_p;
|
||||
typedef type_to_key_function_body<T1, K> *f1_p;
|
||||
typedef type_to_key_function_body<T2, K> *f2_p;
|
||||
typedef std::tuple< f0_p, f1_p, f2_p > func_initializer_type;
|
||||
public:
|
||||
#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING
|
||||
unfolded_join_node(graph &g) : base_type(g,
|
||||
func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, key_from_message_body<K,T0> >(key_from_message_body<K,T0>()),
|
||||
new type_to_key_function_body_leaf<T1, K, key_from_message_body<K,T1> >(key_from_message_body<K,T1>()),
|
||||
new type_to_key_function_body_leaf<T2, K, key_from_message_body<K,T2> >(key_from_message_body<K,T2>())
|
||||
) ) {
|
||||
}
|
||||
#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */
|
||||
template<typename Body0, typename Body1, typename Body2>
|
||||
unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2) : base_type(g,
|
||||
func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, Body0>(body0),
|
||||
new type_to_key_function_body_leaf<T1, K, Body1>(body1),
|
||||
new type_to_key_function_body_leaf<T2, K, Body2>(body2)
|
||||
) ) {
|
||||
static_assert(std::tuple_size<OutputTuple>::value == 3, "wrong number of body initializers");
|
||||
}
|
||||
unfolded_join_node(const unfolded_join_node &other) : base_type(other) {}
|
||||
};
|
||||
|
||||
template<typename OutputTuple, typename K, typename KHash>
|
||||
class unfolded_join_node<4,key_matching_port,OutputTuple,key_matching<K,KHash> > : public
|
||||
join_base<4,key_matching_port,OutputTuple,key_matching<K,KHash> >::type {
|
||||
typedef typename std::tuple_element<0, OutputTuple>::type T0;
|
||||
typedef typename std::tuple_element<1, OutputTuple>::type T1;
|
||||
typedef typename std::tuple_element<2, OutputTuple>::type T2;
|
||||
typedef typename std::tuple_element<3, OutputTuple>::type T3;
|
||||
public:
|
||||
typedef typename wrap_key_tuple_elements<4,key_matching_port,key_matching<K,KHash>,OutputTuple>::type input_ports_type;
|
||||
typedef OutputTuple output_type;
|
||||
private:
|
||||
typedef join_node_base<key_matching<K,KHash>, input_ports_type, output_type > base_type;
|
||||
typedef type_to_key_function_body<T0, K> *f0_p;
|
||||
typedef type_to_key_function_body<T1, K> *f1_p;
|
||||
typedef type_to_key_function_body<T2, K> *f2_p;
|
||||
typedef type_to_key_function_body<T3, K> *f3_p;
|
||||
typedef std::tuple< f0_p, f1_p, f2_p, f3_p > func_initializer_type;
|
||||
public:
|
||||
#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING
|
||||
unfolded_join_node(graph &g) : base_type(g,
|
||||
func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, key_from_message_body<K,T0> >(key_from_message_body<K,T0>()),
|
||||
new type_to_key_function_body_leaf<T1, K, key_from_message_body<K,T1> >(key_from_message_body<K,T1>()),
|
||||
new type_to_key_function_body_leaf<T2, K, key_from_message_body<K,T2> >(key_from_message_body<K,T2>()),
|
||||
new type_to_key_function_body_leaf<T3, K, key_from_message_body<K,T3> >(key_from_message_body<K,T3>())
|
||||
) ) {
|
||||
}
|
||||
#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */
|
||||
template<typename Body0, typename Body1, typename Body2, typename Body3>
|
||||
unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3) : base_type(g,
|
||||
func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, Body0>(body0),
|
||||
new type_to_key_function_body_leaf<T1, K, Body1>(body1),
|
||||
new type_to_key_function_body_leaf<T2, K, Body2>(body2),
|
||||
new type_to_key_function_body_leaf<T3, K, Body3>(body3)
|
||||
) ) {
|
||||
static_assert(std::tuple_size<OutputTuple>::value == 4, "wrong number of body initializers");
|
||||
}
|
||||
unfolded_join_node(const unfolded_join_node &other) : base_type(other) {}
|
||||
};
|
||||
|
||||
template<typename OutputTuple, typename K, typename KHash>
|
||||
class unfolded_join_node<5,key_matching_port,OutputTuple,key_matching<K,KHash> > : public
|
||||
join_base<5,key_matching_port,OutputTuple,key_matching<K,KHash> >::type {
|
||||
typedef typename std::tuple_element<0, OutputTuple>::type T0;
|
||||
typedef typename std::tuple_element<1, OutputTuple>::type T1;
|
||||
typedef typename std::tuple_element<2, OutputTuple>::type T2;
|
||||
typedef typename std::tuple_element<3, OutputTuple>::type T3;
|
||||
typedef typename std::tuple_element<4, OutputTuple>::type T4;
|
||||
public:
|
||||
typedef typename wrap_key_tuple_elements<5,key_matching_port,key_matching<K,KHash>,OutputTuple>::type input_ports_type;
|
||||
typedef OutputTuple output_type;
|
||||
private:
|
||||
typedef join_node_base<key_matching<K,KHash> , input_ports_type, output_type > base_type;
|
||||
typedef type_to_key_function_body<T0, K> *f0_p;
|
||||
typedef type_to_key_function_body<T1, K> *f1_p;
|
||||
typedef type_to_key_function_body<T2, K> *f2_p;
|
||||
typedef type_to_key_function_body<T3, K> *f3_p;
|
||||
typedef type_to_key_function_body<T4, K> *f4_p;
|
||||
typedef std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p > func_initializer_type;
|
||||
public:
|
||||
#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING
|
||||
unfolded_join_node(graph &g) : base_type(g,
|
||||
func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, key_from_message_body<K,T0> >(key_from_message_body<K,T0>()),
|
||||
new type_to_key_function_body_leaf<T1, K, key_from_message_body<K,T1> >(key_from_message_body<K,T1>()),
|
||||
new type_to_key_function_body_leaf<T2, K, key_from_message_body<K,T2> >(key_from_message_body<K,T2>()),
|
||||
new type_to_key_function_body_leaf<T3, K, key_from_message_body<K,T3> >(key_from_message_body<K,T3>()),
|
||||
new type_to_key_function_body_leaf<T4, K, key_from_message_body<K,T4> >(key_from_message_body<K,T4>())
|
||||
) ) {
|
||||
}
|
||||
#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */
|
||||
template<typename Body0, typename Body1, typename Body2, typename Body3, typename Body4>
|
||||
unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4) : base_type(g,
|
||||
func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, Body0>(body0),
|
||||
new type_to_key_function_body_leaf<T1, K, Body1>(body1),
|
||||
new type_to_key_function_body_leaf<T2, K, Body2>(body2),
|
||||
new type_to_key_function_body_leaf<T3, K, Body3>(body3),
|
||||
new type_to_key_function_body_leaf<T4, K, Body4>(body4)
|
||||
) ) {
|
||||
static_assert(std::tuple_size<OutputTuple>::value == 5, "wrong number of body initializers");
|
||||
}
|
||||
unfolded_join_node(const unfolded_join_node &other) : base_type(other) {}
|
||||
};
|
||||
|
||||
#if __TBB_VARIADIC_MAX >= 6
|
||||
template<typename OutputTuple, typename K, typename KHash>
|
||||
class unfolded_join_node<6,key_matching_port,OutputTuple,key_matching<K,KHash> > : public
|
||||
join_base<6,key_matching_port,OutputTuple,key_matching<K,KHash> >::type {
|
||||
typedef typename std::tuple_element<0, OutputTuple>::type T0;
|
||||
typedef typename std::tuple_element<1, OutputTuple>::type T1;
|
||||
typedef typename std::tuple_element<2, OutputTuple>::type T2;
|
||||
typedef typename std::tuple_element<3, OutputTuple>::type T3;
|
||||
typedef typename std::tuple_element<4, OutputTuple>::type T4;
|
||||
typedef typename std::tuple_element<5, OutputTuple>::type T5;
|
||||
public:
|
||||
typedef typename wrap_key_tuple_elements<6,key_matching_port,key_matching<K,KHash>,OutputTuple>::type input_ports_type;
|
||||
typedef OutputTuple output_type;
|
||||
private:
|
||||
typedef join_node_base<key_matching<K,KHash> , input_ports_type, output_type > base_type;
|
||||
typedef type_to_key_function_body<T0, K> *f0_p;
|
||||
typedef type_to_key_function_body<T1, K> *f1_p;
|
||||
typedef type_to_key_function_body<T2, K> *f2_p;
|
||||
typedef type_to_key_function_body<T3, K> *f3_p;
|
||||
typedef type_to_key_function_body<T4, K> *f4_p;
|
||||
typedef type_to_key_function_body<T5, K> *f5_p;
|
||||
typedef std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p > func_initializer_type;
|
||||
public:
|
||||
#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING
|
||||
unfolded_join_node(graph &g) : base_type(g,
|
||||
func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, key_from_message_body<K,T0> >(key_from_message_body<K,T0>()),
|
||||
new type_to_key_function_body_leaf<T1, K, key_from_message_body<K,T1> >(key_from_message_body<K,T1>()),
|
||||
new type_to_key_function_body_leaf<T2, K, key_from_message_body<K,T2> >(key_from_message_body<K,T2>()),
|
||||
new type_to_key_function_body_leaf<T3, K, key_from_message_body<K,T3> >(key_from_message_body<K,T3>()),
|
||||
new type_to_key_function_body_leaf<T4, K, key_from_message_body<K,T4> >(key_from_message_body<K,T4>()),
|
||||
new type_to_key_function_body_leaf<T5, K, key_from_message_body<K,T5> >(key_from_message_body<K,T5>())
|
||||
) ) {
|
||||
}
|
||||
#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */
|
||||
template<typename Body0, typename Body1, typename Body2, typename Body3, typename Body4, typename Body5>
|
||||
unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4, Body5 body5)
|
||||
: base_type(g, func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, Body0>(body0),
|
||||
new type_to_key_function_body_leaf<T1, K, Body1>(body1),
|
||||
new type_to_key_function_body_leaf<T2, K, Body2>(body2),
|
||||
new type_to_key_function_body_leaf<T3, K, Body3>(body3),
|
||||
new type_to_key_function_body_leaf<T4, K, Body4>(body4),
|
||||
new type_to_key_function_body_leaf<T5, K, Body5>(body5)
|
||||
) ) {
|
||||
static_assert(std::tuple_size<OutputTuple>::value == 6, "wrong number of body initializers");
|
||||
}
|
||||
unfolded_join_node(const unfolded_join_node &other) : base_type(other) {}
|
||||
};
|
||||
unfolded_join_node(graph &g)
|
||||
: base_type(g,
|
||||
func_initializer_type(new type_to_key_function_body_leaf<Types, K,
|
||||
key_from_message_body<K, Types>>(key_from_message_body<K, Types>())...))
|
||||
{}
|
||||
#endif
|
||||
|
||||
#if __TBB_VARIADIC_MAX >= 7
|
||||
template<typename OutputTuple, typename K, typename KHash>
|
||||
class unfolded_join_node<7,key_matching_port,OutputTuple,key_matching<K,KHash> > : public
|
||||
join_base<7,key_matching_port,OutputTuple,key_matching<K,KHash> >::type {
|
||||
typedef typename std::tuple_element<0, OutputTuple>::type T0;
|
||||
typedef typename std::tuple_element<1, OutputTuple>::type T1;
|
||||
typedef typename std::tuple_element<2, OutputTuple>::type T2;
|
||||
typedef typename std::tuple_element<3, OutputTuple>::type T3;
|
||||
typedef typename std::tuple_element<4, OutputTuple>::type T4;
|
||||
typedef typename std::tuple_element<5, OutputTuple>::type T5;
|
||||
typedef typename std::tuple_element<6, OutputTuple>::type T6;
|
||||
public:
|
||||
typedef typename wrap_key_tuple_elements<7,key_matching_port,key_matching<K,KHash>,OutputTuple>::type input_ports_type;
|
||||
typedef OutputTuple output_type;
|
||||
private:
|
||||
typedef join_node_base<key_matching<K,KHash> , input_ports_type, output_type > base_type;
|
||||
typedef type_to_key_function_body<T0, K> *f0_p;
|
||||
typedef type_to_key_function_body<T1, K> *f1_p;
|
||||
typedef type_to_key_function_body<T2, K> *f2_p;
|
||||
typedef type_to_key_function_body<T3, K> *f3_p;
|
||||
typedef type_to_key_function_body<T4, K> *f4_p;
|
||||
typedef type_to_key_function_body<T5, K> *f5_p;
|
||||
typedef type_to_key_function_body<T6, K> *f6_p;
|
||||
typedef std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6_p > func_initializer_type;
|
||||
public:
|
||||
#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING
|
||||
unfolded_join_node(graph &g) : base_type(g,
|
||||
func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, key_from_message_body<K,T0> >(key_from_message_body<K,T0>()),
|
||||
new type_to_key_function_body_leaf<T1, K, key_from_message_body<K,T1> >(key_from_message_body<K,T1>()),
|
||||
new type_to_key_function_body_leaf<T2, K, key_from_message_body<K,T2> >(key_from_message_body<K,T2>()),
|
||||
new type_to_key_function_body_leaf<T3, K, key_from_message_body<K,T3> >(key_from_message_body<K,T3>()),
|
||||
new type_to_key_function_body_leaf<T4, K, key_from_message_body<K,T4> >(key_from_message_body<K,T4>()),
|
||||
new type_to_key_function_body_leaf<T5, K, key_from_message_body<K,T5> >(key_from_message_body<K,T5>()),
|
||||
new type_to_key_function_body_leaf<T6, K, key_from_message_body<K,T6> >(key_from_message_body<K,T6>())
|
||||
) ) {
|
||||
}
|
||||
#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */
|
||||
template<typename Body0, typename Body1, typename Body2, typename Body3, typename Body4,
|
||||
typename Body5, typename Body6>
|
||||
unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4,
|
||||
Body5 body5, Body6 body6) : base_type(g, func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, Body0>(body0),
|
||||
new type_to_key_function_body_leaf<T1, K, Body1>(body1),
|
||||
new type_to_key_function_body_leaf<T2, K, Body2>(body2),
|
||||
new type_to_key_function_body_leaf<T3, K, Body3>(body3),
|
||||
new type_to_key_function_body_leaf<T4, K, Body4>(body4),
|
||||
new type_to_key_function_body_leaf<T5, K, Body5>(body5),
|
||||
new type_to_key_function_body_leaf<T6, K, Body6>(body6)
|
||||
) ) {
|
||||
static_assert(std::tuple_size<OutputTuple>::value == 7, "wrong number of body initializers");
|
||||
}
|
||||
template<typename... Bodies>
|
||||
unfolded_join_node(graph &g, Bodies... bodies)
|
||||
: base_type(g,
|
||||
func_initializer_type(new type_to_key_function_body_leaf<Types, K, Bodies>(bodies)...))
|
||||
{}
|
||||
unfolded_join_node(const unfolded_join_node &other) : base_type(other) {}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if __TBB_VARIADIC_MAX >= 8
|
||||
template<typename OutputTuple, typename K, typename KHash>
|
||||
class unfolded_join_node<8,key_matching_port,OutputTuple,key_matching<K,KHash> > : public
|
||||
join_base<8,key_matching_port,OutputTuple,key_matching<K,KHash> >::type {
|
||||
typedef typename std::tuple_element<0, OutputTuple>::type T0;
|
||||
typedef typename std::tuple_element<1, OutputTuple>::type T1;
|
||||
typedef typename std::tuple_element<2, OutputTuple>::type T2;
|
||||
typedef typename std::tuple_element<3, OutputTuple>::type T3;
|
||||
typedef typename std::tuple_element<4, OutputTuple>::type T4;
|
||||
typedef typename std::tuple_element<5, OutputTuple>::type T5;
|
||||
typedef typename std::tuple_element<6, OutputTuple>::type T6;
|
||||
typedef typename std::tuple_element<7, OutputTuple>::type T7;
|
||||
public:
|
||||
typedef typename wrap_key_tuple_elements<8,key_matching_port,key_matching<K,KHash>,OutputTuple>::type input_ports_type;
|
||||
typedef OutputTuple output_type;
|
||||
private:
|
||||
typedef join_node_base<key_matching<K,KHash> , input_ports_type, output_type > base_type;
|
||||
typedef type_to_key_function_body<T0, K> *f0_p;
|
||||
typedef type_to_key_function_body<T1, K> *f1_p;
|
||||
typedef type_to_key_function_body<T2, K> *f2_p;
|
||||
typedef type_to_key_function_body<T3, K> *f3_p;
|
||||
typedef type_to_key_function_body<T4, K> *f4_p;
|
||||
typedef type_to_key_function_body<T5, K> *f5_p;
|
||||
typedef type_to_key_function_body<T6, K> *f6_p;
|
||||
typedef type_to_key_function_body<T7, K> *f7_p;
|
||||
typedef std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6_p, f7_p > func_initializer_type;
|
||||
public:
|
||||
#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING
|
||||
unfolded_join_node(graph &g) : base_type(g,
|
||||
func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, key_from_message_body<K,T0> >(key_from_message_body<K,T0>()),
|
||||
new type_to_key_function_body_leaf<T1, K, key_from_message_body<K,T1> >(key_from_message_body<K,T1>()),
|
||||
new type_to_key_function_body_leaf<T2, K, key_from_message_body<K,T2> >(key_from_message_body<K,T2>()),
|
||||
new type_to_key_function_body_leaf<T3, K, key_from_message_body<K,T3> >(key_from_message_body<K,T3>()),
|
||||
new type_to_key_function_body_leaf<T4, K, key_from_message_body<K,T4> >(key_from_message_body<K,T4>()),
|
||||
new type_to_key_function_body_leaf<T5, K, key_from_message_body<K,T5> >(key_from_message_body<K,T5>()),
|
||||
new type_to_key_function_body_leaf<T6, K, key_from_message_body<K,T6> >(key_from_message_body<K,T6>()),
|
||||
new type_to_key_function_body_leaf<T7, K, key_from_message_body<K,T7> >(key_from_message_body<K,T7>())
|
||||
) ) {
|
||||
}
|
||||
#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */
|
||||
template<typename Body0, typename Body1, typename Body2, typename Body3, typename Body4,
|
||||
typename Body5, typename Body6, typename Body7>
|
||||
unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4,
|
||||
Body5 body5, Body6 body6, Body7 body7) : base_type(g, func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, Body0>(body0),
|
||||
new type_to_key_function_body_leaf<T1, K, Body1>(body1),
|
||||
new type_to_key_function_body_leaf<T2, K, Body2>(body2),
|
||||
new type_to_key_function_body_leaf<T3, K, Body3>(body3),
|
||||
new type_to_key_function_body_leaf<T4, K, Body4>(body4),
|
||||
new type_to_key_function_body_leaf<T5, K, Body5>(body5),
|
||||
new type_to_key_function_body_leaf<T6, K, Body6>(body6),
|
||||
new type_to_key_function_body_leaf<T7, K, Body7>(body7)
|
||||
) ) {
|
||||
static_assert(std::tuple_size<OutputTuple>::value == 8, "wrong number of body initializers");
|
||||
}
|
||||
unfolded_join_node(const unfolded_join_node &other) : base_type(other) {}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if __TBB_VARIADIC_MAX >= 9
|
||||
template<typename OutputTuple, typename K, typename KHash>
|
||||
class unfolded_join_node<9,key_matching_port,OutputTuple,key_matching<K,KHash> > : public
|
||||
join_base<9,key_matching_port,OutputTuple,key_matching<K,KHash> >::type {
|
||||
typedef typename std::tuple_element<0, OutputTuple>::type T0;
|
||||
typedef typename std::tuple_element<1, OutputTuple>::type T1;
|
||||
typedef typename std::tuple_element<2, OutputTuple>::type T2;
|
||||
typedef typename std::tuple_element<3, OutputTuple>::type T3;
|
||||
typedef typename std::tuple_element<4, OutputTuple>::type T4;
|
||||
typedef typename std::tuple_element<5, OutputTuple>::type T5;
|
||||
typedef typename std::tuple_element<6, OutputTuple>::type T6;
|
||||
typedef typename std::tuple_element<7, OutputTuple>::type T7;
|
||||
typedef typename std::tuple_element<8, OutputTuple>::type T8;
|
||||
public:
|
||||
typedef typename wrap_key_tuple_elements<9,key_matching_port,key_matching<K,KHash>,OutputTuple>::type input_ports_type;
|
||||
typedef OutputTuple output_type;
|
||||
private:
|
||||
typedef join_node_base<key_matching<K,KHash> , input_ports_type, output_type > base_type;
|
||||
typedef type_to_key_function_body<T0, K> *f0_p;
|
||||
typedef type_to_key_function_body<T1, K> *f1_p;
|
||||
typedef type_to_key_function_body<T2, K> *f2_p;
|
||||
typedef type_to_key_function_body<T3, K> *f3_p;
|
||||
typedef type_to_key_function_body<T4, K> *f4_p;
|
||||
typedef type_to_key_function_body<T5, K> *f5_p;
|
||||
typedef type_to_key_function_body<T6, K> *f6_p;
|
||||
typedef type_to_key_function_body<T7, K> *f7_p;
|
||||
typedef type_to_key_function_body<T8, K> *f8_p;
|
||||
typedef std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6_p, f7_p, f8_p > func_initializer_type;
|
||||
public:
|
||||
#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING
|
||||
unfolded_join_node(graph &g) : base_type(g,
|
||||
func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, key_from_message_body<K,T0> >(key_from_message_body<K,T0>()),
|
||||
new type_to_key_function_body_leaf<T1, K, key_from_message_body<K,T1> >(key_from_message_body<K,T1>()),
|
||||
new type_to_key_function_body_leaf<T2, K, key_from_message_body<K,T2> >(key_from_message_body<K,T2>()),
|
||||
new type_to_key_function_body_leaf<T3, K, key_from_message_body<K,T3> >(key_from_message_body<K,T3>()),
|
||||
new type_to_key_function_body_leaf<T4, K, key_from_message_body<K,T4> >(key_from_message_body<K,T4>()),
|
||||
new type_to_key_function_body_leaf<T5, K, key_from_message_body<K,T5> >(key_from_message_body<K,T5>()),
|
||||
new type_to_key_function_body_leaf<T6, K, key_from_message_body<K,T6> >(key_from_message_body<K,T6>()),
|
||||
new type_to_key_function_body_leaf<T7, K, key_from_message_body<K,T7> >(key_from_message_body<K,T7>()),
|
||||
new type_to_key_function_body_leaf<T8, K, key_from_message_body<K,T8> >(key_from_message_body<K,T8>())
|
||||
) ) {
|
||||
}
|
||||
#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */
|
||||
template<typename Body0, typename Body1, typename Body2, typename Body3, typename Body4,
|
||||
typename Body5, typename Body6, typename Body7, typename Body8>
|
||||
unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4,
|
||||
Body5 body5, Body6 body6, Body7 body7, Body8 body8) : base_type(g, func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, Body0>(body0),
|
||||
new type_to_key_function_body_leaf<T1, K, Body1>(body1),
|
||||
new type_to_key_function_body_leaf<T2, K, Body2>(body2),
|
||||
new type_to_key_function_body_leaf<T3, K, Body3>(body3),
|
||||
new type_to_key_function_body_leaf<T4, K, Body4>(body4),
|
||||
new type_to_key_function_body_leaf<T5, K, Body5>(body5),
|
||||
new type_to_key_function_body_leaf<T6, K, Body6>(body6),
|
||||
new type_to_key_function_body_leaf<T7, K, Body7>(body7),
|
||||
new type_to_key_function_body_leaf<T8, K, Body8>(body8)
|
||||
) ) {
|
||||
static_assert(std::tuple_size<OutputTuple>::value == 9, "wrong number of body initializers");
|
||||
}
|
||||
unfolded_join_node(const unfolded_join_node &other) : base_type(other) {}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if __TBB_VARIADIC_MAX >= 10
|
||||
template<typename OutputTuple, typename K, typename KHash>
|
||||
class unfolded_join_node<10,key_matching_port,OutputTuple,key_matching<K,KHash> > : public
|
||||
join_base<10,key_matching_port,OutputTuple,key_matching<K,KHash> >::type {
|
||||
typedef typename std::tuple_element<0, OutputTuple>::type T0;
|
||||
typedef typename std::tuple_element<1, OutputTuple>::type T1;
|
||||
typedef typename std::tuple_element<2, OutputTuple>::type T2;
|
||||
typedef typename std::tuple_element<3, OutputTuple>::type T3;
|
||||
typedef typename std::tuple_element<4, OutputTuple>::type T4;
|
||||
typedef typename std::tuple_element<5, OutputTuple>::type T5;
|
||||
typedef typename std::tuple_element<6, OutputTuple>::type T6;
|
||||
typedef typename std::tuple_element<7, OutputTuple>::type T7;
|
||||
typedef typename std::tuple_element<8, OutputTuple>::type T8;
|
||||
typedef typename std::tuple_element<9, OutputTuple>::type T9;
|
||||
public:
|
||||
typedef typename wrap_key_tuple_elements<10,key_matching_port,key_matching<K,KHash>,OutputTuple>::type input_ports_type;
|
||||
typedef OutputTuple output_type;
|
||||
private:
|
||||
typedef join_node_base<key_matching<K,KHash> , input_ports_type, output_type > base_type;
|
||||
typedef type_to_key_function_body<T0, K> *f0_p;
|
||||
typedef type_to_key_function_body<T1, K> *f1_p;
|
||||
typedef type_to_key_function_body<T2, K> *f2_p;
|
||||
typedef type_to_key_function_body<T3, K> *f3_p;
|
||||
typedef type_to_key_function_body<T4, K> *f4_p;
|
||||
typedef type_to_key_function_body<T5, K> *f5_p;
|
||||
typedef type_to_key_function_body<T6, K> *f6_p;
|
||||
typedef type_to_key_function_body<T7, K> *f7_p;
|
||||
typedef type_to_key_function_body<T8, K> *f8_p;
|
||||
typedef type_to_key_function_body<T9, K> *f9_p;
|
||||
typedef std::tuple< f0_p, f1_p, f2_p, f3_p, f4_p, f5_p, f6_p, f7_p, f8_p, f9_p > func_initializer_type;
|
||||
public:
|
||||
#if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING
|
||||
unfolded_join_node(graph &g) : base_type(g,
|
||||
func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, key_from_message_body<K,T0> >(key_from_message_body<K,T0>()),
|
||||
new type_to_key_function_body_leaf<T1, K, key_from_message_body<K,T1> >(key_from_message_body<K,T1>()),
|
||||
new type_to_key_function_body_leaf<T2, K, key_from_message_body<K,T2> >(key_from_message_body<K,T2>()),
|
||||
new type_to_key_function_body_leaf<T3, K, key_from_message_body<K,T3> >(key_from_message_body<K,T3>()),
|
||||
new type_to_key_function_body_leaf<T4, K, key_from_message_body<K,T4> >(key_from_message_body<K,T4>()),
|
||||
new type_to_key_function_body_leaf<T5, K, key_from_message_body<K,T5> >(key_from_message_body<K,T5>()),
|
||||
new type_to_key_function_body_leaf<T6, K, key_from_message_body<K,T6> >(key_from_message_body<K,T6>()),
|
||||
new type_to_key_function_body_leaf<T7, K, key_from_message_body<K,T7> >(key_from_message_body<K,T7>()),
|
||||
new type_to_key_function_body_leaf<T8, K, key_from_message_body<K,T8> >(key_from_message_body<K,T8>()),
|
||||
new type_to_key_function_body_leaf<T9, K, key_from_message_body<K,T9> >(key_from_message_body<K,T9>())
|
||||
) ) {
|
||||
}
|
||||
#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */
|
||||
template<typename Body0, typename Body1, typename Body2, typename Body3, typename Body4,
|
||||
typename Body5, typename Body6, typename Body7, typename Body8, typename Body9>
|
||||
unfolded_join_node(graph &g, Body0 body0, Body1 body1, Body2 body2, Body3 body3, Body4 body4,
|
||||
Body5 body5, Body6 body6, Body7 body7, Body8 body8, Body9 body9) : base_type(g, func_initializer_type(
|
||||
new type_to_key_function_body_leaf<T0, K, Body0>(body0),
|
||||
new type_to_key_function_body_leaf<T1, K, Body1>(body1),
|
||||
new type_to_key_function_body_leaf<T2, K, Body2>(body2),
|
||||
new type_to_key_function_body_leaf<T3, K, Body3>(body3),
|
||||
new type_to_key_function_body_leaf<T4, K, Body4>(body4),
|
||||
new type_to_key_function_body_leaf<T5, K, Body5>(body5),
|
||||
new type_to_key_function_body_leaf<T6, K, Body6>(body6),
|
||||
new type_to_key_function_body_leaf<T7, K, Body7>(body7),
|
||||
new type_to_key_function_body_leaf<T8, K, Body8>(body8),
|
||||
new type_to_key_function_body_leaf<T9, K, Body9>(body9)
|
||||
) ) {
|
||||
static_assert(std::tuple_size<OutputTuple>::value == 10, "wrong number of body initializers");
|
||||
}
|
||||
unfolded_join_node(const unfolded_join_node &other) : base_type(other) {}
|
||||
};
|
||||
#endif
|
||||
|
||||
//! templated function to refer to input ports of the join node
|
||||
template<size_t N, typename JNT>
|
||||
|
||||
@@ -43,21 +43,21 @@ struct KeyTrait {
|
||||
};
|
||||
|
||||
// wrap each element of a tuple in a template, and make a tuple of the result.
|
||||
template<int N, template<class> class PT, typename TypeTuple>
|
||||
template<template<class> class PT, typename TypeTuple>
|
||||
struct wrap_tuple_elements;
|
||||
|
||||
// A wrapper that generates the traits needed for each port of a key-matching join,
|
||||
// and the type of the tuple of input ports.
|
||||
template<int N, template<class> class PT, typename KeyTraits, typename TypeTuple>
|
||||
template<template<class> class PT, typename KeyTraits, typename TypeTuple>
|
||||
struct wrap_key_tuple_elements;
|
||||
|
||||
template<int N, template<class> class PT, typename... Args>
|
||||
struct wrap_tuple_elements<N, PT, std::tuple<Args...> >{
|
||||
template<template<class> class PT, typename... Args>
|
||||
struct wrap_tuple_elements<PT, std::tuple<Args...> >{
|
||||
typedef typename std::tuple<PT<Args>... > type;
|
||||
};
|
||||
|
||||
template<int N, template<class> class PT, typename KeyTraits, typename... Args>
|
||||
struct wrap_key_tuple_elements<N, PT, KeyTraits, std::tuple<Args...> > {
|
||||
template<template<class> class PT, typename KeyTraits, typename... Args>
|
||||
struct wrap_key_tuple_elements<PT, KeyTraits, std::tuple<Args...> > {
|
||||
typedef typename KeyTraits::key_type K;
|
||||
typedef typename KeyTraits::hash_compare_type KHash;
|
||||
typedef typename std::tuple<PT<KeyTrait<K, KHash, Args> >... > type;
|
||||
@@ -293,31 +293,11 @@ struct do_if<T, false> {
|
||||
// the object can only be tested for type, and a read-only reference can be fetched by cast_to<T>().
|
||||
|
||||
using tbb::detail::punned_cast;
|
||||
struct tagged_null_type {};
|
||||
template<typename TagType, typename T0, typename T1=tagged_null_type, typename 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 T7=tagged_null_type, typename T8=tagged_null_type, typename T9=tagged_null_type>
|
||||
class tagged_msg {
|
||||
typedef std::tuple<T0, T1, T2, T3, T4
|
||||
//TODO: Should we reject lists longer than a tuple can hold?
|
||||
#if __TBB_VARIADIC_MAX >= 6
|
||||
, T5
|
||||
#endif
|
||||
#if __TBB_VARIADIC_MAX >= 7
|
||||
, T6
|
||||
#endif
|
||||
#if __TBB_VARIADIC_MAX >= 8
|
||||
, T7
|
||||
#endif
|
||||
#if __TBB_VARIADIC_MAX >= 9
|
||||
, T8
|
||||
#endif
|
||||
#if __TBB_VARIADIC_MAX >= 10
|
||||
, T9
|
||||
#endif
|
||||
> Tuple;
|
||||
|
||||
private:
|
||||
template<typename TagType, typename T0, typename... TN>
|
||||
class tagged_msg {
|
||||
using Tuple = std::tuple<T0, TN...>;
|
||||
|
||||
class variant {
|
||||
static const size_t N = std::tuple_size<Tuple>::value;
|
||||
typedef typename pick_tuple_max<N, Tuple, alignment_of>::type AlignType;
|
||||
@@ -373,7 +353,6 @@ private:
|
||||
|
||||
TagType my_tag;
|
||||
variant my_msg;
|
||||
|
||||
public:
|
||||
tagged_msg(): my_tag(TagType(~0)), my_msg(){}
|
||||
|
||||
@@ -393,7 +372,7 @@ public:
|
||||
bool is_a() const {return my_msg.template variant_is_a<V>();}
|
||||
|
||||
bool is_default_constructed() const {return my_msg.variant_is_default_constructed();}
|
||||
}; //class tagged_msg
|
||||
};
|
||||
|
||||
// template to simplify cast and test for tagged_msg in template contexts
|
||||
template<typename V, typename T>
|
||||
|
||||
+19
-361
@@ -856,7 +856,6 @@ class multifunction_node :
|
||||
<
|
||||
Input,
|
||||
typename wrap_tuple_elements<
|
||||
std::tuple_size<Output>::value, // #elements in tuple
|
||||
multifunction_output, // wrap this around each element
|
||||
Output // the tuple providing the types
|
||||
>::type,
|
||||
@@ -871,7 +870,7 @@ protected:
|
||||
public:
|
||||
typedef Input input_type;
|
||||
typedef null_type output_type;
|
||||
typedef typename wrap_tuple_elements<N,multifunction_output, Output>::type output_ports_type;
|
||||
typedef typename wrap_tuple_elements<multifunction_output, Output>::type output_ports_type;
|
||||
typedef multifunction_input<
|
||||
input_type, output_ports_type, Policy, internals_allocator> input_impl_type;
|
||||
typedef function_input_queue<input_type, internals_allocator> input_queue_type;
|
||||
@@ -932,7 +931,6 @@ class split_node : public graph_node, public receiver<TupleType> {
|
||||
public:
|
||||
typedef TupleType input_type;
|
||||
typedef typename wrap_tuple_elements<
|
||||
N, // #elements in tuple
|
||||
multifunction_output, // wrap this around each element
|
||||
TupleType // the tuple providing the types
|
||||
>::type output_ports_type;
|
||||
@@ -2138,10 +2136,10 @@ protected:
|
||||
template<typename OutputTuple, typename JP=queueing> class join_node;
|
||||
|
||||
template<typename OutputTuple>
|
||||
class join_node<OutputTuple,reserving>: public unfolded_join_node<std::tuple_size<OutputTuple>::value, reserving_port, OutputTuple, reserving> {
|
||||
class join_node<OutputTuple,reserving>: public unfolded_join_node<reserving_port, OutputTuple, reserving> {
|
||||
private:
|
||||
static const int N = std::tuple_size<OutputTuple>::value;
|
||||
typedef unfolded_join_node<N, reserving_port, OutputTuple, reserving> unfolded_type;
|
||||
typedef unfolded_join_node<reserving_port, OutputTuple, reserving> unfolded_type;
|
||||
public:
|
||||
typedef OutputTuple output_type;
|
||||
typedef typename unfolded_type::input_ports_type input_ports_type;
|
||||
@@ -2165,10 +2163,10 @@ public:
|
||||
};
|
||||
|
||||
template<typename OutputTuple>
|
||||
class join_node<OutputTuple,queueing>: public unfolded_join_node<std::tuple_size<OutputTuple>::value, queueing_port, OutputTuple, queueing> {
|
||||
class join_node<OutputTuple,queueing>: public unfolded_join_node<queueing_port, OutputTuple, queueing> {
|
||||
private:
|
||||
static const int N = std::tuple_size<OutputTuple>::value;
|
||||
typedef unfolded_join_node<N, queueing_port, OutputTuple, queueing> unfolded_type;
|
||||
typedef unfolded_join_node<queueing_port, OutputTuple, queueing> unfolded_type;
|
||||
public:
|
||||
typedef OutputTuple output_type;
|
||||
typedef typename unfolded_type::input_ports_type input_ports_type;
|
||||
@@ -2210,11 +2208,10 @@ concept join_node_functions = requires {
|
||||
// template for key_matching join_node
|
||||
// tag_matching join_node is a specialization of key_matching, and is source-compatible.
|
||||
template<typename OutputTuple, typename K, typename KHash>
|
||||
class join_node<OutputTuple, key_matching<K, KHash> > : public unfolded_join_node<std::tuple_size<OutputTuple>::value,
|
||||
key_matching_port, OutputTuple, key_matching<K,KHash> > {
|
||||
class join_node<OutputTuple, key_matching<K, KHash> > : public unfolded_join_node<key_matching_port, OutputTuple, key_matching<K,KHash> > {
|
||||
private:
|
||||
static const int N = std::tuple_size<OutputTuple>::value;
|
||||
typedef unfolded_join_node<N, key_matching_port, OutputTuple, key_matching<K,KHash> > unfolded_type;
|
||||
typedef unfolded_join_node<key_matching_port, OutputTuple, key_matching<K,KHash> > unfolded_type;
|
||||
public:
|
||||
typedef OutputTuple output_type;
|
||||
typedef typename unfolded_type::input_ports_type input_ports_type;
|
||||
@@ -2223,81 +2220,12 @@ public:
|
||||
join_node(graph &g) : unfolded_type(g) {}
|
||||
#endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */
|
||||
|
||||
template<typename __TBB_B0, typename __TBB_B1>
|
||||
__TBB_requires(join_node_functions<OutputTuple, K, __TBB_B0, __TBB_B1>)
|
||||
__TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1) : unfolded_type(g, b0, b1) {
|
||||
template<typename... Bodies, typename = typename std::enable_if<sizeof...(Bodies) == N>>
|
||||
__TBB_requires(join_node_functions<OutputTuple, K, Bodies...>)
|
||||
__TBB_NOINLINE_SYM join_node(graph& g, Bodies... bodies) : unfolded_type(g, bodies...) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2>
|
||||
__TBB_requires(join_node_functions<OutputTuple, K, __TBB_B0, __TBB_B1, __TBB_B2>)
|
||||
__TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2) : unfolded_type(g, b0, b1, b2) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typename __TBB_B3>
|
||||
__TBB_requires(join_node_functions<OutputTuple, K, __TBB_B0, __TBB_B1, __TBB_B2, __TBB_B3>)
|
||||
__TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3) : unfolded_type(g, b0, b1, b2, b3) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typename __TBB_B3, typename __TBB_B4>
|
||||
__TBB_requires(join_node_functions<OutputTuple, K, __TBB_B0, __TBB_B1, __TBB_B2, __TBB_B3, __TBB_B4>)
|
||||
__TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4) :
|
||||
unfolded_type(g, b0, b1, b2, b3, b4) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
#if __TBB_VARIADIC_MAX >= 6
|
||||
template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typename __TBB_B3, typename __TBB_B4,
|
||||
typename __TBB_B5>
|
||||
__TBB_requires(join_node_functions<OutputTuple, K, __TBB_B0, __TBB_B1, __TBB_B2, __TBB_B3, __TBB_B4, __TBB_B5>)
|
||||
__TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5) :
|
||||
unfolded_type(g, b0, b1, b2, b3, b4, b5) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
#endif
|
||||
#if __TBB_VARIADIC_MAX >= 7
|
||||
template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typename __TBB_B3, typename __TBB_B4,
|
||||
typename __TBB_B5, typename __TBB_B6>
|
||||
__TBB_requires(join_node_functions<OutputTuple, K, __TBB_B0, __TBB_B1, __TBB_B2, __TBB_B3, __TBB_B4, __TBB_B5, __TBB_B6>)
|
||||
__TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6) :
|
||||
unfolded_type(g, b0, b1, b2, b3, b4, b5, b6) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
#endif
|
||||
#if __TBB_VARIADIC_MAX >= 8
|
||||
template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typename __TBB_B3, typename __TBB_B4,
|
||||
typename __TBB_B5, typename __TBB_B6, typename __TBB_B7>
|
||||
__TBB_requires(join_node_functions<OutputTuple, K, __TBB_B0, __TBB_B1, __TBB_B2, __TBB_B3, __TBB_B4, __TBB_B5, __TBB_B6, __TBB_B7>)
|
||||
__TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6,
|
||||
__TBB_B7 b7) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
#endif
|
||||
#if __TBB_VARIADIC_MAX >= 9
|
||||
template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typename __TBB_B3, typename __TBB_B4,
|
||||
typename __TBB_B5, typename __TBB_B6, typename __TBB_B7, typename __TBB_B8>
|
||||
__TBB_requires(join_node_functions<OutputTuple, K, __TBB_B0, __TBB_B1, __TBB_B2, __TBB_B3, __TBB_B4, __TBB_B5, __TBB_B6, __TBB_B7, __TBB_B8>)
|
||||
__TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6,
|
||||
__TBB_B7 b7, __TBB_B8 b8) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7, b8) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
#endif
|
||||
#if __TBB_VARIADIC_MAX >= 10
|
||||
template<typename __TBB_B0, typename __TBB_B1, typename __TBB_B2, typename __TBB_B3, typename __TBB_B4,
|
||||
typename __TBB_B5, typename __TBB_B6, typename __TBB_B7, typename __TBB_B8, typename __TBB_B9>
|
||||
__TBB_requires(join_node_functions<OutputTuple, K, __TBB_B0, __TBB_B1, __TBB_B2, __TBB_B3, __TBB_B4, __TBB_B5, __TBB_B6, __TBB_B7, __TBB_B8, __TBB_B9>)
|
||||
__TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 b5, __TBB_B6 b6,
|
||||
__TBB_B7 b7, __TBB_B8 b8, __TBB_B9 b9) : unfolded_type(g, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
|
||||
template <
|
||||
@@ -2324,20 +2252,16 @@ public:
|
||||
// indexer node
|
||||
#include "detail/_flow_graph_indexer_impl.h"
|
||||
|
||||
// TODO: Implement interface with variadic template or tuple
|
||||
template<typename T0, typename T1=null_type, typename T2=null_type, typename T3=null_type,
|
||||
typename T4=null_type, typename T5=null_type, typename T6=null_type,
|
||||
typename T7=null_type, typename T8=null_type, typename T9=null_type> class indexer_node;
|
||||
|
||||
//indexer node specializations
|
||||
template<typename T0>
|
||||
class indexer_node<T0> : public unfolded_indexer_node<std::tuple<T0> > {
|
||||
template <typename T0, typename... TN>
|
||||
__TBB_requires(std::copy_constructible<T0> &&
|
||||
(... && std::copy_constructible<TN>))
|
||||
class indexer_node : public unfolded_indexer_node<T0, TN...> {
|
||||
private:
|
||||
static const int N = 1;
|
||||
static constexpr std::size_t N = sizeof...(TN) + 1;
|
||||
public:
|
||||
typedef std::tuple<T0> InputTuple;
|
||||
typedef tagged_msg<size_t, T0> output_type;
|
||||
typedef unfolded_indexer_node<InputTuple> unfolded_type;
|
||||
using output_type = tagged_msg<std::size_t, T0, TN...>;
|
||||
using unfolded_type = unfolded_indexer_node<T0, TN...>;
|
||||
|
||||
__TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
@@ -2355,273 +2279,7 @@ public:
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T0, typename T1>
|
||||
class indexer_node<T0, T1> : public unfolded_indexer_node<std::tuple<T0, T1> > {
|
||||
private:
|
||||
static const int N = 2;
|
||||
public:
|
||||
typedef std::tuple<T0, T1> InputTuple;
|
||||
typedef tagged_msg<size_t, T0, T1> output_type;
|
||||
typedef unfolded_indexer_node<InputTuple> unfolded_type;
|
||||
__TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
|
||||
template <typename... Args>
|
||||
indexer_node(const node_set<Args...>& nodes) : indexer_node(nodes.graph_reference()) {
|
||||
make_edges_in_order(nodes, *this);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy constructor
|
||||
__TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename T0, typename T1, typename T2>
|
||||
class indexer_node<T0, T1, T2> : public unfolded_indexer_node<std::tuple<T0, T1, T2> > {
|
||||
private:
|
||||
static const int N = 3;
|
||||
public:
|
||||
typedef std::tuple<T0, T1, T2> InputTuple;
|
||||
typedef tagged_msg<size_t, T0, T1, T2> output_type;
|
||||
typedef unfolded_indexer_node<InputTuple> unfolded_type;
|
||||
__TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
|
||||
template <typename... Args>
|
||||
indexer_node(const node_set<Args...>& nodes) : indexer_node(nodes.graph_reference()) {
|
||||
make_edges_in_order(nodes, *this);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy constructor
|
||||
__TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename T0, typename T1, typename T2, typename T3>
|
||||
class indexer_node<T0, T1, T2, T3> : public unfolded_indexer_node<std::tuple<T0, T1, T2, T3> > {
|
||||
private:
|
||||
static const int N = 4;
|
||||
public:
|
||||
typedef std::tuple<T0, T1, T2, T3> InputTuple;
|
||||
typedef tagged_msg<size_t, T0, T1, T2, T3> output_type;
|
||||
typedef unfolded_indexer_node<InputTuple> unfolded_type;
|
||||
__TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
|
||||
template <typename... Args>
|
||||
indexer_node(const node_set<Args...>& nodes) : indexer_node(nodes.graph_reference()) {
|
||||
make_edges_in_order(nodes, *this);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy constructor
|
||||
__TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename T0, typename T1, typename T2, typename T3, typename T4>
|
||||
class indexer_node<T0, T1, T2, T3, T4> : public unfolded_indexer_node<std::tuple<T0, T1, T2, T3, T4> > {
|
||||
private:
|
||||
static const int N = 5;
|
||||
public:
|
||||
typedef std::tuple<T0, T1, T2, T3, T4> InputTuple;
|
||||
typedef tagged_msg<size_t, T0, T1, T2, T3, T4> output_type;
|
||||
typedef unfolded_indexer_node<InputTuple> unfolded_type;
|
||||
__TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
|
||||
template <typename... Args>
|
||||
indexer_node(const node_set<Args...>& nodes) : indexer_node(nodes.graph_reference()) {
|
||||
make_edges_in_order(nodes, *this);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy constructor
|
||||
__TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#if __TBB_VARIADIC_MAX >= 6
|
||||
template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
class indexer_node<T0, T1, T2, T3, T4, T5> : public unfolded_indexer_node<std::tuple<T0, T1, T2, T3, T4, T5> > {
|
||||
private:
|
||||
static const int N = 6;
|
||||
public:
|
||||
typedef std::tuple<T0, T1, T2, T3, T4, T5> InputTuple;
|
||||
typedef tagged_msg<size_t, T0, T1, T2, T3, T4, T5> output_type;
|
||||
typedef unfolded_indexer_node<InputTuple> unfolded_type;
|
||||
__TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
|
||||
template <typename... Args>
|
||||
indexer_node(const node_set<Args...>& nodes) : indexer_node(nodes.graph_reference()) {
|
||||
make_edges_in_order(nodes, *this);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy constructor
|
||||
__TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
};
|
||||
#endif //variadic max 6
|
||||
|
||||
#if __TBB_VARIADIC_MAX >= 7
|
||||
template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6>
|
||||
class indexer_node<T0, T1, T2, T3, T4, T5, T6> : public unfolded_indexer_node<std::tuple<T0, T1, T2, T3, T4, T5, T6> > {
|
||||
private:
|
||||
static const int N = 7;
|
||||
public:
|
||||
typedef std::tuple<T0, T1, T2, T3, T4, T5, T6> InputTuple;
|
||||
typedef tagged_msg<size_t, T0, T1, T2, T3, T4, T5, T6> output_type;
|
||||
typedef unfolded_indexer_node<InputTuple> unfolded_type;
|
||||
__TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
|
||||
template <typename... Args>
|
||||
indexer_node(const node_set<Args...>& nodes) : indexer_node(nodes.graph_reference()) {
|
||||
make_edges_in_order(nodes, *this);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy constructor
|
||||
__TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
};
|
||||
#endif //variadic max 7
|
||||
|
||||
#if __TBB_VARIADIC_MAX >= 8
|
||||
template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7>
|
||||
class indexer_node<T0, T1, T2, T3, T4, T5, T6, T7> : public unfolded_indexer_node<std::tuple<T0, T1, T2, T3, T4, T5, T6, T7> > {
|
||||
private:
|
||||
static const int N = 8;
|
||||
public:
|
||||
typedef std::tuple<T0, T1, T2, T3, T4, T5, T6, T7> InputTuple;
|
||||
typedef tagged_msg<size_t, T0, T1, T2, T3, T4, T5, T6, T7> output_type;
|
||||
typedef unfolded_indexer_node<InputTuple> unfolded_type;
|
||||
indexer_node(graph& g) : unfolded_type(g) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
|
||||
template <typename... Args>
|
||||
indexer_node(const node_set<Args...>& nodes) : indexer_node(nodes.graph_reference()) {
|
||||
make_edges_in_order(nodes, *this);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy constructor
|
||||
indexer_node( const indexer_node& other ) : unfolded_type(other) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
};
|
||||
#endif //variadic max 8
|
||||
|
||||
#if __TBB_VARIADIC_MAX >= 9
|
||||
template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7, typename T8>
|
||||
class indexer_node<T0, T1, T2, T3, T4, T5, T6, T7, T8> : public unfolded_indexer_node<std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8> > {
|
||||
private:
|
||||
static const int N = 9;
|
||||
public:
|
||||
typedef std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8> InputTuple;
|
||||
typedef tagged_msg<size_t, T0, T1, T2, T3, T4, T5, T6, T7, T8> output_type;
|
||||
typedef unfolded_indexer_node<InputTuple> unfolded_type;
|
||||
__TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
|
||||
template <typename... Args>
|
||||
indexer_node(const node_set<Args...>& nodes) : indexer_node(nodes.graph_reference()) {
|
||||
make_edges_in_order(nodes, *this);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy constructor
|
||||
__TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
};
|
||||
#endif //variadic max 9
|
||||
|
||||
#if __TBB_VARIADIC_MAX >= 10
|
||||
template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7, typename T8, typename T9>
|
||||
class indexer_node/*default*/ : public unfolded_indexer_node<std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> > {
|
||||
private:
|
||||
static const int N = 10;
|
||||
public:
|
||||
typedef std::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> InputTuple;
|
||||
typedef tagged_msg<size_t, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> output_type;
|
||||
typedef unfolded_indexer_node<InputTuple> unfolded_type;
|
||||
__TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
|
||||
template <typename... Args>
|
||||
indexer_node(const node_set<Args...>& nodes) : indexer_node(nodes.graph_reference()) {
|
||||
make_edges_in_order(nodes, *this);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy constructor
|
||||
__TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
|
||||
fgt_multiinput_node<N>( CODEPTR(), FLOW_INDEXER_NODE, &this->my_graph,
|
||||
this->input_ports(), static_cast< sender< output_type > *>(this) );
|
||||
}
|
||||
|
||||
};
|
||||
#endif //variadic max 10
|
||||
}; // class indexer_node
|
||||
|
||||
template< typename T >
|
||||
inline void internal_make_edge( sender<T> &p, receiver<T> &s ) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
Copyright (c) 2005-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -306,7 +306,9 @@ struct input_block_handling_task : public task {
|
||||
~input_block_handling_task() {
|
||||
for(std::size_t counter = 0; counter < max_block_size; ++counter) {
|
||||
(task_pool.begin() + counter)->~iteration_task();
|
||||
(block_iteration_space.begin() + counter)->~Item();
|
||||
if (counter < my_size) {
|
||||
(block_iteration_space.begin() + counter)->~Item();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -311,27 +311,6 @@ struct adaptive_mode : partition_type_base<Partition> {
|
||||
}
|
||||
};
|
||||
|
||||
//! Helper type for checking availability of proportional_split constructor
|
||||
template <typename T> using supports_proportional_splitting = typename std::is_constructible<T, T&, proportional_split&>;
|
||||
|
||||
//! A helper class to create a proportional_split object for a given type of Range.
|
||||
/** If the Range has proportional_split constructor,
|
||||
then created object splits a provided value in an implemenation-defined proportion;
|
||||
otherwise it represents equal-size split. */
|
||||
// TODO: check if this helper can be a nested class of proportional_mode.
|
||||
template <typename Range, typename = void>
|
||||
struct proportion_helper {
|
||||
static proportional_split get_split(std::size_t) { return proportional_split(1,1); }
|
||||
};
|
||||
|
||||
template <typename Range>
|
||||
struct proportion_helper<Range, typename std::enable_if<supports_proportional_splitting<Range>::value>::type> {
|
||||
static proportional_split get_split(std::size_t n) {
|
||||
std::size_t right = n / 2;
|
||||
std::size_t left = n - right;
|
||||
return proportional_split(left, right);
|
||||
}
|
||||
};
|
||||
|
||||
//! Provides proportional splitting strategy for partition objects
|
||||
template <typename Partition>
|
||||
@@ -357,8 +336,16 @@ struct proportional_mode : adaptive_mode<Partition> {
|
||||
}
|
||||
template <typename Range>
|
||||
proportional_split get_split() {
|
||||
// Create a proportion for the number of threads expected to handle "this" subrange
|
||||
return proportion_helper<Range>::get_split( self().my_divisor / my_partition::factor );
|
||||
// Create the proportion from partitioner internal resources (threads) that would be used:
|
||||
// - into proportional_mode constructor to split the partitioner
|
||||
// - if Range supports the proportional_split constructor it would use proposed proportion,
|
||||
// otherwise, the tbb::proportional_split object will be implicitly (for Range implementor)
|
||||
// casted to tbb::split
|
||||
|
||||
std::size_t n = self().my_divisor / my_partition::factor;
|
||||
std::size_t right = n / 2;
|
||||
std::size_t left = n - right;
|
||||
return proportional_split(left, right);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -17,8 +17,14 @@
|
||||
#ifndef __TBB_version_H
|
||||
#define __TBB_version_H
|
||||
|
||||
#include "detail/_config.h"
|
||||
#include "detail/_namespace_injection.h"
|
||||
// Exclude all includes during .rc files compilation
|
||||
#ifndef RC_INVOKED
|
||||
#include "detail/_config.h"
|
||||
#include "detail/_namespace_injection.h"
|
||||
#else
|
||||
#define __TBB_STRING_AUX(x) #x
|
||||
#define __TBB_STRING(x) __TBB_STRING_AUX(x)
|
||||
#endif
|
||||
|
||||
// Product version
|
||||
#define TBB_VERSION_MAJOR 2021
|
||||
|
||||
+36
-29
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016-2021 Intel Corporation
|
||||
# Copyright (c) 2016-2022 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -82,6 +82,29 @@ def test(arg=None):
|
||||
say("[%d] Work done (%fms)." % (get_tid(), mseconds*10))
|
||||
return res
|
||||
|
||||
# special flag to to be set by thread calling async work
|
||||
spin_flag = None
|
||||
def timeout_work(param):
|
||||
say("[%d] Spin wait work start..." % get_tid())
|
||||
while spin_flag:
|
||||
time.sleep(0.0001) # yield equivalent
|
||||
say("[%d] Work done." % get_tid())
|
||||
return str(param) if param != None else None
|
||||
|
||||
def prepare_timeout_exception():
|
||||
nonlocal spin_flag
|
||||
spin_flag = True # lock threads in timeout_work
|
||||
|
||||
def check_timeout_exception(pool_object, func):
|
||||
nonlocal spin_flag
|
||||
try:
|
||||
func(pool_object)
|
||||
except TimeoutError:
|
||||
say("Good. Got expected timeout exception.")
|
||||
else:
|
||||
assert False, "Expected exception !"
|
||||
spin_flag = False # unlock threads in timeout_work
|
||||
|
||||
### Test copy/pasted from multiprocessing
|
||||
pool = Pool(4) # start worker threads
|
||||
|
||||
@@ -105,13 +128,9 @@ def test(arg=None):
|
||||
assert next(it) == 4
|
||||
|
||||
# Test apply_sync exceptions
|
||||
result = pool.apply_async(time.sleep, (3,))
|
||||
try:
|
||||
say(result.get(timeout=1)) # raises `TimeoutError`
|
||||
except TimeoutError:
|
||||
say("Good. Got expected timeout exception.")
|
||||
else:
|
||||
assert False, "Expected exception !"
|
||||
prepare_timeout_exception()
|
||||
result = pool.apply_async(timeout_work, (None,))
|
||||
check_timeout_exception(result, lambda result : say(result.get(timeout=1)))
|
||||
assert result.get() is None # sleep() returns None
|
||||
|
||||
def cb(s):
|
||||
@@ -126,23 +145,15 @@ def test(arg=None):
|
||||
str, range(10, 3, -1)))
|
||||
|
||||
# Test map_async()
|
||||
result = pool.map_async(work, range(10), callback=cb)
|
||||
try:
|
||||
result.get(timeout=0.01) # raises `TimeoutError`
|
||||
except TimeoutError:
|
||||
say("Good. Got expected timeout exception.")
|
||||
else:
|
||||
assert False, "Expected exception !"
|
||||
prepare_timeout_exception()
|
||||
result = pool.map_async(timeout_work, range(10), callback=cb)
|
||||
check_timeout_exception(result, lambda result : result.get(timeout=0.01))
|
||||
say(result.get())
|
||||
|
||||
# Test imap_async()
|
||||
result = pool.imap_async(work, range(3, 10), callback=cb)
|
||||
try:
|
||||
result.get(timeout=0.01) # raises `TimeoutError`
|
||||
except TimeoutError:
|
||||
say("Good. Got expected timeout exception.")
|
||||
else:
|
||||
assert False, "Expected exception !"
|
||||
prepare_timeout_exception()
|
||||
result = pool.imap_async(timeout_work, range(3, 10), callback=cb)
|
||||
check_timeout_exception(result, lambda result : result.get(timeout=0.01))
|
||||
for i in result.get():
|
||||
say("Item:", i)
|
||||
say("### Loop again:")
|
||||
@@ -150,13 +161,9 @@ def test(arg=None):
|
||||
say("Item2:", i)
|
||||
|
||||
# Test imap_unordered_async()
|
||||
result = pool.imap_unordered_async(work, range(10, 3, -1), callback=cb)
|
||||
try:
|
||||
say(result.get(timeout=0.01)) # raises `TimeoutError`
|
||||
except TimeoutError:
|
||||
say("Good. Got expected timeout exception.")
|
||||
else:
|
||||
assert False, "Expected exception !"
|
||||
prepare_timeout_exception()
|
||||
result = pool.imap_unordered_async(timeout_work, range(10, 3, -1), callback=cb)
|
||||
check_timeout_exception(result, lambda result : result.get(timeout=0.01))
|
||||
for i in result.get():
|
||||
say("Item1:", i)
|
||||
for i in result.get():
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
# Copyright (c) 2020-2022 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -45,6 +45,7 @@ add_library(tbb
|
||||
add_library(TBB::tbb ALIAS tbb)
|
||||
|
||||
if (WIN32)
|
||||
target_sources(tbb PRIVATE tbb.rc)
|
||||
set_target_properties(tbb PROPERTIES OUTPUT_NAME "tbb${TBB_BINARY_VERSION}")
|
||||
endif()
|
||||
|
||||
@@ -92,8 +93,8 @@ tbb_handle_ipo(tbb)
|
||||
|
||||
if (TBB_DEF_FILE_PREFIX) # If there's no prefix, assume we're using export directives
|
||||
set_target_properties(tbb PROPERTIES
|
||||
LINK_FLAGS ${TBB_LINK_DEF_FILE_FLAG}${CMAKE_CURRENT_SOURCE_DIR}/def/${TBB_DEF_FILE_PREFIX}-tbb.def
|
||||
LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/def/${TBB_DEF_FILE_PREFIX}-tbb.def
|
||||
LINK_FLAGS "${TBB_LINK_DEF_FILE_FLAG}\"${CMAKE_CURRENT_SOURCE_DIR}/def/${TBB_DEF_FILE_PREFIX}-tbb.def\""
|
||||
LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/def/${TBB_DEF_FILE_PREFIX}-tbb.def"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
// Copyright (c) 2005-2022 Intel Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include <winresrc.h>
|
||||
#include "../../include/oneapi/tbb/version.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Neutral resources
|
||||
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// manifest integration
|
||||
#ifdef TBB_MANIFEST
|
||||
#include "winuser.h"
|
||||
2 RT_MANIFEST tbbmanifest.exe.manifest
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
#define TBB_VERNUMBERS TBB_VERSION_MAJOR,TBB_VERSION_MINOR
|
||||
#define TBB_VERSION TBB_VERSION_STRING
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION TBB_VERNUMBERS
|
||||
PRODUCTVERSION TBB_VERNUMBERS
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "000004b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Intel Corporation\0"
|
||||
VALUE "FileDescription", "oneAPI Threading Building Blocks (oneTBB) library\0"
|
||||
VALUE "FileVersion", TBB_VERSION "\0"
|
||||
VALUE "LegalCopyright", "Copyright 2005-2022 Intel Corporation. All Rights Reserved.\0"
|
||||
VALUE "LegalTrademarks", "\0"
|
||||
#ifndef TBB_USE_DEBUG
|
||||
VALUE "OriginalFilename", "tbb12.dll\0"
|
||||
#else
|
||||
VALUE "OriginalFilename", "tbb12_debug.dll\0"
|
||||
#endif
|
||||
VALUE "ProductName", "oneAPI Threading Building Blocks (oneTBB)\0"
|
||||
VALUE "ProductVersion", TBB_VERSION "\0"
|
||||
VALUE "PrivateBuild", "\0"
|
||||
VALUE "SpecialBuild", "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0, 1200
|
||||
END
|
||||
END
|
||||
|
||||
//#endif // Neutral resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
@@ -167,6 +167,18 @@
|
||||
# define ITT_ARCH_LOONGARCH64 7
|
||||
#endif /* ITT_ARCH_LOONGARCH64 */
|
||||
|
||||
#ifndef ITT_ARCH_S390X
|
||||
# define ITT_ARCH_S390X 8
|
||||
#endif /* ITT_ARCH_S390X */
|
||||
|
||||
#ifndef ITT_ARCH_HPPA
|
||||
# define ITT_ARCH_HPPA 9
|
||||
#endif /* ITT_ARCH_HPPA */
|
||||
|
||||
#ifndef ITT_ARCH_RISCV64
|
||||
# define ITT_ARCH_RISCV64 10
|
||||
#endif /* ITT_ARCH_RISCV64 */
|
||||
|
||||
#ifndef ITT_ARCH
|
||||
# if defined _M_IX86 || defined __i386__
|
||||
# define ITT_ARCH ITT_ARCH_IA32
|
||||
@@ -182,6 +194,12 @@
|
||||
# define ITT_ARCH ITT_ARCH_PPC64
|
||||
# elif defined __loongarch__
|
||||
# define ITT_ARCH ITT_ARCH_LOONGARCH64
|
||||
# elif defined __s390__ || defined __s390x__
|
||||
# define ITT_ARCH ITT_ARCH_S390X
|
||||
# elif defined __hppa__
|
||||
# define ITT_ARCH ITT_ARCH_HPPA
|
||||
# elif defined __riscv && __riscv_xlen == 64
|
||||
# define ITT_ARCH ITT_ARCH_RISCV64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -24,6 +24,13 @@ function(tbbbind_build TBBBIND_NAME REQUIRED_HWLOC_TARGET)
|
||||
return()
|
||||
endif()
|
||||
add_library(${TBBBIND_NAME} tbb_bind.cpp)
|
||||
|
||||
if (WIN32)
|
||||
if(${TBBBIND_NAME} STREQUAL tbbbind) #adding resource info for default tbbbind
|
||||
target_sources(${TBBBIND_NAME} PRIVATE tbb_bind.rc)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_library(TBB::${TBBBIND_NAME} ALIAS ${TBBBIND_NAME})
|
||||
|
||||
target_compile_definitions(${TBBBIND_NAME}
|
||||
@@ -59,8 +66,8 @@ function(tbbbind_build TBBBIND_NAME REQUIRED_HWLOC_TARGET)
|
||||
|
||||
if (TBB_DEF_FILE_PREFIX) # If there's no prefix, assume we're using export directives
|
||||
set_target_properties(${TBBBIND_NAME} PROPERTIES
|
||||
LINK_FLAGS ${TBB_LINK_DEF_FILE_FLAG}${CMAKE_CURRENT_SOURCE_DIR}/def/${TBB_DEF_FILE_PREFIX}-tbbbind.def
|
||||
LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/def/${TBB_DEF_FILE_PREFIX}-tbbbind.def
|
||||
LINK_FLAGS "${TBB_LINK_DEF_FILE_FLAG}\"${CMAKE_CURRENT_SOURCE_DIR}/def/${TBB_DEF_FILE_PREFIX}-tbbbind.def\""
|
||||
LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/def/${TBB_DEF_FILE_PREFIX}-tbbbind.def"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
// Copyright (c) 2005-2022 Intel Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include <winresrc.h>
|
||||
#include "../../include/oneapi/tbb/version.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Neutral resources
|
||||
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// manifest integration
|
||||
#ifdef TBB_MANIFEST
|
||||
#include "winuser.h"
|
||||
2 RT_MANIFEST tbbmanifest.exe.manifest
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
#define TBB_VERNUMBERS TBB_VERSION_MAJOR,TBB_VERSION_MINOR
|
||||
#define TBB_VERSION TBB_VERSION_STRING
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION TBB_VERNUMBERS
|
||||
PRODUCTVERSION TBB_VERNUMBERS
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "000004b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Intel Corporation\0"
|
||||
VALUE "FileDescription", "oneAPI Threading Building Blocks (oneTBB) library\0"
|
||||
VALUE "FileVersion", TBB_VERSION "\0"
|
||||
VALUE "LegalCopyright", "Copyright 2005-2022 Intel Corporation. All Rights Reserved.\0"
|
||||
VALUE "LegalTrademarks", "\0"
|
||||
#ifndef TBB_USE_DEBUG
|
||||
VALUE "OriginalFilename", "tbbbind.dll\0"
|
||||
#else
|
||||
VALUE "OriginalFilename", "tbbbind_debug.dll\0"
|
||||
#endif
|
||||
VALUE "ProductName", "oneAPI Threading Building Blocks (oneTBB)\0"
|
||||
VALUE "ProductVersion", TBB_VERSION "\0"
|
||||
VALUE "PrivateBuild", "\0"
|
||||
VALUE "SpecialBuild", "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0, 1200
|
||||
END
|
||||
END
|
||||
|
||||
//#endif // Neutral resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
# Copyright (c) 2020-2022 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,10 @@ add_library(tbbmalloc
|
||||
large_objects.cpp
|
||||
tbbmalloc.cpp
|
||||
../tbb/itt_notify.cpp)
|
||||
|
||||
if (WIN32)
|
||||
target_sources(tbbmalloc PRIVATE tbbmalloc.rc)
|
||||
endif()
|
||||
|
||||
add_library(TBB::tbbmalloc ALIAS tbbmalloc)
|
||||
|
||||
@@ -75,8 +79,8 @@ tbb_handle_ipo(tbbmalloc)
|
||||
|
||||
if (TBB_DEF_FILE_PREFIX) # If there's no prefix, assume we're using export directives
|
||||
set_target_properties(tbbmalloc PROPERTIES
|
||||
LINK_FLAGS ${TBB_LINK_DEF_FILE_FLAG}${CMAKE_CURRENT_SOURCE_DIR}/def/${TBB_DEF_FILE_PREFIX}-tbbmalloc.def
|
||||
LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/def/${TBB_DEF_FILE_PREFIX}-tbbmalloc.def
|
||||
LINK_FLAGS "${TBB_LINK_DEF_FILE_FLAG}\"${CMAKE_CURRENT_SOURCE_DIR}/def/${TBB_DEF_FILE_PREFIX}-tbbmalloc.def\""
|
||||
LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/def/${TBB_DEF_FILE_PREFIX}-tbbmalloc.def"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
// Copyright (c) 2005-2022 Intel Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include <winresrc.h>
|
||||
#include "../../include/oneapi/tbb/version.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Neutral resources
|
||||
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// manifest integration
|
||||
#ifdef TBB_MANIFEST
|
||||
#include "winuser.h"
|
||||
2 RT_MANIFEST tbbmanifest.exe.manifest
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
#define TBB_VERNUMBERS TBB_VERSION_MAJOR,TBB_VERSION_MINOR
|
||||
#define TBB_VERSION TBB_VERSION_STRING
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION TBB_VERNUMBERS
|
||||
PRODUCTVERSION TBB_VERNUMBERS
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "000004b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Intel Corporation\0"
|
||||
VALUE "FileDescription", "oneAPI Threading Building Blocks (oneTBB) library\0"
|
||||
VALUE "FileVersion", TBB_VERSION "\0"
|
||||
VALUE "LegalCopyright", "Copyright 2005-2022 Intel Corporation. All Rights Reserved.\0"
|
||||
VALUE "LegalTrademarks", "\0"
|
||||
#ifndef TBB_USE_DEBUG
|
||||
VALUE "OriginalFilename", "tbbmalloc.dll\0"
|
||||
#else
|
||||
VALUE "OriginalFilename", "tbbmalloc_debug.dll\0"
|
||||
#endif
|
||||
VALUE "ProductName", "oneAPI Threading Building Blocks (oneTBB)\0"
|
||||
VALUE "ProductVersion", TBB_VERSION "\0"
|
||||
VALUE "PrivateBuild", "\0"
|
||||
VALUE "SpecialBuild", "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0, 1200
|
||||
END
|
||||
END
|
||||
|
||||
//#endif // Neutral resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2020-2021 Intel Corporation
|
||||
# Copyright (c) 2020-2022 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,10 @@ add_library(tbbmalloc_proxy
|
||||
function_replacement.cpp
|
||||
proxy.cpp)
|
||||
|
||||
if (WIN32)
|
||||
target_sources(tbbmalloc_proxy PRIVATE tbbmalloc_proxy.rc)
|
||||
endif()
|
||||
|
||||
add_library(TBB::tbbmalloc_proxy ALIAS tbbmalloc_proxy)
|
||||
|
||||
target_compile_definitions(tbbmalloc_proxy
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
// Copyright (c) 2005-2022 Intel Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include <winresrc.h>
|
||||
#include "../../include/oneapi/tbb/version.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Neutral resources
|
||||
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// manifest integration
|
||||
#ifdef TBB_MANIFEST
|
||||
#include "winuser.h"
|
||||
2 RT_MANIFEST tbbmanifest.exe.manifest
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
#define TBB_VERNUMBERS TBB_VERSION_MAJOR,TBB_VERSION_MINOR
|
||||
#define TBB_VERSION TBB_VERSION_STRING
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION TBB_VERNUMBERS
|
||||
PRODUCTVERSION TBB_VERNUMBERS
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "000004b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Intel Corporation\0"
|
||||
VALUE "FileDescription", "oneAPI Threading Building Blocks (oneTBB) library\0"
|
||||
VALUE "FileVersion", TBB_VERSION "\0"
|
||||
VALUE "LegalCopyright", "Copyright 2005-2022 Intel Corporation. All Rights Reserved.\0"
|
||||
VALUE "LegalTrademarks", "\0"
|
||||
#ifndef TBB_USE_DEBUG
|
||||
VALUE "OriginalFilename", "tbbmalloc_proxy.dll\0"
|
||||
#else
|
||||
VALUE "OriginalFilename", "tbbmalloc_proxy_debug.dll\0"
|
||||
#endif
|
||||
VALUE "ProductName", "oneAPI Threading Building Blocks (oneTBB)\0"
|
||||
VALUE "ProductVersion", TBB_VERSION "\0"
|
||||
VALUE "PrivateBuild", "\0"
|
||||
VALUE "SpecialBuild", "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0, 1200
|
||||
END
|
||||
END
|
||||
|
||||
//#endif // Neutral resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
+15
-3
@@ -361,17 +361,29 @@ unset(_sde_find_name)
|
||||
# Common target for the tbbbind related tests
|
||||
add_custom_target(test_suite_arena_constraints)
|
||||
|
||||
# Check support for --no-as-needed linker option
|
||||
if (MINGW OR NOT WIN32)
|
||||
include(CheckCXXSourceCompiles)
|
||||
set(CMAKE_REQUIRED_LIBRARIES "-Wl,--no-as-needed")
|
||||
check_cxx_source_compiles("int main(int, char*[]) { return 0; }" LINKER_HAS_NO_AS_NEEDED)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
endif()
|
||||
|
||||
if (TARGET TBB::tbb)
|
||||
# Define the tests
|
||||
tbb_add_test(SUBDIR tbb NAME test_tick_count DEPENDENCIES TBB::tbb)
|
||||
tbb_add_test(SUBDIR tbb NAME test_allocators DEPENDENCIES TBB::tbb)
|
||||
tbb_add_test(SUBDIR tbb NAME test_arena_priorities DEPENDENCIES TBB::tbb)
|
||||
tbb_add_test(SUBDIR tbb NAME test_dynamic_link DEPENDENCIES TBB::tbb)
|
||||
if (WIN32)
|
||||
tbb_add_test(SUBDIR tbb NAME test_numa_dist DEPENDENCIES TBB::tbb)
|
||||
if (LINKER_HAS_NO_AS_NEEDED)
|
||||
# The linker may not detect a dependency on pthread in static variable constructors.
|
||||
target_link_libraries(test_dynamic_link PRIVATE "-Wl,--no-as-needed")
|
||||
endif()
|
||||
if (APPLE OR ANDROID_PLATFORM)
|
||||
target_link_libraries(test_dynamic_link PRIVATE -rdynamic) # for the test_dynamic_link
|
||||
target_link_libraries(test_dynamic_link PRIVATE -rdynamic)
|
||||
endif()
|
||||
if (WIN32)
|
||||
tbb_add_test(SUBDIR tbb NAME test_numa_dist DEPENDENCIES TBB::tbb)
|
||||
endif()
|
||||
tbb_add_test(SUBDIR tbb NAME test_collaborative_call_once DEPENDENCIES TBB::tbb)
|
||||
tbb_add_test(SUBDIR tbb NAME test_concurrent_lru_cache DEPENDENCIES TBB::tbb)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2005-2021 Intel Corporation
|
||||
Copyright (c) 2005-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -36,12 +36,12 @@
|
||||
constexpr std::size_t depths_nubmer = 20;
|
||||
static std::atomic<int> g_values_counter;
|
||||
|
||||
class value_t {
|
||||
class value_t : public utils::NoAfterlife {
|
||||
size_t x;
|
||||
value_t& operator=(const value_t&);
|
||||
public:
|
||||
value_t(size_t xx) : x(xx) { ++g_values_counter; }
|
||||
value_t(const value_t& v) : x(v.x) { ++g_values_counter; }
|
||||
value_t(const value_t& v) : utils::NoAfterlife(v), x(v.x) { ++g_values_counter; }
|
||||
value_t(value_t&& v) : x(v.x) { ++g_values_counter; }
|
||||
~value_t() { --g_values_counter; }
|
||||
size_t value() const volatile { return x; }
|
||||
|
||||
@@ -161,3 +161,83 @@ TEST_CASE("indexer_node copy constructor"){
|
||||
TEST_CASE("indexer_node output_type") {
|
||||
CHECK_MESSAGE((conformance::check_output_type<my_output_type, oneapi::tbb::flow::tagged_msg<size_t, int, float, input_msg>>()), "indexer_node output_type should returns a tagged_msg");
|
||||
}
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
template <std::size_t N, typename... Args>
|
||||
struct indexer_node_type_generator_impl {
|
||||
using type = typename indexer_node_type_generator_impl<N - 1, Args..., int>::type;
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
struct indexer_node_type_generator_impl<0, Args...> {
|
||||
using type = oneapi::tbb::flow::indexer_node<Args...>;
|
||||
};
|
||||
|
||||
// Generates oneapi::tbb::flow::indexer_node<int, int, ..., int> with N integer template arguments
|
||||
template <std::size_t N>
|
||||
using indexer_node_type_generator_t = typename indexer_node_type_generator_impl<N>::type;
|
||||
|
||||
template <std::size_t N>
|
||||
struct edge_maker {
|
||||
template <typename SendersVector, typename IndexerNodeType>
|
||||
static void make(SendersVector& senders, IndexerNodeType& indexer) {
|
||||
oneapi::tbb::flow::make_edge(senders[N - 1], oneapi::tbb::flow::input_port<N - 1>(indexer));
|
||||
edge_maker<N - 1>::make(senders, indexer);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct edge_maker<1> {
|
||||
template <typename SendersVector, typename IndexerNodeType>
|
||||
static void make(SendersVector& senders, IndexerNodeType& indexer) {
|
||||
oneapi::tbb::flow::make_edge(senders[0], oneapi::tbb::flow::input_port<0>(indexer));
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t NInputs>
|
||||
void test_indexer_node_with_n_inputs() {
|
||||
using namespace oneapi::tbb::flow;
|
||||
graph g;
|
||||
int message = 42;
|
||||
|
||||
using submitter_type = function_node<int, int>;
|
||||
|
||||
std::vector<submitter_type> submitters;
|
||||
submitters.reserve(NInputs);
|
||||
for (std::size_t i = 0; i < NInputs; ++i) {
|
||||
submitters.emplace_back(g, unlimited, [](int obj) { return obj; });
|
||||
}
|
||||
|
||||
using indexer_type = indexer_node_type_generator_t<NInputs>;
|
||||
|
||||
indexer_type indexer(g);
|
||||
|
||||
edge_maker<NInputs>::make(submitters, indexer);
|
||||
|
||||
using output_type = typename indexer_type::output_type;
|
||||
|
||||
std::unordered_set<std::size_t> indices;
|
||||
indices.reserve(NInputs);
|
||||
|
||||
function_node<output_type> receiver(g, serial, [&](const output_type& indexer_output) {
|
||||
indices.emplace(indexer_output.tag());
|
||||
CHECK_MESSAGE(cast_to<int>(indexer_output) == message, "invalid message returned from indexer_node");
|
||||
});
|
||||
|
||||
make_edge(indexer, receiver);
|
||||
|
||||
for (auto& submitter : submitters) {
|
||||
submitter.try_put(message);
|
||||
}
|
||||
g.wait_for_all();
|
||||
|
||||
CHECK_MESSAGE(indices.size() == NInputs, "Message from some port lost");
|
||||
for (std::size_t i = 0; i < NInputs; ++i) {
|
||||
CHECK(indices.find(i) != indices.end());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("indexer_node with large number of inputs") {
|
||||
test_indexer_node_with_n_inputs<50>();
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2021 Intel Corporation
|
||||
Copyright (c) 2021-2022 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "tbb/parallel_for.h"
|
||||
#include "tbb/task_arena.h"
|
||||
#include "tbb/global_control.h"
|
||||
#include "oneapi/tbb/mutex.h"
|
||||
|
||||
#include "common/utils.h"
|
||||
#include "common/utils_concurrency_limit.h"
|
||||
@@ -28,6 +29,7 @@
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <algorithm> // std::min_element
|
||||
|
||||
//! \file test_partitioner.cpp
|
||||
//! \brief Test for [internal] functionality
|
||||
@@ -138,3 +140,53 @@ TEST_CASE("Threads respect task affinity") {
|
||||
task_affinity_retention::relaxed_test();
|
||||
task_affinity_retention::strict_test();
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
void test_custom_range(int diff_mult) {
|
||||
int num_trials = 100;
|
||||
|
||||
std::vector<std::vector<std::size_t>> results(num_trials);
|
||||
oneapi::tbb::mutex results_mutex;
|
||||
|
||||
for (int i = 0; i < num_trials; ++i) {
|
||||
oneapi::tbb::parallel_for(Range(0, int(100 * utils::get_platform_max_threads()), 1), [&] (const Range& r) {
|
||||
oneapi::tbb::mutex::scoped_lock lock(results_mutex);
|
||||
results[i].push_back(r.size());
|
||||
}, oneapi::tbb::static_partitioner{});
|
||||
}
|
||||
|
||||
for (auto& res : results) {
|
||||
REQUIRE(res.size() == utils::get_platform_max_threads());
|
||||
|
||||
std::size_t min_size = *std::min_element(res.begin(), res.end());
|
||||
for (auto elem : res) {
|
||||
REQUIRE(min_size * diff_mult + 2 >= elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! \brief \ref regression
|
||||
TEST_CASE("Test partitioned tasks count and size for static_partitioner") {
|
||||
class custom_range : public oneapi::tbb::blocked_range<int> {
|
||||
using base_type = oneapi::tbb::blocked_range<int>;
|
||||
public:
|
||||
custom_range(int l, int r, int g) : base_type(l, r, g) {}
|
||||
custom_range(const custom_range& r) : base_type(r) {}
|
||||
|
||||
custom_range(custom_range& r, tbb::split) : base_type(r, tbb::split()) {}
|
||||
};
|
||||
|
||||
test_custom_range<custom_range>(2);
|
||||
|
||||
class custom_range_with_psplit : public oneapi::tbb::blocked_range<int> {
|
||||
using base_type = oneapi::tbb::blocked_range<int>;
|
||||
public:
|
||||
custom_range_with_psplit(int l, int r, int g) : base_type(l, r, g) {}
|
||||
custom_range_with_psplit(const custom_range_with_psplit& r) : base_type(r) {}
|
||||
|
||||
custom_range_with_psplit(custom_range_with_psplit& r, tbb::split) : base_type(r, tbb::split()) {}
|
||||
custom_range_with_psplit(custom_range_with_psplit& r, tbb::proportional_split& p) : base_type(r, p) {}
|
||||
};
|
||||
|
||||
test_custom_range<custom_range_with_psplit>(1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user