Compare commits

...
Author SHA1 Message Date
kboyarinov 0baaad609a Fix indexer_node implementation, add test 2022-10-26 06:36:29 -05:00
kboyarinov cb8fa21a84 Get rid of C++03 rudiments 2022-10-24 08:52:54 -05:00
Ilya Isaev 912cd2b0b3 Fix build with source dir path containing spaces (#930)
Signed-off-by: Isaev, Ilya <ilya.isaev@intel.com>
2022-10-20 10:30:35 +02:00
Dirk MuellerandMo Zhou e8666c0b9c Add s390x, hppa and riscv64 architecture detection (#917)
* Fix build failure for s390x and hppa architectures.

Signed-off-by: Mo Zhou <cdluminate@gmail.com>

* Add riscv64 architecture detection

Signed-off-by: Dirk Müller <dirk@dmllr.de>

Signed-off-by: Mo Zhou <cdluminate@gmail.com>
Signed-off-by: Dirk Müller <dirk@dmllr.de>
Co-authored-by: Mo Zhou <cdluminate@gmail.com>
2022-10-18 11:34:09 +03:00
Vladislav Shchapov 71b04524d0 Workaround for test_dynamic_link builded with gcc and lto
Signed-off-by: Vladislav Shchapov <vladislav@shchapov.ru>
2022-10-17 19:19:23 +01:00
Ilya Isaev aa247fa816 [tbb::parallel_for_each] Don't call destructor for uninitialized object (#933)
Current implementation of parallel_for_each may call destructors for uninitialized objects when using Input iterator and count of elements in block is less than max_block_size. This is UB and can lead to incorrect memory access in some scenarios.

Signed-off-by: Isaev, Ilya <ilya.isaev@intel.com>
2022-10-17 14:03:06 +02:00
Kavin Teenakul 13544f9432 Update INSTALL.md (#820)
fix typo
2022-10-13 18:12:13 +03:00
AlexandraandPavel Kumbrasev 635761449f Update testing_approach.rst (#937)
* Update testing_approach.rst

* Update doc/main/intro/testing_approach.rst

Co-authored-by: Pavel Kumbrasev <pavel.kumbrasev@intel.com>

Co-authored-by: Pavel Kumbrasev <pavel.kumbrasev@intel.com>
2022-10-11 18:08:27 +02:00
Pavel Kumbrasev 6bfd29bde7 Exclude includes from version.h during .rc files comilation (#928)
Signed-off-by: pavelkumbrasev <pavel.kumbrasev@intel.com>
2022-10-05 12:57:13 +02:00
egfefey e6459e22ae Delete resource.rc (#922) 2022-10-05 11:17:35 +01:00
egfefey 85792ca411 Egfefey patch windows dll (#916)
* Restoring Windows DLL details information

This restores the detailed information in the Windows dll. This has been absent from the revamped oneTBB.

* Update CMakeLists.txt

Enabling build of Windows resource file.

* Update CMakeLists.txt

Updating copyright year

* Add files via upload

Adding Windows resource file for tbbmalloc

* Update CMakeLists.txt

Enabling building of tbbmalloc resource file

* Add files via upload

Adding tbbmalloc_proxy Windows resource file

* Update CMakeLists.txt

Enabling the build of tbbmalloc_proxy resource file

* Add files via upload

Adding tbbbind resource file

* Update CMakeLists.txt

Enabling tbbbind resource file build

* Update resource.rc

Product name update in resource file

* Update CMakeLists.txt

Restricting resource build to default tbbbind

* Add files via upload

Replacing resource.rc with tbb.rc to conform with other dlls (tbbmalloc, tbbbind etc)

* Update CMakeLists.txt

Update from resource.rc to tbb.rc

* Update CMakeLists.txt

Updating copyright year

* Update CMakeLists.txt

Updating the copyright year

* Update tbb.rc

Removing "Windows" from the product name and sourcing the version from version.h

* Update tbb_bind.rc

Removing "Windows" from the product name and sourcing the version info from version.h

* Update tbbmalloc.rc

Removing "Windows" from the product name and sourcing the version info from version.h

* Update tbbmalloc_proxy.rc

Removing "Windows" from the product name and sourcing the version info from version.h
2022-09-30 12:51:10 -05:00
kboyarinov 3fbdbb8b2e Fix the implicit deduction guides on MacOS (#898) 2022-09-28 14:12:46 +03:00
Vladislav Shchapov 3c91aea522 Fix universal binary build on macos. (#919)
Signed-off-by: Vladislav Shchapov <vladislav@shchapov.ru>
2022-09-27 13:15:06 +02:00
Ilya Isaev 2eccd5f998 Fix tbb4py test sporadic fails (#913)
There are sporadic fails with tbb4py test (test.py). The problem is that some test cases rely on the fact, that submitted async work will not finish until calling get with timeout. To do there is a call for time.sleep in functor submitted. Sporadically, expected result is not happening (like OSX example in issue) so to prevent that, the blocking is used.

Signed-off-by: Isaev, Ilya <ilya.isaev@intel.com>
2022-09-26 16:14:17 +02:00
cc3a9aa992 Correct behavior for proportional_mode (#904)
Signed-off-by: pavelkumbrasev <pavel.kumbrasev@intel.com>
Co-authored-by: kboyarinov <konstantin.boyarinov@intel.com>
Co-authored-by: Aleksei Fedotov <aleksei.fedotov@intel.com>
2022-09-26 14:29:27 +01:00
Alexandra 104fb5c9de Testing approach doc (#914)
* Signed-off-by:Alexandra Epanchinzeva alexandra.epanchinzeva@intel.com

* Update testing_approach.rst
2022-09-26 12:35:30 +02:00
Pavel Kumbrasev f10350212b Remove unused function from _concurrent_queue_base.h (#915)
Signed-off-by: pavelkumbrasev <pavel.kumbrasev@intel.com>
2022-09-23 14:18:20 +01:00
28 changed files with 860 additions and 1080 deletions
+1
View File
@@ -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)
+8 -2
View File
@@ -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)
+1
View File
@@ -8,6 +8,7 @@
/main/intro/notation
/main/intro/intro_os
/main/intro/Benefits
/main/intro/testing_approach
.. toctree::
+31
View File
@@ -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.
+20 -1
View File
@@ -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>
+19 -1
View File
@@ -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) {}
+42 -468
View File
@@ -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
View File
@@ -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 ) {
+4 -2
View File
@@ -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();
}
}
}
+10 -23
View File
@@ -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);
}
};
+8 -2
View File
@@ -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
View File
@@ -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():
+4 -3
View File
@@ -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
View File
@@ -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
+18
View File
@@ -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
+9 -2
View File
@@ -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()
+111
View File
@@ -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
+7 -3
View File
@@ -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()
+111
View File
@@ -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
+5 -1
View File
@@ -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
+111
View File
@@ -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
View File
@@ -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)
+3 -3
View File
@@ -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>();
}
+53 -1
View File
@@ -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);
}