Committing TBB 2019 Update 9 source code master
authortbbdev <inteltbbdevelopers@intel.com>
Wed, 9 Oct 2019 13:55:53 +0000 (16:55 +0300)
committertbbdev <inteltbbdevelopers@intel.com>
Wed, 9 Oct 2019 14:58:36 +0000 (17:58 +0300)
305 files changed:
.gitignore
CHANGES
README.md
build/BSD.inc
build/FreeBSD.gcc.inc
build/Makefile.rml
build/Makefile.test
build/common_rules.inc
build/detect.js
build/linux.clang.inc
build/linux.gcc.inc
build/linux.icc.inc
build/macos.clang.inc
build/macos.gcc.inc
build/macos.icc.inc
build/macos.inc
build/version_info_macos.sh
build/vs2013/tbb.vcxproj
build/vs2013/tbbmalloc.vcxproj
build/vs2013/tbbmalloc_proxy.vcxproj
build/windows.icl.inc
build/windows.inc
cmake/README.rst
cmake/TBBInstallConfig.cmake
cmake/TBBMakeConfig.cmake
cmake/templates/TBBConfig.cmake.in
cmake/templates/TBBConfigInternal.cmake.in
examples/GettingStarted/sub_string_finder/Makefile
examples/GettingStarted/sub_string_finder/msvs/sub_string_finder.vcxproj
examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_extended.vcxproj
examples/GettingStarted/sub_string_finder/msvs/sub_string_finder_pretty.vcxproj
examples/Makefile
examples/common/copy_libraries.bat
examples/common/examples-common.inc
examples/common/index.html
examples/common/utility/get_default_num_threads.h [new file with mode: 0644]
examples/common/utility/utility.h
examples/concurrent_hash_map/count_strings/Makefile
examples/concurrent_hash_map/count_strings/count_strings.cpp
examples/concurrent_hash_map/count_strings/msvs/count_strings.vcxproj
examples/concurrent_hash_map/count_strings/xcode/count_strings.xcodeproj/project.pbxproj
examples/concurrent_priority_queue/shortpath/Makefile
examples/concurrent_priority_queue/shortpath/msvs/shortpath.vcxproj
examples/concurrent_priority_queue/shortpath/shortpath.cpp
examples/concurrent_priority_queue/shortpath/xcode/shortpath.xcodeproj/project.pbxproj
examples/graph/binpack/Makefile
examples/graph/binpack/binpack.cpp
examples/graph/binpack/msvs/binpack.vcxproj
examples/graph/binpack/xcode/binpack.xcodeproj/project.pbxproj
examples/graph/cholesky/Makefile
examples/graph/cholesky/cholesky.cpp
examples/graph/cholesky/msvs/cholesky.vcxproj
examples/graph/cholesky/xcode/cholesky.xcodeproj/project.pbxproj
examples/graph/dining_philosophers/Makefile
examples/graph/dining_philosophers/dining_philosophers.cpp
examples/graph/dining_philosophers/msvs/dining_philosophers.vcxproj
examples/graph/dining_philosophers/xcode/dining_philosophers.xcodeproj/project.pbxproj
examples/graph/fgbzip2/Makefile
examples/graph/fgbzip2/fgbzip2.cpp
examples/graph/fgbzip2/msvs/fgbzip2.vcxproj
examples/graph/fgbzip2/xcode/fgbzip2.xcodeproj/project.pbxproj
examples/graph/logic_sim/Makefile
examples/graph/logic_sim/basics.h
examples/graph/logic_sim/msvs/logic_sim.vcxproj
examples/graph/logic_sim/test_all.cpp
examples/graph/som/Makefile
examples/graph/som/msvs/som.vcxproj
examples/graph/som/som_graph.cpp
examples/graph/som/xcode/som.xcodeproj/project.pbxproj
examples/graph/stereo/msvs/stereo.vcxproj
examples/parallel_do/parallel_preorder/Graph.cpp
examples/parallel_do/parallel_preorder/Graph.h
examples/parallel_do/parallel_preorder/Makefile
examples/parallel_do/parallel_preorder/main.cpp
examples/parallel_do/parallel_preorder/msvs/parallel_preorder.vcxproj
examples/parallel_do/parallel_preorder/xcode/parallel_preorder.xcodeproj/project.pbxproj
examples/parallel_for/game_of_life/Makefile
examples/parallel_for/game_of_life/msvs/Game_of_life.vcxproj
examples/parallel_for/game_of_life/src/Evolution.cpp
examples/parallel_for/game_of_life/src/Evolution.h
examples/parallel_for/game_of_life/src/Game_of_life.cpp
examples/parallel_for/polygon_overlay/Makefile
examples/parallel_for/polygon_overlay/msvs/pover.vcxproj
examples/parallel_for/polygon_overlay/polymain.cpp
examples/parallel_for/polygon_overlay/polyover.cpp
examples/parallel_for/polygon_overlay/polyover.h
examples/parallel_for/polygon_overlay/pover_video.cpp
examples/parallel_for/polygon_overlay/xcode/polygon_overlay.xcodeproj/project.pbxproj
examples/parallel_for/seismic/Makefile
examples/parallel_for/seismic/main.cpp
examples/parallel_for/seismic/msvs/SeismicSimulation.vcxproj
examples/parallel_for/seismic/seismic_video.cpp
examples/parallel_for/seismic/xcode/seismic.xcodeproj/project.pbxproj
examples/parallel_for/tachyon/Makefile
examples/parallel_for/tachyon/msvs/tachyon.tbb.vcxproj
examples/parallel_for/tachyon/msvs/tachyon.tbb1d.vcxproj
examples/parallel_for/tachyon/msvs/uwp/App.xaml [moved from examples/parallel_for/tachyon/msvs/win8ui/App.xaml with 100% similarity]
examples/parallel_for/tachyon/msvs/uwp/App.xaml.cpp [moved from examples/parallel_for/tachyon/msvs/win8ui/App.xaml.cpp with 100% similarity]
examples/parallel_for/tachyon/msvs/uwp/App.xaml.h [moved from examples/parallel_for/tachyon/msvs/win8ui/App.xaml.h with 100% similarity]
examples/parallel_for/tachyon/msvs/uwp/Assets/Logo.png [moved from examples/parallel_for/tachyon/msvs/win8ui/Assets/Logo.png with 100% similarity]
examples/parallel_for/tachyon/msvs/uwp/Assets/SmallLogo.png [moved from examples/parallel_for/tachyon/msvs/win8ui/Assets/SmallLogo.png with 100% similarity]
examples/parallel_for/tachyon/msvs/uwp/Assets/SplashScreen.png [moved from examples/parallel_for/tachyon/msvs/win8ui/Assets/SplashScreen.png with 100% similarity]
examples/parallel_for/tachyon/msvs/uwp/Assets/StoreLogo.png [moved from examples/parallel_for/tachyon/msvs/win8ui/Assets/StoreLogo.png with 100% similarity]
examples/parallel_for/tachyon/msvs/uwp/Common/StandardStyles.xaml [moved from examples/parallel_for/tachyon/msvs/win8ui/Common/StandardStyles.xaml with 100% similarity]
examples/parallel_for/tachyon/msvs/uwp/DirectXBase.cpp [moved from examples/parallel_for/tachyon/msvs/win8ui/DirectXBase.cpp with 99% similarity]
examples/parallel_for/tachyon/msvs/uwp/DirectXBase.h [moved from examples/parallel_for/tachyon/msvs/win8ui/DirectXBase.h with 100% similarity]
examples/parallel_for/tachyon/msvs/uwp/DirectXPage.xaml [moved from examples/parallel_for/tachyon/msvs/win8ui/DirectXPage.xaml with 100% similarity]
examples/parallel_for/tachyon/msvs/uwp/DirectXPage.xaml.cpp [moved from examples/parallel_for/tachyon/msvs/win8ui/DirectXPage.xaml.cpp with 89% similarity]
examples/parallel_for/tachyon/msvs/uwp/DirectXPage.xaml.h [moved from examples/parallel_for/tachyon/msvs/win8ui/DirectXPage.xaml.h with 100% similarity]
examples/parallel_for/tachyon/msvs/uwp/Package.appxmanifest [new file with mode: 0644]
examples/parallel_for/tachyon/msvs/uwp/copy_libraries_and_assets.bat [moved from examples/parallel_for/tachyon/msvs/win8ui/copy_libraries_and_assets.bat with 75% similarity]
examples/parallel_for/tachyon/msvs/uwp/pch.h [moved from examples/parallel_for/tachyon/msvs/win8ui/pch.h with 100% similarity]
examples/parallel_for/tachyon/msvs/uwp/tbbTachyon.sln [new file with mode: 0644]
examples/parallel_for/tachyon/msvs/uwp/tbbTachyon.vcxproj [moved from examples/parallel_for/tachyon/msvs/win8ui/tbbTachyon.vcxproj with 91% similarity]
examples/parallel_for/tachyon/msvs/uwp/tbbTachyon.vcxproj.filters [moved from examples/parallel_for/tachyon/msvs/win8ui/tbbTachyon.vcxproj.filters with 87% similarity]
examples/parallel_for/tachyon/msvs/uwp/tbbTachyonRenderer.cpp [moved from examples/parallel_for/tachyon/msvs/win8ui/tbbTachyonRenderer.cpp with 97% similarity]
examples/parallel_for/tachyon/msvs/uwp/tbbTachyonRenderer.h [moved from examples/parallel_for/tachyon/msvs/win8ui/tbbTachyonRenderer.h with 100% similarity]
examples/parallel_for/tachyon/msvs/win8ui/Package.appxmanifest [deleted file]
examples/parallel_for/tachyon/msvs/win8ui/tbbTachyon.sln [deleted file]
examples/parallel_for/tachyon/src/main.cpp
examples/parallel_for/tachyon/src/trace.tbb.cpp
examples/parallel_for/tachyon/src/trace.tbb1d.cpp
examples/parallel_for/tachyon/xcode/tachyon.xcodeproj/project.pbxproj
examples/parallel_reduce/convex_hull/Makefile
examples/parallel_reduce/convex_hull/convex_hull.h
examples/parallel_reduce/convex_hull/convex_hull_bench.cpp
examples/parallel_reduce/convex_hull/convex_hull_sample.cpp
examples/parallel_reduce/convex_hull/msvs/convex_hull_benchmark.vcxproj
examples/parallel_reduce/convex_hull/msvs/convex_hull_sample.vcxproj
examples/parallel_reduce/primes/Makefile
examples/parallel_reduce/primes/main.cpp
examples/parallel_reduce/primes/msvs/primes.vcxproj
examples/parallel_reduce/primes/primes.cpp
examples/parallel_reduce/primes/primes.h
examples/pipeline/index.html
examples/pipeline/square/Makefile
examples/pipeline/square/msvs/square.vcxproj
examples/pipeline/square/readme.html
examples/pipeline/square/square.cpp
examples/task/tree_sum/Makefile
examples/task/tree_sum/main.cpp
examples/task/tree_sum/msvs/tree_sum.vcxproj
examples/task_arena/fractal/Makefile
examples/task_arena/fractal/fractal.cpp
examples/task_arena/fractal/fractal.h
examples/task_arena/fractal/fractal_video.h
examples/task_arena/fractal/main.cpp
examples/task_arena/fractal/msvs/fractal.vcxproj
examples/task_arena/fractal/readme.html
examples/task_arena/fractal/xcode/fractal.xcodeproj/project.pbxproj
examples/task_arena/index.html
examples/task_group/sudoku/Makefile
examples/task_group/sudoku/msvs/sudoku.vcxproj
examples/task_group/sudoku/sudoku.cpp
examples/task_group/sudoku/xcode/sudoku.xcodeproj/project.pbxproj
examples/test_all/fibonacci/CMakeLists.txt
examples/test_all/fibonacci/Fibonacci.cpp
examples/test_all/fibonacci/Makefile
examples/test_all/fibonacci/msvs/fibonacci.vcxproj
examples/test_all/fibonacci/xcode/fibonacci.xcodeproj/project.pbxproj
include/serial/tbb/parallel_for.h
include/tbb/aggregator.h
include/tbb/aligned_space.h
include/tbb/atomic.h
include/tbb/combinable.h
include/tbb/compat/condition_variable
include/tbb/compat/ppl.h
include/tbb/compat/thread
include/tbb/compat/tuple
include/tbb/concurrent_hash_map.h
include/tbb/concurrent_lru_cache.h
include/tbb/concurrent_map.h
include/tbb/concurrent_priority_queue.h
include/tbb/concurrent_queue.h
include/tbb/concurrent_set.h
include/tbb/concurrent_unordered_map.h
include/tbb/concurrent_unordered_set.h
include/tbb/concurrent_vector.h
include/tbb/critical_section.h
include/tbb/enumerable_thread_specific.h
include/tbb/flow_graph.h
include/tbb/flow_graph_abstractions.h
include/tbb/flow_graph_opencl_node.h
include/tbb/internal/_concurrent_queue_impl.h
include/tbb/internal/_concurrent_skip_list_impl.h
include/tbb/internal/_concurrent_unordered_impl.h
include/tbb/internal/_deprecated_header_message_guard.h [new file with mode: 0644]
include/tbb/internal/_flow_graph_body_impl.h
include/tbb/internal/_flow_graph_cache_impl.h
include/tbb/internal/_flow_graph_impl.h
include/tbb/internal/_flow_graph_indexer_impl.h
include/tbb/internal/_flow_graph_join_impl.h
include/tbb/internal/_flow_graph_node_impl.h
include/tbb/internal/_flow_graph_node_set_impl.h [new file with mode: 0644]
include/tbb/internal/_flow_graph_nodes_deduction.h [new file with mode: 0644]
include/tbb/internal/_flow_graph_streaming_node.h
include/tbb/internal/_flow_graph_trace_impl.h
include/tbb/internal/_tbb_hash_compare_impl.h
include/tbb/internal/_tbb_strings.h
include/tbb/internal/_template_helpers.h
include/tbb/internal/_warning_suppress_disable_notice.h [new file with mode: 0644]
include/tbb/internal/_warning_suppress_enable_notice.h [new file with mode: 0644]
include/tbb/iterators.h
include/tbb/mutex.h
include/tbb/parallel_do.h
include/tbb/parallel_for.h
include/tbb/parallel_invoke.h
include/tbb/parallel_reduce.h
include/tbb/parallel_scan.h
include/tbb/parallel_sort.h
include/tbb/parallel_while.h
include/tbb/partitioner.h
include/tbb/pipeline.h
include/tbb/queuing_mutex.h
include/tbb/queuing_rw_mutex.h
include/tbb/reader_writer_lock.h
include/tbb/recursive_mutex.h
include/tbb/runtime_loader.h
include/tbb/spin_mutex.h
include/tbb/task.h
include/tbb/task_arena.h
include/tbb/task_group.h
include/tbb/task_scheduler_init.h
include/tbb/task_scheduler_observer.h
include/tbb/tbb.h
include/tbb/tbb_config.h
include/tbb/tbb_exception.h
include/tbb/tbb_profiling.h
include/tbb/tbb_stddef.h
include/tbb/tbb_thread.h
python/setup.py
src/old/concurrent_queue_v2.h
src/perf/harness_perf.h [new file with mode: 0644]
src/perf/time_resumable_tasks.cpp [new file with mode: 0644]
src/rml/server/rml_server.cpp
src/tbb/arena.cpp
src/tbb/arena.h
src/tbb/co_context.h [new file with mode: 0644]
src/tbb/custom_scheduler.h
src/tbb/governor.cpp
src/tbb/governor.h
src/tbb/lin32-tbb-export.lst
src/tbb/lin64-tbb-export.lst
src/tbb/lin64ipf-tbb-export.lst
src/tbb/mac32-tbb-export.lst
src/tbb/mac64-tbb-export.lst
src/tbb/market.cpp
src/tbb/market.h
src/tbb/scheduler.cpp
src/tbb/scheduler.h
src/tbb/scheduler_common.h
src/tbb/tbb_main.cpp
src/tbb/tbb_misc.cpp
src/tbb/tbb_misc.h
src/tbb/win32-tbb-export.lst
src/tbb/win64-gcc-tbb-export.lst
src/tbb/win64-tbb-export.lst
src/test/harness.h
src/test/harness_graph.h
src/test/harness_m128.h
src/test/test_allocator.h
src/test/test_async_msg.cpp
src/test/test_async_node.cpp
src/test/test_broadcast_node.cpp
src/test/test_buffer_node.cpp
src/test/test_combinable.cpp
src/test/test_concurrent_associative_common.h
src/test/test_concurrent_map.cpp
src/test/test_concurrent_ordered_common.h
src/test/test_concurrent_priority_queue.cpp
src/test/test_concurrent_queue.cpp
src/test/test_concurrent_set.cpp
src/test/test_continue_node.cpp
src/test/test_eh_flow_graph.cpp
src/test/test_eh_tasks.cpp
src/test/test_flow_graph_whitebox.cpp
src/test/test_follows_and_precedes_api.h [new file with mode: 0644]
src/test/test_function_node.cpp
src/test/test_global_control.cpp
src/test/test_indexer_node.cpp
src/test/test_iterators.cpp
src/test/test_join_node.cpp
src/test/test_join_node.h
src/test/test_join_node_key_matching.cpp
src/test/test_join_node_msg_key_matching.cpp
src/test/test_limiter_node.cpp
src/test/test_multifunction_node.cpp
src/test/test_opencl_node.cpp
src/test/test_overwrite_node.cpp
src/test/test_parallel_pipeline.cpp
src/test/test_parallel_reduce.cpp
src/test/test_partitioner_whitebox.h
src/test/test_priority_queue_node.cpp
src/test/test_queue_node.cpp
src/test/test_resumable_tasks.cpp [new file with mode: 0644]
src/test/test_sequencer_node.cpp
src/test/test_source_node.cpp
src/test/test_split_node.cpp
src/test/test_streaming_node.cpp
src/test/test_tagged_msg.cpp
src/test/test_task.cpp
src/test/test_task_group.cpp
src/test/test_tbb_header.cpp
src/test/test_tbb_version.cpp
src/test/test_write_once_node.cpp

index 13b5c5a..9b2411e 100644 (file)
@@ -85,3 +85,4 @@ CMakeFiles/
 .svn
 crash*
 *.tmp
+/.vs
diff --git a/CHANGES b/CHANGES
index 6e7cb60..79bb675 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,40 @@
 The list of most significant changes made over time in
 Intel(R) Threading Building Blocks (Intel(R) TBB).
 
+Intel TBB 2019 Update 9
+TBB_INTERFACE_VERSION == 11009
+
+Changes (w.r.t. Intel TBB 2019 Update 8):
+
+- Multiple APIs are deprecated. For details, please see
+    Deprecated Features appendix in the TBB reference manual.
+- Added C++17 deduction guides for flow graph nodes.
+
+Preview Features:
+
+- Added isolated_task_group class that allows multiple threads to add 
+    and execute tasks sharing the same isolation.
+- Extended the flow graph API to simplify connecting nodes.
+- Added erase() by heterogeneous keys for concurrent ordered containers.
+- Added a possibility to suspend task execution at a specific point
+    and resume it later.
+
+Bugs fixed:
+
+- Fixed the emplace() method of concurrent unordered containers to
+    destroy a temporary element that was not inserted.
+- Fixed a bug in the merge() method of concurrent unordered
+    containers.
+- Fixed behavior of a continue_node that follows buffering nodes.
+
+Open-source contributions integrated:
+
+- Added support for move-only types to tbb::parallel_pipeline
+    (https://github.com/intel/tbb/pull/159) by Raf Schietekat.
+- Fixed detection of clang version when CUDA toolkit is installed
+    (https://github.com/intel/tbb/pull/150) by Guilherme Amadio.
+
+------------------------------------------------------------------------
 Intel TBB 2019 Update 8
 TBB_INTERFACE_VERSION == 11008
 
index 4efa64a..926a964 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-# Threading Building Blocks 2019 Update 8
-[![Stable release](https://img.shields.io/badge/version-2019_U8-green.svg)](https://github.com/01org/tbb/releases/tag/2019_U8)
+# Threading Building Blocks 2019 Update 9
+[![Stable release](https://img.shields.io/badge/version-2019_U9-green.svg)](https://github.com/intel/tbb/releases/tag/2019_U9)
 [![Apache License Version 2.0](https://img.shields.io/badge/license-Apache_2.0-green.svg)](LICENSE)
 
 Threading Building Blocks (TBB) lets you easily write parallel C++ programs that take
@@ -8,7 +8,7 @@ full advantage of multicore performance, that are portable, composable and have
 ## Release Information
 Here are the latest [Changes](CHANGES) and [Release Notes](doc/Release_Notes.txt) (contains system requirements and known issues).
 
-Since [2018 U5](https://github.com/01org/tbb/releases/tag/2018_U5) TBB binary packages include [Parallel STL](https://github.com/intel/parallelstl) as a high-level component.
+Since [2018 U5](https://github.com/intel/tbb/releases/tag/2018_U5) TBB binary packages include [Parallel STL](https://github.com/intel/parallelstl) as a high-level component.
 
 ## Documentation
 * TBB [tutorial](https://software.intel.com/en-us/tbb-tutorial)
@@ -17,7 +17,7 @@ and [latest](https://www.threadingbuildingblocks.org/docs/help/index.htm)
 
 ## Support
 Please report issues and suggestions via
-[GitHub issues](https://github.com/01org/tbb/issues) or start a topic on the
+[GitHub issues](https://github.com/intel/tbb/issues) or start a topic on the
 [TBB forum](http://software.intel.com/en-us/forums/intel-threading-building-blocks/).
 
 ## How to Contribute
index 6ef75db..bb35b58 100644 (file)
@@ -25,7 +25,7 @@ ifndef arch
 endif
 
 ifndef runtime
-        clang_version:=$(shell clang -v 2>&1 | grep version | sed "s/.*version \([0-9]*\.[0-9]*\).*/\1/")
+        clang_version:=$(shell clang --version | sed -n "1s/.*version \(.*[0-9]\) .*/\1/p")
         os_version:=$(shell uname -r)
         os_kernel_version:=$(shell uname -r | sed -e 's/-.*$$//')
         export runtime:=cc$(clang_version)_kernel$(os_kernel_version)
index 653d4a3..ebc47d7 100644 (file)
@@ -32,7 +32,7 @@ C_FLAGS = $(CPLUS_FLAGS)
 
 # gcc 6.0 and later have -flifetime-dse option that controls
 # elimination of stores done outside the object lifetime
-ifneq (,$(shell gcc -dumpfullversion -dumpversion | egrep  "^([6-9])"))
+ifneq (,$(shell gcc -dumpfullversion -dumpversion | egrep  "^([6-9]|1[0-9])"))
     # keep pre-contruction stores for zero initialization
     DSE_KEY = -flifetime-dse=1
 endif
index 62983a6..69e2e05 100644 (file)
@@ -60,6 +60,13 @@ TBB_DEP_NON_RML_TEST?= cache_aligned_allocator_rml.$(OBJ) dynamic_link_rml.$(OBJ
 ifeq ($(cfg),debug)
 RML_TBB_DEP+= spin_mutex_rml.$(OBJ)
 TBB_DEP_RML_TEST?= $(RML_ASM.OBJ) tbb_misc_rml.$(OBJ)
+
+ifeq (windows icl,$(tbb_os) $(compiler_name))
+# Some versions of ICC link to the wrong version of the vc runtime
+# libcpmtd.lib should be used instead of libcpmt.lib
+LIB_LINK_FLAGS += /nodefaultlib:libcpmt.lib
+endif
+
 else
 TBB_DEP_RML_TEST?= $(RML_ASM.OBJ)
 endif
index a014e13..4eb0010 100644 (file)
@@ -103,6 +103,9 @@ test_dynamic_link.$(TEST_EXT): LIBS += $(LIBDL)
 ifneq (,$(BIGOBJ_KEY))
 TEST_BIGOBJ = test_opencl_node.$(TEST_EXT)      \
     test_atomic.$(TEST_EXT)                     \
+    test_concurrent_hash_map.$(TEST_EXT)        \
+    test_concurrent_set.$(TEST_EXT)             \
+    test_concurrent_map.$(TEST_EXT)             \
     test_concurrent_unordered_set.$(TEST_EXT)   \
     test_concurrent_unordered_map.$(TEST_EXT)   \
     test_join_node_key_matching.$(TEST_EXT)     \
@@ -130,6 +133,8 @@ TEST_TBB_PLAIN.EXE = test_assembly.$(TEST_EXT)   \
        test_concurrent_unordered_set.$(TEST_EXT)    \
        test_concurrent_unordered_map.$(TEST_EXT)    \
        test_concurrent_hash_map.$(TEST_EXT)         \
+       test_concurrent_set.$(TEST_EXT)              \
+       test_concurrent_map.$(TEST_EXT)              \
        test_enumerable_thread_specific.$(TEST_EXT)  \
        test_handle_perror.$(TEST_EXT)               \
        test_halt.$(TEST_EXT)                        \
@@ -211,6 +216,7 @@ TEST_TBB_PLAIN.EXE = test_assembly.$(TEST_EXT)   \
        test_composite_node.$(TEST_EXT)              \
        test_async_node.$(TEST_EXT)                  \
        test_async_msg.$(TEST_EXT)                   \
+       test_resumable_tasks.$(TEST_EXT)             \
        test_tbb_version.$(TEST_EXT)                 # insert new files right above
 
 # These tests depend on other technologies
index d56b924..e974701 100644 (file)
@@ -42,6 +42,10 @@ endif
 INCLUDES += $(INCLUDE_KEY)$(tbb_root)/src $(INCLUDE_KEY)$(tbb_root)/src/rml/include $(INCLUDE_KEY)$(tbb_root)/include
 
 CPLUS_FLAGS += $(WARNING_KEY) $(CXXFLAGS)
+
+# Suppress warnings about usage of deprecated content
+CPLUS_FLAGS += $(DEFINE_KEY)TBB_SUPPRESS_DEPRECATED_MESSAGES=1
+
 ifeq (1,$(tbb_cpf))
 CPLUS_FLAGS += $(DEFINE_KEY)__TBB_CPF_BUILD=1
 endif
index ccbe986..6617e3e 100644 (file)
@@ -57,12 +57,18 @@ function doWork() {
                     WScript.Echo("mingw" + gccVersion);
                 }
                 else if (WScript.Arguments(0) == "/minversion") {
-                    // Comparing strings, not numbers; will not work for two-digit versions
-                    if (gccVersion >= WScript.Arguments(2)) {
-                        WScript.Echo("ok");
-                    } else {
-                        WScript.Echo("fail");
+                    for (var i = 0; i < 3; i++) {
+                        v1 = parseInt(gccVersion.split('.')[i]);
+                        v2 = parseInt(WScript.Arguments(2).split('.')[i]);
+
+                        if (v1 > v2) {
+                            break;
+                        } else if (v1 < v2) {
+                            WScript.Echo("fail");
+                            return;
+                        }
                     }
+                    WScript.Echo("ok");
                 }
             }
             return;
@@ -121,6 +127,8 @@ function doWork() {
         } else if (mapContext.match(vc140)) {
             if (WshShell.ExpandEnvironmentStrings("%VisualStudioVersion%") == "15.0")
                 WScript.Echo("vc14.1");
+            else if (WshShell.ExpandEnvironmentStrings("%VisualStudioVersion%") == "16.0")
+                WScript.Echo("vc14.2");
             else
                 WScript.Echo("vc14");
         } else {
index 9965331..a0caf16 100644 (file)
@@ -30,17 +30,21 @@ EXPORT_KEY = -Wl,--version-script,
 LIBDL = -ldl
 
 LIB_LINK_FLAGS = $(DYLIB_KEY) -Wl,-soname=$(BUILDING_LIBRARY)
-LIBS += -lpthread -lrt
+LIBS += -lrt
 LINK_FLAGS = -Wl,-rpath-link=. -rdynamic
 C_FLAGS = $(CPLUS_FLAGS)
 
 ifeq ($(cfg), release)
-        CPLUS_FLAGS = $(ITT_NOTIFY) -g -O2 -DUSE_PTHREAD
+        # -g is set intentionally in the release mode. It should not affect performance.
+        CPLUS_FLAGS = -O2 -g
 endif
 ifeq ($(cfg), debug)
-        CPLUS_FLAGS = -DTBB_USE_DEBUG $(ITT_NOTIFY) -g -O0 -DUSE_PTHREAD
+        CPLUS_FLAGS = -DTBB_USE_DEBUG -O0 -g
 endif
 
+CPLUS_FLAGS += $(ITT_NOTIFY) -DUSE_PTHREAD -pthread
+LIB_LINK_FLAGS += -pthread
+
 ifneq (,$(stdlib))
     CPLUS_FLAGS    += -stdlib=$(stdlib)
     LIB_LINK_FLAGS += -stdlib=$(stdlib)
index b898676..14428ad 100644 (file)
@@ -31,27 +31,27 @@ EXPORT_KEY = -Wl,--version-script,
 LIBDL = -ldl
 
 LIB_LINK_FLAGS = $(DYLIB_KEY) -Wl,-soname=$(BUILDING_LIBRARY)
-LIBS += -lpthread -lrt
+LIBS += -lrt
 LINK_FLAGS = -Wl,-rpath-link=. -rdynamic
 C_FLAGS = $(CPLUS_FLAGS)
 
 # gcc 4.2 and higher support OpenMP
-ifneq (,$(shell $(CONLY) -dumpfullversion -dumpversion | egrep  "^(4\.[2-9]|[5-9])"))
+ifneq (,$(shell $(CONLY) -dumpfullversion -dumpversion | egrep  "^(4\.[2-9]|[5-9]|1[0-9])"))
     OPENMP_FLAG = -fopenmp
 endif
 
 # gcc 4.8 and later support RTM intrinsics, but require command line switch to enable them
-ifneq (,$(shell $(CONLY) -dumpfullversion -dumpversion | egrep  "^(4\.[8-9]|[5-9])"))
+ifneq (,$(shell $(CONLY) -dumpfullversion -dumpversion | egrep  "^(4\.[8-9]|[5-9]|1[0-9])"))
     RTM_KEY = -mrtm
 endif
 
 # gcc 4.0 and later have -Wextra that is used by some our customers.
-ifneq (,$(shell $(CONLY) -dumpfullversion -dumpversion | egrep  "^([4-9])"))
+ifneq (,$(shell $(CONLY) -dumpfullversion -dumpversion | egrep  "^([4-9]|1[0-9])"))
     WARNING_KEY += -Wextra
 endif
 
 # gcc 5.0 and later have -Wsuggest-override and -Wno-sized-deallocation options
-ifneq (,$(shell $(CONLY) -dumpfullversion -dumpversion | egrep  "^([5-9])"))
+ifneq (,$(shell $(CONLY) -dumpfullversion -dumpversion | egrep  "^([5-9]|1[0-9])"))
     # enable -Wsuggest-override via a pre-included header in order to limit to C++11 and above
     INCLUDE_TEST_HEADERS = -include $(tbb_root)/src/test/harness_preload.h
     WARNING_SUPPRESS += -Wno-sized-deallocation
@@ -59,18 +59,22 @@ endif
 
 # gcc 6.0 and later have -flifetime-dse option that controls
 # elimination of stores done outside the object lifetime
-ifneq (,$(shell $(CONLY) -dumpfullversion -dumpversion | egrep  "^([6-9])"))
+ifneq (,$(shell $(CONLY) -dumpfullversion -dumpversion | egrep  "^([6-9]|1[0-9])"))
     # keep pre-contruction stores for zero initialization
     DSE_KEY = -flifetime-dse=1
 endif
 
 ifeq ($(cfg), release)
-        CPLUS_FLAGS = $(ITT_NOTIFY) -g -O2 -DUSE_PTHREAD
+        # -g is set intentionally in the release mode. It should not affect performance.
+        CPLUS_FLAGS = -O2 -g
 endif
 ifeq ($(cfg), debug)
-        CPLUS_FLAGS = -DTBB_USE_DEBUG $(ITT_NOTIFY) -g -O0 -DUSE_PTHREAD
+        CPLUS_FLAGS = -DTBB_USE_DEBUG -O0 -g
 endif
 
+CPLUS_FLAGS += $(ITT_NOTIFY) -DUSE_PTHREAD -pthread
+LIB_LINK_FLAGS += -pthread
+
 TBB_ASM.OBJ=
 MALLOC_ASM.OBJ=
 
index 3079812..210ad17 100644 (file)
@@ -34,16 +34,20 @@ endif
 ITT_NOTIFY = -DDO_ITT_NOTIFY
 ifeq (release,$(cfg))
 SDL_FLAGS += -D_FORTIFY_SOURCE=2
-CPLUS_FLAGS = $(ITT_NOTIFY) -O2 -g -DUSE_PTHREAD
+# -g is set intentionally in the release mode. It should not affect performance.
+CPLUS_FLAGS = -O2 -g -qno-opt-report-embed
 else
-CPLUS_FLAGS = $(ITT_NOTIFY) -O0 -g -DUSE_PTHREAD -DTBB_USE_DEBUG
+CPLUS_FLAGS = -O0 -g -DTBB_USE_DEBUG
 endif
 
 LIB_LINK_FLAGS = -shared -static-intel -Wl,-soname=$(BUILDING_LIBRARY) -z relro -z now
-LIBS += -lpthread -lrt
+LIBS += -lrt
 LINK_FLAGS = -rdynamic
 C_FLAGS = $(CPLUS_FLAGS)
 
+CPLUS_FLAGS += $(ITT_NOTIFY) -DUSE_PTHREAD -pthread
+LIB_LINK_FLAGS += -pthread
+
 ifneq (,$(shell icc -dumpversion | egrep  "^1[6-9]\."))
 OPENMP_FLAG = -qopenmp
 else
index 4316fa3..5b67de4 100644 (file)
@@ -42,6 +42,11 @@ endif
 
 CPLUS_FLAGS += -DUSE_PTHREAD $(ITT_NOTIFY)
 
+ifeq (1,$(tbb_cpf))
+# For correct ucontext.h structures layout
+CPLUS_FLAGS += -D_XOPEN_SOURCE
+endif
+
 # For Clang, we add the option to support RTM intrinsics *iff* xtest is found in <immintrin.h>
 ifneq (,$(shell grep xtest `echo "\#include<immintrin.h>" | $(CONLY) -E -M - 2>&1 | grep immintrin.h` 2>/dev/null))
     RTM_KEY = -mrtm
index b03dc9c..2a6f385 100644 (file)
@@ -35,19 +35,19 @@ LIB_LINK_FLAGS = -dynamiclib -install_name @rpath/$(BUILDING_LIBRARY)
 C_FLAGS = $(CPLUS_FLAGS)
 
 # gcc 4.8 and later support RTM intrinsics, but require command line switch to enable them
-ifneq (,$(shell $(CONLY) -dumpfullversion -dumpversion | egrep  "^(4\.[8-9]|[5-9])"))
+ifneq (,$(shell $(CONLY) -dumpfullversion -dumpversion | egrep  "^(4\.[8-9]|[5-9]|1[0-9])"))
     RTM_KEY = -mrtm
 endif
 
 # gcc 5.0 and later have -Wsuggest-override option
 # enable it via a pre-included header in order to limit to C++11 and above
-ifneq (,$(shell $(CONLY) -dumpfullversion -dumpversion | egrep  "^([5-9])"))
+ifneq (,$(shell $(CONLY) -dumpfullversion -dumpversion | egrep  "^([5-9]|1[0-9])"))
     INCLUDE_TEST_HEADERS = -include $(tbb_root)/src/test/harness_preload.h
 endif
 
 # gcc 6.0 and later have -flifetime-dse option that controls
 # elimination of stores done outside the object lifetime
-ifneq (,$(shell $(CONLY) -dumpfullversion -dumpversion | egrep  "^([6-9])"))
+ifneq (,$(shell $(CONLY) -dumpfullversion -dumpversion | egrep  "^([6-9]|1[0-9])"))
     # keep pre-contruction stores for zero initialization
     DSE_KEY = -flifetime-dse=1
 endif
index 506d98c..20f59b2 100644 (file)
@@ -49,7 +49,7 @@ endif
 
 ifeq ($(cfg), release)
     SDL_FLAGS += -D_FORTIFY_SOURCE=2
-    CPLUS_FLAGS = -g -O2 -fno-omit-frame-pointer
+    CPLUS_FLAGS = -g -O2 -fno-omit-frame-pointer -qno-opt-report-embed
 else
     CPLUS_FLAGS = -g -O0 -DTBB_USE_DEBUG
 endif
@@ -57,6 +57,11 @@ endif
 ITT_NOTIFY = -DDO_ITT_NOTIFY
 CPLUS_FLAGS += -DUSE_PTHREAD $(ITT_NOTIFY)
 
+ifeq (1,$(tbb_cpf))
+# For correct ucontext.h structures layout
+CPLUS_FLAGS += -D_XOPEN_SOURCE
+endif
+
 ifneq (,$(codecov))
     CPLUS_FLAGS += -prof-gen=srcpos
 endif
index aa2923b..99c46e9 100644 (file)
@@ -45,7 +45,7 @@ ifndef arch
 endif
 
 ifndef runtime
-  clang_version:=$(shell clang -v 2>&1 >/dev/null | grep version | sed -e "s/.*version \(.*[0-9]\) .*/\1/")
+  clang_version:=$(shell clang --version | sed -n "1s/.*version \(.*[0-9]\) .*/\1/p")
   ifndef os_version
     os_version:=$(shell /usr/bin/sw_vers -productVersion)
   endif
index d49fcf8..370e4e1 100644 (file)
@@ -19,7 +19,7 @@ echo "#define __TBB_VERSION_STRINGS(N) \\"
 echo '#N": BUILD_HOST'"\t\t"`hostname -s`" ("`arch`")"'" ENDL \'
 echo '#N": BUILD_OS'"\t\t"`sw_vers -productName`" version "`sw_vers -productVersion`'" ENDL \'
 echo '#N": BUILD_KERNEL'"\t"`uname -v`'" ENDL \'
-echo '#N": BUILD_CLANG'"\t"`clang --version </dev/null 2>&1 | grep 'version '`'" ENDL \'
+echo '#N": BUILD_CLANG'"\t"`clang --version | sed -n "1p"`'" ENDL \'
 echo '#N": BUILD_XCODE'"\t"`xcodebuild -version </dev/null 2>&1 | grep 'Xcode'`'" ENDL \'
 [ -z "$COMPILER_VERSION" ] || echo '#N": BUILD_COMPILER'"\t"$COMPILER_VERSION'" ENDL \'
 echo '#N": BUILD_TARGET'"\t$arch on $runtime"'" ENDL \'
index cbfcd39..e1aa9b5 100644 (file)
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
-      <AdditionalOptions>  /c /MDd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBB_BUILD=1 /W4 /I../../src /I../../src/rml/include /I../../include</AdditionalOptions>
+      <AdditionalOptions>  /c /MDd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBB_BUILD=1 /W4 /I../../src /I../../src/rml/include /I../../include</AdditionalOptions>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <TargetEnvironment>X64</TargetEnvironment>
     </Midl>
     <ClCompile>
-      <AdditionalOptions>  /c /MDd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBB_BUILD=1 /W4 /I../../src /I../../src/rml/include /I../../include</AdditionalOptions>
+      <AdditionalOptions>  /c /MDd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBB_BUILD=1 /W4 /I../../src /I../../src/rml/include /I../../include</AdditionalOptions>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <ClCompile>
-      <AdditionalOptions>  /c /MD /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBB_BUILD=1 /W4 /I../../src /I../../src/rml/include /I../../include</AdditionalOptions>
+      <AdditionalOptions>  /c /MD /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBB_BUILD=1 /W4 /I../../src /I../../src/rml/include /I../../include</AdditionalOptions>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <TargetEnvironment>X64</TargetEnvironment>
     </Midl>
     <ClCompile>
-      <AdditionalOptions>  /c /MD /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBB_BUILD=1 /W4 /I../../src /I../../src/rml/include /I../../include</AdditionalOptions>
+      <AdditionalOptions>  /c /MD /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBB_BUILD=1 /W4 /I../../src /I../../src/rml/include /I../../include</AdditionalOptions>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug-MT|Win32'">
     <ClCompile>
-      <AdditionalOptions>  /c /MTd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBB_BUILD=1 /W4 /I../../src /I../../src/rml/include /I../../include</AdditionalOptions>
+      <AdditionalOptions>  /c /MTd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBB_BUILD=1 /W4 /I../../src /I../../src/rml/include /I../../include</AdditionalOptions>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <TargetEnvironment>X64</TargetEnvironment>
     </Midl>
     <ClCompile>
-      <AdditionalOptions>  /c /MTd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBB_BUILD=1 /W4 /I../../src /I../../src/rml/include /I../../include</AdditionalOptions>
+      <AdditionalOptions>  /c /MTd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBB_BUILD=1 /W4 /I../../src /I../../src/rml/include /I../../include</AdditionalOptions>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release-MT|Win32'">
     <ClCompile>
-      <AdditionalOptions>  /c /MT /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBB_BUILD=1 /W4 /I../../src /I../../src/rml/include /I../../include</AdditionalOptions>
+      <AdditionalOptions>  /c /MT /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBB_BUILD=1 /W4 /I../../src /I../../src/rml/include /I../../include</AdditionalOptions>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <TargetEnvironment>X64</TargetEnvironment>
     </Midl>
     <ClCompile>
-      <AdditionalOptions>  /c /MT /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBB_BUILD=1 /W4 /I../../src /I../../src/rml/include /I../../include</AdditionalOptions>
+      <AdditionalOptions>  /c /MT /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBB_BUILD=1 /W4 /I../../src /I../../src/rml/include /I../../include</AdditionalOptions>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
index 0a38cd5..b8f21dd 100644 (file)
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
-      <AdditionalOptions> /c /MDd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc /I.</AdditionalOptions>
+      <AdditionalOptions> /c /MDd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc /I.</AdditionalOptions>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <TargetEnvironment>X64</TargetEnvironment>
     </Midl>
     <ClCompile>
-      <AdditionalOptions> /c /MDd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc /I.</AdditionalOptions>
+      <AdditionalOptions> /c /MDd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc /I.</AdditionalOptions>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <MinimalRebuild>false</MinimalRebuild>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <ClCompile>
-      <AdditionalOptions> /c /MD /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc /I.</AdditionalOptions>
+      <AdditionalOptions> /c /MD /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc /I.</AdditionalOptions>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
       <TargetEnvironment>X64</TargetEnvironment>
     </Midl>
     <ClCompile>
-      <AdditionalOptions> /c /MD /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc /I.</AdditionalOptions>
+      <AdditionalOptions> /c /MD /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc /I.</AdditionalOptions>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug-MT|Win32'">
     <ClCompile>
-      <AdditionalOptions> /c /MTd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc /I.</AdditionalOptions>
+      <AdditionalOptions> /c /MTd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc /I.</AdditionalOptions>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <TargetEnvironment>X64</TargetEnvironment>
     </Midl>
     <ClCompile>
-      <AdditionalOptions> /c /MTd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc /I.</AdditionalOptions>
+      <AdditionalOptions> /c /MTd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc /I.</AdditionalOptions>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <MinimalRebuild>false</MinimalRebuild>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release-MT|Win32'">
     <ClCompile>
-      <AdditionalOptions> /c /MT /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc /I.</AdditionalOptions>
+      <AdditionalOptions> /c /MT /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc /I.</AdditionalOptions>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <TargetEnvironment>X64</TargetEnvironment>
     </Midl>
     <ClCompile>
-      <AdditionalOptions> /c /MT /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc /I.</AdditionalOptions>
+      <AdditionalOptions> /c /MT /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc /I.</AdditionalOptions>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
index 758bb51..23dac2f 100644 (file)
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
-      <AdditionalOptions> /c /MDd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /W4 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc</AdditionalOptions>
+      <AdditionalOptions> /c /MDd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /W4 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc</AdditionalOptions>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <TargetEnvironment>X64</TargetEnvironment>
     </Midl>
     <ClCompile>
-      <AdditionalOptions> /c /MDd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /W4 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc</AdditionalOptions>
+      <AdditionalOptions> /c /MDd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /W4 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc</AdditionalOptions>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <MinimalRebuild>false</MinimalRebuild>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <ClCompile>
-      <AdditionalOptions> /c /MD /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /W4 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc</AdditionalOptions>
+      <AdditionalOptions> /c /MD /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /W4 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc</AdditionalOptions>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExceptionHandling>
       <TargetEnvironment>X64</TargetEnvironment>
     </Midl>
     <ClCompile>
-      <AdditionalOptions> /c /MD /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /W4 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc</AdditionalOptions>
+      <AdditionalOptions> /c /MD /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /W4 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc</AdditionalOptions>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExceptionHandling>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug-MT|Win32'">
     <ClCompile>
-      <AdditionalOptions> /c /MTd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /W4 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc</AdditionalOptions>
+      <AdditionalOptions> /c /MTd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /W4 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc</AdditionalOptions>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <TargetEnvironment>X64</TargetEnvironment>
     </Midl>
     <ClCompile>
-      <AdditionalOptions> /c /MTd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /W4 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc</AdditionalOptions>
+      <AdditionalOptions> /c /MTd /Od /Ob0 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /DTBB_USE_DEBUG /D__TBB_LIB_NAME=tbb_debug.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /W4 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc</AdditionalOptions>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <MinimalRebuild>false</MinimalRebuild>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release-MT|Win32'">
     <ClCompile>
-      <AdditionalOptions> /c /MT /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /W4 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc</AdditionalOptions>
+      <AdditionalOptions> /c /MT /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /W4 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc</AdditionalOptions>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExceptionHandling>
       <TargetEnvironment>X64</TargetEnvironment>
     </Midl>
     <ClCompile>
-      <AdditionalOptions> /c /MT /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /W4 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc</AdditionalOptions>
+      <AdditionalOptions> /c /MT /O2 /Zi /EHsc /GR /Zc:forScope /Zc:wchar_t /DTBB_SUPPRESS_DEPRECATED_MESSAGES=1 /D__TBB_LIB_NAME=tbb.lib /DDO_ITT_NOTIFY /GS /DUSE_WINTHREAD /D_CRT_SECURE_NO_DEPRECATE /D_WIN32_WINNT=0x0502 /W4 /D__TBBMALLOC_BUILD=1 /I../../src /I../../src/rml/include /I../../include /I../../src/tbbmalloc /I../../src/tbbmalloc</AdditionalOptions>
       <AdditionalIncludeDirectories>.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExceptionHandling>
index 8010d5f..de2e66a 100644 (file)
@@ -51,6 +51,11 @@ ifeq (ok,$(call detect_js,/minversion icl 17 4))
     VS2017_SUPPORT = yes
 endif
 
+# ICC 19.0.4 and higher provide support for VS2019
+ifeq (ok,$(call detect_js,/minversion icl 19 4))
+    VS2019_SUPPORT = yes
+endif
+
 ifeq ($(runtime), vc_mt)
     MS_CRT_KEY = /MT$(if $(findstring debug,$(cfg)),d)
 else
@@ -59,7 +64,7 @@ endif
 EH_FLAGS = $(if $(no_exceptions),/EHs-,/EHsc /GR)
 
 ifeq ($(cfg), release)
-    CPLUS_FLAGS = $(MS_CRT_KEY) /O2 /Zi $(EH_FLAGS) /Zc:forScope /Zc:wchar_t /D__TBB_LIB_NAME=$(TBB.LIB)
+    CPLUS_FLAGS = $(MS_CRT_KEY) /O2 /Zi /Qopt-report-embed- $(EH_FLAGS) /Zc:forScope /Zc:wchar_t /D__TBB_LIB_NAME=$(TBB.LIB)
     ASM_FLAGS =
 endif
 ifeq ($(cfg), debug)
@@ -110,7 +115,7 @@ ifeq ($(VCCOMPAT_FLAG),)
         VCCOMPAT_FLAG := $(if $(findstring vc8, $(VCVERSION)),/Qvc8)
 endif
 ifeq ($(VCCOMPAT_FLAG),)
-        VCCOMPAT_FLAG := $(if $(findstring vc_mt, $(VCVERSION)),/Qvc10)
+        VCCOMPAT_FLAG := $(if $(findstring vc_mt, $(VCVERSION)),/Qvc14)
 endif
 ifeq ($(VCCOMPAT_FLAG),)
         VCCOMPAT_FLAG := $(if $(findstring vc9, $(VCVERSION)),/Qvc9)
@@ -131,6 +136,11 @@ ifeq ($(VCCOMPAT_FLAG),)
             VCCOMPAT_FLAG := /Qvc14.1
         endif
     endif
+    ifeq ($(VS2019_SUPPORT),yes)
+        ifneq (,$(findstring vc14.2, $(VCVERSION)))
+            VCCOMPAT_FLAG := /Qvc14.2
+        endif
+    endif
 endif
 ifeq ($(VCCOMPAT_FLAG),)
         $(error VC version not detected correctly: $(VCVERSION) )
index fdb9d5b..0d50e07 100644 (file)
@@ -59,7 +59,11 @@ def_prefix = $(if $(findstring intel64,$(arch)),win64,win32)
 # Target Windows version. Do not increase beyond 0x0502 without prior discussion!
 # Used as the value for macro definition option in windows.cl.inc etc.
 # For tests, we need at least Windows XP SP2 for sake of enabling stack backtraces.
+ifeq (1,$(tbb_cpf))
+_WIN32_WINNT=0x0600
+else
 _WIN32_WINNT=0x0502
+endif
 
 TBB.LST = $(tbb_root)/src/tbb/$(def_prefix)-tbb-export.lst
 TBB.DEF = $(TBB.LST:.lst=.def)
@@ -68,7 +72,7 @@ TBB.LIB = tbb$(CPF_SUFFIX)$(DEBUG_SUFFIX).$(LIBEXT)
 TBB.RES = tbb_resource.res
 # On Windows, we use #pragma comment to set the proper TBB lib to link with.
 # But for cross-configuration testing, need to link explicitly.
-# Tests use this variable to detect dependency on TBB binary, so have to be non-empty. 
+# Tests use this variable to detect dependency on TBB binary, so have to be non-empty.
 LINK_TBB.LIB = $(if $(crosstest),$(TBB.LIB),$(DEFINE_KEY)__TBB_IMPLICITLY_LINKED)
 TBB.MANIFEST =
 ifneq ($(filter vc8 vc9,$(runtime)),)
index 3b16c37..52cc46d 100644 (file)
@@ -30,7 +30,7 @@ Visit our `forum <https://software.intel.com/en-us/forums/intel-threading-buildi
 Release Notes
 -------------
 * Minimum supported CMake version: ``3.0.0``.
-* TBB versioning via `find_package <https://cmake.org/cmake/help/latest/command/find_package.html>`_ has the following format: ``find_package(TBB <major>.<minor>.<interface> ...)``. TBB interface version can also be obtained in the customer project via the ``TBB_INTERFACE_VERSION`` variable.
+* TBB versioning via `find_package <https://cmake.org/cmake/help/latest/command/find_package.html>`_ has the following format: ``find_package(TBB <major>.<minor> ...)``.
 
 Use cases of TBB integration into CMake-aware projects
 ------------------------------------------------------------
@@ -206,7 +206,7 @@ Variables set during TBB configuration:
 ``TBB_<component>_FOUND``  specific TBB component is found
 ``TBB_IMPORTED_TARGETS``   all created TBB imported targets
 ``TBB_VERSION``            TBB version (format: ``<major>.<minor>``)
-``TBB_INTERFACE_VERSION``  TBB interface version
+``TBB_INTERFACE_VERSION``  TBB interface version (can be empty, see below for details)
 =========================  ================================================
 
 TBBInstallConfig
@@ -219,7 +219,7 @@ Provides the following functions:
  .. code:: cmake
 
   tbb_install_config(INSTALL_DIR <install_dir> SYSTEM_NAME Linux|Darwin|Windows
-                     [TBB_VERSION <major>.<minor>.<interface>|TBB_VERSION_FILE <version_file>]
+                     [TBB_VERSION <major>.<minor>|TBB_VERSION_FILE <version_file>]
                      [LIB_REL_PATH <lib_rel_path> INC_REL_PATH <inc_rel_path>]
                      [LIB_PATH <lib_path> INC_PATH <inc_path>])``
 
@@ -241,8 +241,8 @@ The use case is applicable for package maintainers who create own TBB packages a
 ``SYSTEM_NAME Linux|Darwin|Windows``         OS name to generate config files for
 ``TBB_VERSION_FILE <version_file>``          Path to ``tbb_stddef.h`` to parse version from and
                                              write it to TBBConfigVersion.cmake
-``TBB_VERSION <major>.<minor>.<interface>``  Directly specified TBB version;
-                                             alternative to ``TBB_VERSION_FILE`` parameter
+``TBB_VERSION <major>.<minor>``              Directly specified TBB version; alternative to ``TBB_VERSION_FILE`` parameter;
+                                             ``TBB_INTERFACE_VERSION`` is set to empty value in this case
 ``LIB_REL_PATH <lib_rel_path>``              Relative path to TBB binaries (.lib files on Windows), default: ``../../../lib``
 ``BIN_REL_PATH <bin_rel_path>``              Relative path to TBB DLLs, default: ``../../../bin`` (applicable for Windows only)
 ``INC_REL_PATH <inc_rel_path>``              Relative path to TBB headers, default: ``../../../include``
index b6ed34b..a5fa7e8 100644 (file)
@@ -83,8 +83,8 @@ function(tbb_install_config)
         file(READ ${tbb_version_file} _tbb_stddef)
         string(REGEX REPLACE ".*#define TBB_VERSION_MAJOR ([0-9]+).*" "\\1" _tbb_ver_major "${_tbb_stddef}")
         string(REGEX REPLACE ".*#define TBB_VERSION_MINOR ([0-9]+).*" "\\1" _tbb_ver_minor "${_tbb_stddef}")
-        string(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" _tbb_ver_interface "${_tbb_stddef}")
-        set(TBB_VERSION "${_tbb_ver_major}.${_tbb_ver_minor}.${_tbb_ver_interface}")
+        string(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" TBB_INTERFACE_VERSION "${_tbb_stddef}")
+        set(TBB_VERSION "${_tbb_ver_major}.${_tbb_ver_minor}")
     endif()
     # ------
 
index bbcb990..b5b7a12 100644 (file)
@@ -56,33 +56,16 @@ function(tbb_make_config)
         set(TBB_LIB_EXT "so.2")
 
         # Note: multiline variable
-        set(TBB_CHOOSE_COMPILER_SUBDIR "if (CMAKE_CXX_COMPILER_LOADED)
-    set(_tbb_compiler_id \${CMAKE_CXX_COMPILER_ID})
-    set(_tbb_compiler_ver \${CMAKE_CXX_COMPILER_VERSION})
-elseif (CMAKE_C_COMPILER_LOADED)
-    set(_tbb_compiler_id \${CMAKE_C_COMPILER_ID})
-    set(_tbb_compiler_ver \${CMAKE_C_COMPILER_VERSION})
-endif()
+        set(TBB_CHOOSE_COMPILER_SUBDIR "set(_tbb_compiler_subdir gcc4.8)
 
 # For non-GCC compilers try to find version of system GCC to choose right compiler subdirectory.
-if (NOT _tbb_compiler_id STREQUAL \"GNU\")
-    execute_process(COMMAND gcc --version OUTPUT_VARIABLE _tbb_gcc_ver_output ERROR_QUIET)
-    string(REGEX REPLACE \".*gcc.*([0-9]+\\\\.[0-9]+)\\\\.[0-9]+.*\" \"\\\\1\" _tbb_compiler_ver \"\${_tbb_gcc_ver_output}\")
-    if (NOT _tbb_compiler_ver)
+if (NOT CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\" AND NOT CMAKE_C_COMPILER_ID STREQUAL \"GNU\")
+    find_program(_gcc_executable gcc)
+    if (NOT _gcc_executable)
         message(FATAL_ERROR \"This Intel TBB package is intended to be used only in environment with available 'gcc'\")
     endif()
-    unset(_tbb_gcc_ver_output)
-endif()
-
-set(_tbb_compiler_subdir gcc4.1)
-foreach (_tbb_gcc_version 4.1 4.4 4.7)
-    if (NOT _tbb_compiler_ver VERSION_LESS \${_tbb_gcc_version})
-        set(_tbb_compiler_subdir gcc\${_tbb_gcc_version})
-    endif()
-endforeach()
-
-unset(_tbb_compiler_id)
-unset(_tbb_compiler_ver)")
+    unset(_gcc_executable)
+endif()")
 
     elseif (tbb_system_name STREQUAL "Windows")
         set(TBB_SHARED_LIB_DIR "bin")
@@ -96,23 +79,14 @@ unset(_tbb_compiler_ver)")
     message(FATAL_ERROR \"This Intel TBB package is intended to be used only in the project with MSVC\")
 endif()
 
-# Detect the most relevant MSVC subdirectory
-set(_tbb_msvc_1700_subdir vc11)
-set(_tbb_msvc_1800_subdir vc12)
-set(_tbb_msvc_1900_subdir vc14)
-set(_tbb_msvc_ver \${MSVC_VERSION})
-if (MSVC_VERSION VERSION_LESS 1700)
-    message(FATAL_ERROR \"This Intel TBB package is intended to be used only in the project with MSVC version 1700 (vc11) or higher\")
-elseif (MSVC_VERSION VERSION_GREATER 1900)
-    set(_tbb_msvc_ver 1900)
+if (MSVC_VERSION VERSION_LESS 1900)
+    message(FATAL_ERROR \"This Intel TBB package is intended to be used only in the project with MSVC version 1900 (vc14) or higher\")
 endif()
-set(_tbb_compiler_subdir \${_tbb_msvc_\${_tbb_msvc_ver}_subdir})
-unset(_tbb_msvc_1700_subdir)
-unset(_tbb_msvc_1800_subdir)
-unset(_tbb_msvc_1900_subdir)
+
+set(_tbb_compiler_subdir vc14)
 
 if (WINDOWS_STORE)
-    set(_tbb_compiler_subdir \${_tbb_compiler_subdir}_ui)
+    set(_tbb_compiler_subdir \${_tbb_compiler_subdir}_uwp)
 endif()")
 
         if (tbb_MK_CONFIG_FOR_SOURCE)
@@ -153,7 +127,7 @@ endif()")
     string(REGEX REPLACE ".*#define TBB_VERSION_MAJOR ([0-9]+).*" "\\1" _tbb_ver_major "${_tbb_stddef}")
     string(REGEX REPLACE ".*#define TBB_VERSION_MINOR ([0-9]+).*" "\\1" _tbb_ver_minor "${_tbb_stddef}")
     string(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" TBB_INTERFACE_VERSION "${_tbb_stddef}")
-    set(TBB_VERSION "${_tbb_ver_major}.${_tbb_ver_minor}.${TBB_INTERFACE_VERSION}")
+    set(TBB_VERSION "${_tbb_ver_major}.${_tbb_ver_minor}")
 
     if (tbb_MK_CONFIG_FOR_SOURCE)
         set(TBB_CHOOSE_ARCH_AND_COMPILER "")
index 84e2539..d5f2eab 100644 (file)
 # limitations under the License.
 
 # It defines the following variables:
-#     TBB_tbb_FOUND
-#     TBB_tbbmalloc_FOUND
-#     TBB_tbbmalloc_proxy_FOUND
+#     TBB_<component>_FOUND
 #     TBB_IMPORTED_TARGETS
 #
 # TBBConfigVersion.cmake defines TBB_VERSION
 #
 # Initialize to default values
-if (NOT TBB_tbb_FOUND)
-    set(TBB_tbb_FOUND 0)
-endif()
-if (NOT TBB_tbbmalloc_FOUND)
-    set(TBB_tbbmalloc_FOUND 0)
-endif()
-if (NOT TBB_tbbmalloc_proxy_FOUND)
-    set(TBB_tbbmalloc_proxy_FOUND 0)
-endif()
 if (NOT TBB_IMPORTED_TARGETS)
     set(TBB_IMPORTED_TARGETS "")
 endif()
@@ -41,6 +30,8 @@ if (NOT TBB_FIND_COMPONENTS)
     endforeach()
 endif()
 
+set(TBB_INTERFACE_VERSION @TBB_INTERFACE_VERSION@)
+
 # Add components with internal dependencies: tbbmalloc_proxy -> tbbmalloc
 list(FIND TBB_FIND_COMPONENTS tbbmalloc_proxy _tbbmalloc_proxy_ix)
 if (NOT _tbbmalloc_proxy_ix EQUAL -1)
@@ -54,6 +45,8 @@ endif()
 unset(_tbbmalloc_proxy_ix)
 
 foreach (_tbb_component ${TBB_FIND_COMPONENTS})
+    set(TBB_${_tbb_component}_FOUND 0)
+
     set(_tbb_release_lib "${CMAKE_CURRENT_LIST_DIR}/@TBB_LIB_REL_PATH@/@TBB_LIB_PREFIX@${_tbb_component}.@TBB_LIB_EXT@")
     set(_tbb_debug_lib "${CMAKE_CURRENT_LIST_DIR}/@TBB_LIB_REL_PATH@/@TBB_LIB_PREFIX@${_tbb_component}_debug.@TBB_LIB_EXT@")
 
@@ -79,17 +72,17 @@ foreach (_tbb_component ${TBB_FIND_COMPONENTS})
             if (_tbb_component STREQUAL tbbmalloc_proxy)
                 set_target_properties(TBB::tbbmalloc_proxy PROPERTIES INTERFACE_LINK_LIBRARIES TBB::tbbmalloc)
             endif()
-            list(APPEND TBB_IMPORTED_TARGETS TBB::${_tbb_component})
         else()
             message(STATUS "Using previously found TBB::${_tbb_component}")
         endif()
+        list(APPEND TBB_IMPORTED_TARGETS TBB::${_tbb_component})
         set(TBB_${_tbb_component}_FOUND 1)
     elseif (TBB_FIND_REQUIRED AND TBB_FIND_REQUIRED_${_tbb_component})
         message(STATUS "Missed required Intel TBB component: ${_tbb_component}")
         message(STATUS "  one or both of:\n   ${_tbb_release_lib}\n    ${_tbb_debug_lib}\n   files must exist.")
         set(TBB_FOUND FALSE)
-        set(TBB_${_tbb_component}_FOUND 0)
     endif()
 endforeach()
+list(REMOVE_DUPLICATES TBB_IMPORTED_TARGETS)
 unset(_tbb_release_lib)
 unset(_tbb_debug_lib)
index 40528c6..c3d7ee4 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# TBB_FOUND should not be set explicitly. It is defined automatically by CMake.
-# Handling of TBB_VERSION is in TBBConfigVersion.cmake.
+# It defines the following variables:
+#     TBB_<component>_FOUND
+#     TBB_IMPORTED_TARGETS
+#
+# TBBConfigVersion.cmake defines TBB_VERSION
+#
+# Initialize to default values
+if (NOT TBB_IMPORTED_TARGETS)
+    set(TBB_IMPORTED_TARGETS "")
+endif()
 
 if (NOT TBB_FIND_COMPONENTS)
     set(TBB_FIND_COMPONENTS "@TBB_DEFAULT_COMPONENTS@")
@@ -38,39 +46,45 @@ get_filename_component(_tbb_root "${CMAKE_CURRENT_LIST_FILE}" PATH)
 get_filename_component(_tbb_root "${_tbb_root}" PATH)
 @TBB_CHOOSE_ARCH_AND_COMPILER@
 foreach (_tbb_component ${TBB_FIND_COMPONENTS})
+    set(TBB_${_tbb_component}_FOUND 0)
+
     set(_tbb_release_lib "@TBB_RELEASE_LIB_PATH@/@TBB_LIB_PREFIX@${_tbb_component}.@TBB_LIB_EXT@")
     set(_tbb_debug_lib "@TBB_DEBUG_LIB_PATH@/@TBB_LIB_PREFIX@${_tbb_component}_debug.@TBB_LIB_EXT@")
 
     if (EXISTS "${_tbb_release_lib}" OR EXISTS "${_tbb_debug_lib}")
-        add_library(TBB::${_tbb_component} SHARED IMPORTED)
-        set_target_properties(TBB::${_tbb_component} PROPERTIES
-                              INTERFACE_INCLUDE_DIRECTORIES "${_tbb_root}/include"@TBB_COMPILE_DEFINITIONS@)
-
-        if (EXISTS "${_tbb_release_lib}")
+        if (NOT TARGET TBB::${_tbb_component})
+            add_library(TBB::${_tbb_component} SHARED IMPORTED)
             set_target_properties(TBB::${_tbb_component} PROPERTIES
-                                  IMPORTED_LOCATION_RELEASE "${_tbb_release_lib}"@TBB_IMPLIB_RELEASE@)
-            set_property(TARGET TBB::${_tbb_component} APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
-        endif()
+                                INTERFACE_INCLUDE_DIRECTORIES "${_tbb_root}/include"@TBB_COMPILE_DEFINITIONS@)
 
-        if (EXISTS "${_tbb_debug_lib}")
-            set_target_properties(TBB::${_tbb_component} PROPERTIES
-                                  IMPORTED_LOCATION_DEBUG "${_tbb_debug_lib}"@TBB_IMPLIB_DEBUG@)
-            set_property(TARGET TBB::${_tbb_component} APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
-        endif()
+            if (EXISTS "${_tbb_release_lib}")
+                set_target_properties(TBB::${_tbb_component} PROPERTIES
+                                    IMPORTED_LOCATION_RELEASE "${_tbb_release_lib}"@TBB_IMPLIB_RELEASE@)
+                set_property(TARGET TBB::${_tbb_component} APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
+            endif()
 
-        # Add internal dependencies for imported targets: TBB::tbbmalloc_proxy -> TBB::tbbmalloc
-        if (_tbb_component STREQUAL tbbmalloc_proxy)
-            set_target_properties(TBB::tbbmalloc_proxy PROPERTIES INTERFACE_LINK_LIBRARIES TBB::tbbmalloc)
-        endif()
+            if (EXISTS "${_tbb_debug_lib}")
+                set_target_properties(TBB::${_tbb_component} PROPERTIES
+                                    IMPORTED_LOCATION_DEBUG "${_tbb_debug_lib}"@TBB_IMPLIB_DEBUG@)
+                set_property(TARGET TBB::${_tbb_component} APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
+            endif()
 
+            # Add internal dependencies for imported targets: TBB::tbbmalloc_proxy -> TBB::tbbmalloc
+            if (_tbb_component STREQUAL tbbmalloc_proxy)
+                set_target_properties(TBB::tbbmalloc_proxy PROPERTIES INTERFACE_LINK_LIBRARIES TBB::tbbmalloc)
+            endif()
+        else()
+            message(STATUS "Using previously found TBB::${_tbb_component}")
+        endif()
         list(APPEND TBB_IMPORTED_TARGETS TBB::${_tbb_component})
         set(TBB_${_tbb_component}_FOUND 1)
     elseif (TBB_FIND_REQUIRED AND TBB_FIND_REQUIRED_${_tbb_component})
         message(STATUS "Missed required Intel TBB component: ${_tbb_component}")
+        message(STATUS "  one or both of:\n   ${_tbb_release_lib}\n    ${_tbb_debug_lib}\n   files must exist.")
         set(TBB_FOUND FALSE)
-        set(TBB_${_tbb_component}_FOUND 0)
     endif()
 endforeach()
+list(REMOVE_DUPLICATES TBB_IMPORTED_TARGETS)
 @TBB_UNSET_ADDITIONAL_VARIABLES@
 unset(_tbbmalloc_proxy_ix)
 unset(_tbbmalloc_ix)
index 8aa56e7..7714846 100644 (file)
@@ -44,21 +44,24 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:   release test
 
 release: *.cpp
 ifeq ($(offload),)
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o sub_string_finder sub_string_finder.cpp $(TBBLIB) $(LIBS)
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o sub_string_finder_pretty sub_string_finder_pretty.cpp $(TBBLIB) $(LIBS)
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o sub_string_finder sub_string_finder.cpp $(TBBLIB) $(LIBS) $(CXX0XFLAGS)
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o sub_string_finder_pretty sub_string_finder_pretty.cpp $(TBBLIB) $(LIBS) $(CXX0XFLAGS)
 endif
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o sub_string_finder_extended sub_string_finder_extended.cpp $(TBBLIB) $(LIBS)
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o sub_string_finder_extended sub_string_finder_extended.cpp $(TBBLIB) $(LIBS) $(CXX0XFLAGS)
 
 debug: *.cpp
 ifeq ($(offload),)
-       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o sub_string_finder sub_string_finder.cpp $(TBBLIB_DEBUG) $(LIBS)
-       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o sub_string_finder_pretty sub_string_finder_pretty.cpp  $(TBBLIB_DEBUG) $(LIBS)
+       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o sub_string_finder sub_string_finder.cpp $(TBBLIB_DEBUG) $(LIBS) $(CXX0XFLAGS)
+       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o sub_string_finder_pretty sub_string_finder_pretty.cpp  $(TBBLIB_DEBUG) $(LIBS) $(CXX0XFLAGS)
 endif
-       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o sub_string_finder_extended sub_string_finder_extended.cpp $(TBBLIB_DEBUG) $(LIBS)
+       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o sub_string_finder_extended sub_string_finder_extended.cpp $(TBBLIB_DEBUG) $(LIBS) $(CXX0XFLAGS)
 
 clean:
        $(RM) sub_string_finder sub_string_finder_extended sub_string_finder_pretty *.o *.d
index 8926181..b3397cb 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index fad4043..0ff7e15 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index bb3e84b..fced1c2 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index dd1339b..8c07b3e 100644 (file)
@@ -37,6 +37,8 @@ override CXXFLAGS += $(CXX_STD_FLAGS)
 # give stdver priotity over autodetection
 ifneq (,$(stdver))
     CXX0XFLAGS=-std=$(stdver)
+else
+    include common/examples-common.inc
 endif
 # empty CXX0XFLAGS exported as well, to have control over C++ autodetection
 export CXX0XFLAGS
index c1ed9d7..1c35145 100644 (file)
@@ -41,8 +41,6 @@ if ("%TBBROOT%") == ("") set TBBROOT=%~d0%~p0..\..\
 
 :: Getting vs folders in case vc_mt binaries are not provided
 :: ordered from oldest to newest, so we end with newest available version
-if ("%VS110COMNTOOLS%") NEQ ("") set vc_dir=vc11
-if ("%VS120COMNTOOLS%") NEQ ("") set vc_dir=vc12
 if ("%VS140COMNTOOLS%") NEQ ("") set vc_dir=vc14
 :: To use Microsoft* Visual Studio* 2017 IDE, make sure the variable VS150COMNTOOLS is set in your IDE instance.
 :: If it is not, try running Microsoft Visual Studio 2017 from Microsoft* Developer Command Prompt* for VS 2017.
index c0257a7..f81c18c 100644 (file)
 
 # detect if a compiler can support C++11
 # If CXX0XFLAGS already set, do not change it
-ifneq (,$(findstring $(CXX), icc icpc clang++))
+ifneq (,$(findstring icc, $(CXX))$(findstring icpc, $(CXX))$(findstring clang++, $(CXX)))
     # every supported icc or clang is OK
-    CXX0XFLAGS ?= -std=c++0x
+    CXX0XFLAGS ?= -std=c++11
 else
-    ifneq (,$(findstring $(CXX), g++ gcc))
+    ifneq (,$(findstring g++, $(CXX))$(findstring gcc, $(CXX)))
         ifneq (, $(strip $(shell $(CXX) -v 2>&1 | grep "clang-")))
             # This is clang actually,
             # every supported clang is OK
-            CXX0XFLAGS ?= -std=c++0x
+            CXX0XFLAGS ?= -std=c++11
         else
             # support of lambda started GCC 4.5
-            ifneq (, $(strip $(shell g++ -dumpfullversion -dumpversion | egrep "^(4\.[5-9]|[5-9])")))
-               CXX0XFLAGS ?= -std=c++0x
+            ifneq (, $(strip $(shell g++ -dumpfullversion -dumpversion | egrep "^(4\.[5-9]|[5-9]|1[0-9])")))
+               CXX0XFLAGS ?= -std=c++11
             endif
         endif
     endif
index 2535857..7de00c9 100644 (file)
                .circ {
                        list-style-type:circle
                }
-               
+
                .single {
                        padding: 0 0.5em;
                }
-               
+
                /* ------------------------------------------------- */
                /* Table styles                                      */
                table{
                }
                th{
                        border:1px #dddddd solid;
-                       padding-top:2px;                 
+                       padding-top:2px;
                        padding-bottom:0px;
-                       padding-right:3px;               
+                       padding-right:3px;
                        padding-left:3px;
                }
                td{
                        padding-right:5px;
                        vertical-align:top;
                }
-               
+
                .specs {
                        border-collapse:collapse;
                }
                        padding: 0 0.2em 0.2em;
                        text-align: center;
                }
-               .specs td tr:last-child td, 
+               .specs td tr:last-child td,
                .specs td tr:last-child th {
                        padding: 0 0.2em;
                }
        <title>Intel&reg; Threading Building Blocks. Common source code for samples</title>
 </head>
 <body>
-       
+
        <div id="banner">
                <img class="logo" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEMAAAAsCAYAAAA+aAX8AAAAAXNSR0IArs4c6QAAAARnQU1BAACx
                                jwv8YQUAAAAJcEhZcwAALiIAAC4iAari3ZIAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVh
                                9Or1LzUmVVz+HJXDAAAAAElFTkSuQmCC">
                <h1 class="title">Intel&reg; Threading Building Blocks.<br>Common source code for samples</h1>
        </div>
-       
+
        <p>
                This directory contains common code that is used in the Intel&reg; Threading Building Blocks (Intel&reg; TBB) samples.
                <br>
                                        </ul>
                                        See the examples that use the GUI
                                        (<a href="../graph/stereo/readme.html">stereo</a>,
-                                       <a href="../parallel_for/tachyon/readme.html">tachyon</a>, 
+                                       <a href="../parallel_for/tachyon/readme.html">tachyon</a>,
                                        <a href="../parallel_for/seismic/readme.html">seismic</a>,
                                        <a href="../task_arena/fractal/readme.html">fractal</a>)
                                        for more details.
                        <p>
                                Most Intel TBB examples allow to specify <i>n-of-threads</i>, the set of thread numbers that should be used to run an example.
                                <br>Usually, it is a range of the form <i>low[:high[:(+|*|#)S]]</i>, where <i>low</i> and optional <i>high</i>
-                               are non-negative integers or 'auto' for the default choice, and optional step expression <i>(+|*|#)S</i> 
+                               are non-negative integers or 'auto' for the default choice, and optional step expression <i>(+|*|#)S</i>
                                specifies how thread numbers are chosen within the range:
                                <ul>
                                        <li>With <i>+/*</i>, the previous number is incremented/multiplied by <i>S</i>.
                                        E.g., expression '12:16:+1' means 12,13,14,15,16 threads, and '1:16:*2' means 1,2,4,8,16 threads.
                                        <li>With <i>#</i>, <i>S</i> is the desired number of steps between any subsequent powers of 2;
-                                       it must be a power of 2 on its own, with most meaningful values being 2, 4, and 8. 
+                                       it must be a power of 2 on its own, with most meaningful values being 2, 4, and 8.
                                        For a given number of threads, the actual step value is computed as the quotient
                                        of the nearest smaller power of 2 divided by the number of steps, but is at least 1.
                                        E.g., '1:32:#4' means 1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32 threads;
                                        note the step doubling at 8 and 16 to keep 4 steps between powers of 2.
                                </ul>
                                A default value for the number of threads can be customized in an example. If not customized, it is '1:auto:#4'.
-                               The 'auto' parameter is substituted with a value returned by a specified function, which typically is
-                               <code>tbb::task_scheduler_init::default_num_threads()</code>.
+                               The 'auto' parameter is substituted with a value returned by a specified function
+                               (this function is typically <code>utility::get_default_num_threads()</code>, which returns a copy of
+                               constant that was initialized with <code>tbb::global_control::active_value(tbb::global_control::max_allowed_parallelism)</code>
+                               at the start of the program).
                        </p>
                </div>
        </div>
                <div class="show-hide">
                        <p>
                                Intel and the Intel logo are trademarks of Intel Corporation in the U.S. and/or other countries.
-                               <br>* Other names and brands may be claimed as the property of others. 
+                               <br>* Other names and brands may be claimed as the property of others.
                                <br>&copy; 2019, Intel Corporation
                        </p>
                </div>
diff --git a/examples/common/utility/get_default_num_threads.h b/examples/common/utility/get_default_num_threads.h
new file mode 100644 (file)
index 0000000..6af6d97
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+    Copyright (c) 2005-2019 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.
+*/
+
+#ifndef GET_DEFAULT_NUM_THREADS_H_
+#define GET_DEFAULT_NUM_THREADS_H_
+
+#include "tbb/global_control.h"
+
+namespace utility {
+    inline int get_default_num_threads() {
+        #if __TBB_MIC_OFFLOAD
+            #pragma offload target(mic) out(default_num_threads)
+        #endif // __TBB_MIC_OFFLOAD
+        static size_t default_num_threads = tbb::global_control::active_value(tbb::global_control::max_allowed_parallelism);
+        return static_cast<int>(default_num_threads);
+    }
+}
+
+#endif /* GET_DEFAULT_NUM_THREADS_H_ */
index ab55007..f146f9d 100644 (file)
@@ -99,9 +99,10 @@ namespace utility{
         template <typename type>
         class type_impl : public type_base {
         private:
+            type_impl(const type_impl& src) : type_base(src.name, src.description), target(src.target),
+                                              validating_function(src.validating_function) {}
             type_impl& operator=(const type_impl&);
             typedef bool(*validating_function_type)(const type&);
-        private:
             type & target;
             validating_function_type validating_function;
         public:
@@ -419,10 +420,10 @@ namespace utility{
         int first; // 0<=first (0 can be used as a special value)
         int last;  // first<=last
 
-        internal::thread_range_step step;
+               ::utility::internal::thread_range_step step;
 
         thread_number_range( int (*auto_number_of_threads_)(),int low_=1, int high_=-1
-                , internal::thread_range_step step_ =  internal::thread_range_step(internal::step_function_power2_ladder,4)
+                , ::utility::internal::thread_range_step step_ = ::utility::internal::thread_range_step(::utility::internal::step_function_power2_ladder,4)
         )
             : auto_number_of_threads(auto_number_of_threads_), first(low_), last((high_>-1) ? high_ : auto_number_of_threads_())
               ,step(step_)
@@ -484,7 +485,7 @@ namespace utility{
                                                 "\n\twhere low and optional high are non-negative integers or 'auto' for the default choice,"
                                                 "\n\tand optional step expression specifies how thread numbers are chosen within the range."
                                                 "\n\tSee examples/common/index.html for detailed description."
-   ;
+    ;
 
     inline void report_elapsed_time(double seconds){
         std::cout<<"elapsed time : "<<seconds<<" seconds"<<std::endl;
index 069aab7..194c86b 100644 (file)
@@ -34,13 +34,16 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:   release test
 
 release: *.cpp
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS)
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS) $(CXX0XFLAGS)
 
 debug: *.cpp
-       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS)
+       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS) $(CXX0XFLAGS)
 
 clean:
        $(RM) $(PROG) *.o *.d
index 17851c0..e9b516d 100644 (file)
 #include "tbb/blocked_range.h"
 #include "tbb/parallel_for.h"
 #include "tbb/tick_count.h"
-#include "tbb/task_scheduler_init.h"
 #include "tbb/tbb_allocator.h"
+#include "tbb/global_control.h"
 #include "../../common/utility/utility.h"
+#include "../../common/utility/get_default_num_threads.h"
 
 
 //! String type with scalable allocator.
-/** On platforms with non-scalable default memory allocators, the example scales 
+/** On platforms with non-scalable default memory allocators, the example scales
     better if the string allocator is changed to tbb::tbb_allocator<char>. */
 typedef std::basic_string<char,std::char_traits<char>,tbb::tbb_allocator<char> > MyString;
 
@@ -185,7 +186,7 @@ int main( int argc, char* argv[] ) {
         //! Working threads count
         // The 1st argument is the function to obtain 'auto' value; the 2nd is the default value
         // The example interprets 0 threads as "run serially, then fully subscribed"
-        utility::thread_number_range threads(tbb::task_scheduler_init::default_num_threads,0);
+        utility::thread_number_range threads(utility::get_default_num_threads,0);
 
         utility::parse_cli_arguments(argc,argv,
             utility::cli_argument_pack()
@@ -204,18 +205,18 @@ int main( int argc, char* argv[] ) {
         if ( threads.first ) {
             for(int p = threads.first;  p <= threads.last; p = threads.step(p)) {
                 if ( !silent ) printf("threads = %d  ", p );
-                task_scheduler_init init( p );
+                global_control c(tbb::global_control::max_allowed_parallelism, p);
                 CountOccurrences( p );
             }
         } else { // Number of threads wasn't set explicitly. Run serial and parallel version
             { // serial run
                 if ( !silent ) printf("serial run   ");
-                task_scheduler_init init_serial(1);
+                global_control c(tbb::global_control::max_allowed_parallelism, 1);
                 CountOccurrences(1);
             }
             { // parallel run (number of threads is selected automatically)
                 if ( !silent ) printf("parallel run ");
-                task_scheduler_init init_parallel;
+                global_control c(tbb::global_control::max_allowed_parallelism, utility::get_default_num_threads());
                 CountOccurrences(0);
             }
         }
index 7e29463..0f050eb 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index 120146d..966ca5f 100644 (file)
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++11";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++11";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
index 5028ce6..b5b5cb5 100644 (file)
@@ -23,9 +23,6 @@ ifneq (,$(shell which icc 2>/dev/null))
     CXX=icpc
 endif
 
-# autodetect C++11 support
-include ../../common/examples-common.inc
-
 ifeq ($(shell uname), Linux)
 ifeq ($(target), android)
 LIBS+= --sysroot=$(SYSROOT)
@@ -37,6 +34,8 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+include ../../common/examples-common.inc
+
 all:    release test
 
 release: *.cpp
index 22aed9c..0d2ac6c 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index bbdfcf7..ec45ebf 100644 (file)
 
 #include <cstdio>
 #include <vector>
+#include <atomic>
 #include <math.h>
 
-#include "tbb/atomic.h"
 #include "tbb/tick_count.h"
-#include "tbb/task_scheduler_init.h"
 #include "tbb/task_group.h"
 #include "tbb/concurrent_priority_queue.h"
 #include "tbb/spin_mutex.h"
 #include "tbb/parallel_for.h"
 #include "tbb/blocked_range.h"
+#include "tbb/global_control.h"
 #include "../../common/utility/utility.h"
 #include "../../common/utility/fast_random.h"
+#include "../../common/utility/get_default_num_threads.h"
 
 #if defined(_MSC_VER) && defined(_Wp64)
     // Workaround for overzealous compiler warnings in /Wp64 mode
@@ -74,24 +75,24 @@ typedef size_t vertex_id;
 typedef std::pair<vertex_id,double> vertex_rec;
 typedef vector<vector<vertex_id> > edge_set;
 
-bool verbose = false;          // prints bin details and other diagnostics to screen
-bool silent = false;           // suppress all output except for time
-size_t N = 1000;               // number of vertices
-size_t src = 0;                // start of path
-size_t dst = N-1;              // end of path
-double INF=100000.0;           // infinity
-size_t grainsize = 16;         // number of vertices per task on average
-size_t max_spawn;              // max tasks to spawn
-tbb::atomic<size_t> num_spawn;      // number of active tasks
-
-point_set vertices;            // vertices
-edge_set edges;                // edges
-vector<vertex_id> predecessor; // for recreating path from src to dst
-
-vector<double> f_distance;     // estimated distances at particular vertex
-vector<double> g_distance;     // current shortest distances from src vertex
-spin_mutex    *locks;          // a lock for each vertex
-task_group *sp_group;          // task group for tasks executing sub-problems
+bool verbose = false;                       // prints bin details and other diagnostics to screen
+bool silent = false;                        // suppress all output except for time
+size_t N = 1000;                            // number of vertices
+size_t src = 0;                             // start of path
+size_t dst = N-1;                           // end of path
+double INF=100000.0;                        // infinity
+size_t grainsize = 16;                      // number of vertices per task on average
+size_t max_spawn;                           // max tasks to spawn
+std::atomic<size_t> num_spawn;              // number of active tasks
+
+point_set vertices;                         // vertices
+edge_set edges;                             // edges
+vector<vertex_id> predecessor;              // for recreating path from src to dst
+
+vector<double> f_distance;                  // estimated distances at particular vertex
+vector<double> g_distance;                  // current shortest distances from src vertex
+spin_mutex    *locks;                       // a lock for each vertex
+task_group *sp_group;                       // task group for tasks executing sub-problems
 
 class compare_f {
 public:
@@ -200,13 +201,6 @@ void print_path() {
     else if (!silent) printf(" %5.1f\n", path_length);
 }
 
-int get_default_num_threads() {
-    static int threads = 0;
-    if (threads == 0)
-        threads = tbb::task_scheduler_init::default_num_threads();
-    return threads;
-}
-
 #if !__TBB_CPP11_LAMBDAS_PRESENT
 class gen_vertices {
 public:
@@ -246,7 +240,7 @@ public:
 #endif
 
 void InitializeGraph() {
-    task_scheduler_init init(get_default_num_threads());
+    global_control c(tbb::global_control::max_allowed_parallelism, utility::get_default_num_threads());
     vertices.resize(N);
     edges.resize(N);
     predecessor.resize(N);
@@ -294,7 +288,7 @@ void ReleaseGraph() {
 }
 
 void ResetGraph() {
-    task_scheduler_init init(get_default_num_threads());
+    global_control c(tbb::global_control::max_allowed_parallelism, utility::get_default_num_threads());
 #if __TBB_CPP11_LAMBDAS_PRESENT
     parallel_for(blocked_range<size_t>(0,N),
                  [&](blocked_range<size_t>& r) {
@@ -310,7 +304,7 @@ void ResetGraph() {
 
 int main(int argc, char *argv[]) {
     try {
-        utility::thread_number_range threads(get_default_num_threads);
+        utility::thread_number_range threads(utility::get_default_num_threads);
         utility::parse_cli_arguments(argc, argv,
                                      utility::cli_argument_pack()
                                      //"-h" option for displaying help is present implicitly
@@ -339,7 +333,7 @@ int main(int argc, char *argv[]) {
         InitializeGraph();
         for (int n_thr=threads.first; n_thr<=threads.last; n_thr=threads.step(n_thr)) {
             ResetGraph();
-            task_scheduler_init init(n_thr);
+            global_control c(tbb::global_control::max_allowed_parallelism, n_thr);
             t0 = tick_count::now();
             shortpath();
             t1 = tick_count::now();
index 1af55b1..6b2f38d 100644 (file)
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                                CLANG_WARN_COMMA = YES;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                                CLANG_WARN_COMMA = YES;
index d9d11f7..cc98a07 100644 (file)
@@ -34,13 +34,16 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:    release test
 
 release: *.cpp
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS)
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS) $(CXX0XFLAGS)
 
 debug: *.cpp
-       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS)
+       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS)  $(CXX0XFLAGS)
 
 profile: override CXXFLAGS += -DTBB_USE_THREADING_TOOLS -g
 profile: release
index d089ab0..79c4bd4 100644 (file)
 #include <iostream>
 #include <cmath>
 #include <vector>
-#include "tbb/atomic.h"
-#include "tbb/task_scheduler_init.h"
+#include <atomic>
 #include "tbb/tick_count.h"
 #include "tbb/flow_graph.h"
+#include "tbb/global_control.h"
 #include "../../common/utility/utility.h"
+#include "../../common/utility/get_default_num_threads.h"
 
 using tbb::tick_count;
-using tbb::task_scheduler_init;
 using namespace tbb::flow;
 
 typedef size_t size_type;             // to represent non-zero indices, capacities, etc.
@@ -62,9 +62,9 @@ size_type min_B;                 // lower bound on the optimal number of bins
 size_type B;                     // the answer, i.e. number of bins used by the algorithm
 size_type *input_array;          // stores randomly generated input values
 value_type item_sum;             // sum of all randomly generated input values
-tbb::atomic<value_type> packed_sum;   // sum of all values currently packed into all bins
-tbb::atomic<size_type> packed_items;  // number of values currently packed into all bins
-tbb::atomic<size_type> active_bins;   // number of active bin_packers
+std::atomic<value_type> packed_sum;   // sum of all values currently packed into all bins
+std::atomic<size_type>  packed_items; // number of values currently packed into all bins
+std::atomic<size_type>  active_bins;  // number of active bin_packers
 bin_packer **bins;               // the array of bin packers
 
 // This class is the Body type for bin_packer
@@ -218,16 +218,9 @@ public:
     }
 };
 
-int get_default_num_threads() {
-    static int threads = 0;
-    if (threads == 0)
-        threads = task_scheduler_init::default_num_threads();
-    return threads;
-}
-
 int main(int argc, char *argv[]) {
     try {
-        utility::thread_number_range threads(get_default_num_threads);
+        utility::thread_number_range threads(utility::get_default_num_threads);
         utility::parse_cli_arguments(argc, argv,
                                      utility::cli_argument_pack()
                                      //"-h" option for displaying help is present implicitly
@@ -255,7 +248,7 @@ int main(int argc, char *argv[]) {
 
         tick_count start = tick_count::now();
         for(int p = threads.first; p <= threads.last; p = threads.step(p)) {
-            task_scheduler_init init(p);
+            tbb::global_control c(tbb::global_control::max_allowed_parallelism, p);
             packed_sum = 0;
             packed_items = 0;
             B = 0;
index 5946c66..620a672 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;tbbmalloc_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;tbbmalloc_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;tbbmalloc.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;tbbmalloc.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index ad27f72..1c199b8 100644 (file)
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                                CLANG_WARN_COMMA = YES;
                                        "$(TBBROOT)/include",
                                        /opt/intel/tbb/include,
                                );
+                               ICC_CXX_LANG_DIALECT = "c++11";
                                LD_RUNPATH_SEARCH_PATHS = "$(TBBROOT)/lib /opt/intel/tbb/lib";
                                LIBRARY_SEARCH_PATHS = (
                                        "$(TBBROOT)/lib",
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                                CLANG_WARN_COMMA = YES;
                                        "$(TBBROOT)/include",
                                        /opt/intel/tbb/include,
                                );
+                               ICC_CXX_LANG_DIALECT = "c++11";
                                LD_RUNPATH_SEARCH_PATHS = "$(TBBROOT)/lib /opt/intel/tbb/lib";
                                LIBRARY_SEARCH_PATHS = (
                                        "$(TBBROOT)/lib",
index 7b0c7de..fe11dab 100644 (file)
@@ -34,16 +34,16 @@ endif
 override MKL_LIBS += -lmkl_rt
 endif
 
-# C++0x support
-override CXXFLAGS += -std=c++0x
+# autodetect C++11 support
+include ../../common/examples-common.inc
 
 all:   release test
 
 release: *.cpp
-       $(CXX) -O2  -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(MKL_LIBS) $(LIBS)
+       $(CXX) -O2  -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(MKL_LIBS) $(LIBS) $(CXX0XFLAGS)
 
 debug: *.cpp
-       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(MKL_LIBS) $(LIBS)
+       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(MKL_LIBS) $(LIBS) $(CXX0XFLAGS)
 
 profile: override CXXFLAGS += -DTBB_USE_THREADING_TOOLS -g
 profile: release
index aa4376b..44aeb63 100644 (file)
 #include "tbb/tbb_config.h"
 #include "tbb/flow_graph.h"
 #include "tbb/tick_count.h"
-#include "tbb/task_scheduler_init.h"
+#include "tbb/global_control.h"
 
 // Application command line arguments parsing
 #include "../../common/utility/utility.h"
+#include "../../common/utility/get_default_num_threads.h"
 
 /************************************************************
  FORWARD DECLARATIONS
@@ -49,7 +50,7 @@ void matrix_init( double * &A, int &n, const char *fname );
 
 /**********************************************
  Writes a lower triangular matrix to a file
- -- first line of file is n 
+ -- first line of file is n
  -- subsequently 1 row per line
 **********************************************/
 void matrix_write ( double *A, int n, const char *fname, bool is_triangular = false );
@@ -58,11 +59,11 @@ void matrix_write ( double *A, int n, const char *fname, bool is_triangular = fa
  GLOBAL VARIABLES
 ************************************************************/
 bool g_benchmark_run = false;
-int g_num_tbb_threads = tbb::task_scheduler_init::default_num_threads();
 int g_n = -1, g_b = -1, g_num_trials = 1;
 char *g_input_file_name = NULL;
 char *g_output_prefix = NULL;
 std::string g_alg_name;
+int g_num_tbb_threads;
 
 // Creates tiled array
 static double ***create_tile_array( double *A, int n, int b ) {
@@ -210,7 +211,7 @@ static void call_dpotf2( double ***tile, int b, int k ) {
     double *A_block = tile[k][k];
     char uplo = 'l';
     int info = 0;
-    dpotf2( &uplo, &b, A_block, &b, &info ); 
+    dpotf2( &uplo, &b, A_block, &b, &info );
     return;
 }
 
@@ -320,7 +321,7 @@ public:
         dpotf2( &uplo, &b, A_block, &b, &info );
 
         // Send to dtrsms in same column
-        // k == k  j == k 
+        // k == k  j == k
         t.a[2] = k;
         for ( int j = k+1; j < p; ++j ) {
             t.a[1] = j;
@@ -390,7 +391,7 @@ public:
         int j = in2.first.a[1];
         int i = in2.first.a[2];
 
-        tile_t A_block = in2.second; 
+        tile_t A_block = in2.second;
         if ( i == j ) {   // Diagonal block
             tile_t L_block = in0.second;
             dsyrk( &uplo, &transa, &b, &b, &alpha, L_block, &b, &beta, A_block, &b );
@@ -660,6 +661,7 @@ bool process_args( int argc, char *argv[] ) {
 }
 
 int main(int argc, char *argv[]) {
+    g_num_tbb_threads = utility::get_default_num_threads();
     typedef std::map< std::string, algorithm * > algmap_t;
     algmap_t algmap;
 
@@ -674,7 +676,7 @@ int main(int argc, char *argv[]) {
         exit( 1 );
     }
 
-    tbb::task_scheduler_init init( g_num_tbb_threads );
+    tbb::global_control c(tbb::global_control::max_allowed_parallelism, g_num_tbb_threads);
     double *A = NULL;
 
     // Read input matrix
index d906a46..67c7c8f 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;mkl_rt.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(MKLROOT)\lib\ia32;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(MKLROOT)\lib\ia32;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;mkl_rt.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(MKLROOT)\lib\intel64;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(MKLROOT)\lib\intel64;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;mkl_rt.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(MKLROOT)\lib\ia32;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(MKLROOT)\lib\ia32;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;mkl_rt.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(MKLROOT)\lib\intel64;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(MKLROOT)\lib\intel64;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index 041d3bc..87f4d69 100644 (file)
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                                CLANG_WARN_COMMA = YES;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                                CLANG_WARN_COMMA = YES;
index fd86266..6fd81a6 100644 (file)
@@ -33,13 +33,16 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:   release test
 
 release: dining_philosophers.cpp
-       $(CXX) -O2 -DNDEBUG -D_CONSOLE $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS)
+       $(CXX) -O2 -DNDEBUG -D_CONSOLE $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS) $(CXX0XFLAGS)
 
 debug:  dining_philosophers.cpp
-       $(CXX) -O0 -D_CONSOLE -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS)
+       $(CXX) -O0 -D_CONSOLE -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS) $(CXX0XFLAGS)
 
 profile: override CXXFLAGS += -DTBB_USE_THREADING_TOOLS -g
 profile: release
index e052e07..6720408 100644 (file)
 #endif
 
 #include "tbb/flow_graph.h"
-#include "tbb/task_scheduler_init.h"
 #include "tbb/tick_count.h"
-#include "tbb/tbb_thread.h"
-#include "tbb/atomic.h"
 #include "tbb/spin_mutex.h"
+#include "tbb/global_control.h"
 #include <iostream>
+#include <thread>
+#include <chrono>
 #include "../../common/utility/utility.h"
+#include "../../common/utility/get_default_num_threads.h"
 #include <cstdlib>
 #include <cstdio>
 
@@ -45,8 +46,8 @@
 // eat() function_node.  The output of the eat() function_node is sent to the forward()
 // multifunction_node.
 
-const tbb::tick_count::interval_t think_time(1.0);
-const tbb::tick_count::interval_t eat_time(1.0);
+const std::chrono::seconds think_time (1);
+const std::chrono::seconds eat_time   (1);
 const int num_times = 10;
 
 tbb::tick_count t0;
@@ -69,8 +70,8 @@ struct RunOptions {
 };
 
 RunOptions ParseCommandLine(int argc, char *argv[]) {
-    int auto_threads = tbb::task_scheduler_init::default_num_threads();
-    utility::thread_number_range threads(tbb::task_scheduler_init::default_num_threads, auto_threads, auto_threads);
+    int auto_threads = utility::get_default_num_threads();
+    utility::thread_number_range threads(utility::get_default_num_threads, auto_threads, auto_threads);
     int nPhilosophers = 5;
     bool verbose = false;
     char charbuf[100];
@@ -198,7 +199,7 @@ void philosopher::eat() {
         tbb::spin_mutex::scoped_lock lock(my_mutex);
         std::printf("%s eating\n", name());
     }
-    tbb::this_tbb_thread::sleep(eat_time);
+    std::this_thread::sleep_for(eat_time);
     if(verbose) {
         tbb::spin_mutex::scoped_lock lock(my_mutex);
         std::printf("%s done eating\n", name());
@@ -210,7 +211,7 @@ void philosopher::think() {
         tbb::spin_mutex::scoped_lock lock(my_mutex);
         std::printf("%s thinking\n", name());
     }
-    tbb::this_tbb_thread::sleep(think_time);
+    std::this_thread::sleep_for(think_time);
     if(verbose) {
         tbb::spin_mutex::scoped_lock lock(my_mutex);
         std::printf("%s done thinking\n", name());
@@ -231,7 +232,7 @@ int main(int argc, char *argv[]) {
 
     for(num_threads = options.threads.first; num_threads <= options.threads.last; num_threads = options.threads.step(num_threads)) {
 
-        tbb::task_scheduler_init init(num_threads);
+        tbb::global_control c(tbb::global_control::max_allowed_parallelism, num_threads);
 
             graph g;
 
index 78b0ae2..53e5ce2 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index 7a3535d..9b3462c 100644 (file)
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                                CLANG_WARN_COMMA = YES;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                                CLANG_WARN_COMMA = YES;
index cf1ab95..b93daa8 100644 (file)
@@ -24,22 +24,22 @@ ifneq (,$(shell which icc 2>/dev/null))
     CXX=icpc
 endif
 
-# autodetect C++11 support
-include ../../common/examples-common.inc
-
 ifeq ($(shell uname), Linux)
 LIBS+= -lrt -lpthread
 else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all: release test
 
 release:
        $(CXX) -O2 -DNDEBUG *.cpp $(CXXFLAGS) -o $(PROG) -ltbb $(LIBS) $(CXX0XFLAGS)
 
 debug:
-       $(CXX) -O0 -g -DTBB_USE_DEBUG *.cpp $(CXXFLAGS) -o $(PROG) -ltbb_debug $(LIBS)  $(CXX0XFLAGS)
+       $(CXX) -O0 -g -DTBB_USE_DEBUG *.cpp $(CXXFLAGS) -o $(PROG) -ltbb_debug $(LIBS) $(CXX0XFLAGS)
 
 profile: override CXXFLAGS += -DTBB_USE_THREADING_TOOLS -g
 profile: release
index c9cd43f..c226192 100644 (file)
 #include <string>
 #include <memory>
 #include <queue>
+#include <thread>
 
 #include "bzlib.h"
 
 #include "tbb/flow_graph.h"
 #include "tbb/tick_count.h"
-#include "tbb/compat/thread"
 #include "tbb/concurrent_queue.h"
 
 // TODO: change memory allocation/deallocation to be managed in constructor/destructor
index bf28d99..4d6ae7f 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;tbbmalloc_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;tbbmalloc_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;tbbmalloc.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;tbbmalloc.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index 69f17bd..a2de5c6 100644 (file)
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++11";
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                                CLANG_WARN_COMMA = YES;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++11";
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                                CLANG_WARN_COMMA = YES;
index 1aaee5c..5a626eb 100644 (file)
@@ -34,13 +34,16 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:    release test
 
 release: *.cpp
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $(PROG).cpp -std=c++0x -ltbb $(LIBS) 
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $(PROG).cpp -std=c++11 -ltbb $(LIBS) $(CXX0XFLAGS)
 
 debug: *.cpp
-       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $(PROG).cpp -std=c++0x -ltbb_debug $(LIBS) 
+       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $(PROG).cpp -std=c++11 -ltbb_debug $(LIBS) $(CXX0XFLAGS)
 
 profile: override CXXFLAGS += -DTBB_USE_THREADING_TOOLS -g
 profile: release
index 76aa3a1..b696d62 100644 (file)
@@ -19,8 +19,6 @@
 
 #include <cstdio>
 #include <string>
-#include "tbb/atomic.h"
-#include "tbb/task_scheduler_init.h"
 #include "tbb/tick_count.h"
 #include "tbb/flow_graph.h"
 #include "../../common/utility/utility.h"
@@ -167,7 +165,7 @@ class steady_signal {
     ~steady_signal() {}
     // Assignment is ignored
     steady_signal& operator=(const steady_signal& src) { return *this; }
-    sender<signal_t>& get_out() { return signal_node; }
+    write_once_node<signal_t>& get_out() { return signal_node; }
     void activate() { signal_node.try_put(init_signal); }
 };
 
@@ -208,7 +206,7 @@ public:
         ms = src.ms; init_ms = src.init_ms; reps = src.reps; init_reps = src.init_reps;
         return *this; 
     }
-    sender<signal_t>& get_out() { return clock_node; }
+    source_node<signal_t>& get_out() { return clock_node; }
     void activate() { clock_node.activate(); }
     void reset() { reps = init_reps; }
 };
@@ -227,7 +225,7 @@ class push_button {
     ~push_button() {}
     // Assignment is ignored
     push_button& operator=(const push_button& src) { return *this; }
-    sender<signal_t>& get_out() { return push_button_node; }
+    overwrite_node<signal_t>& get_out() { return push_button_node; }
     void press() { push_button_node.try_put(high); }
     void release() { push_button_node.try_put(low); }
 };
@@ -243,7 +241,7 @@ class toggle {
     ~toggle() {}
     // Assignment ignored
     toggle& operator=(const toggle& src) { return *this; }
-    sender<signal_t>& get_out() { return toggle_node; }
+    overwrite_node<signal_t>& get_out() { return toggle_node; }
     void flip() { 
         if (state==high) state = low; 
         else state = high;
@@ -494,7 +492,7 @@ class led {
         label = src.label; state = undefined; report_changes = src.report_changes; 
         return *this;
     }
-    receiver<signal_t>& get_in() { return led_node; }
+    function_node<signal_t, continue_msg>& get_in() { return led_node; }
     void display() { 
         if (state == high) printf("%s: (*)\n", label.c_str());
         else if (state == low) printf("%s: ( )\n", label.c_str());
index 922e86b..7c7725f 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;tbbmalloc_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;tbbmalloc_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;tbbmalloc.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;tbbmalloc.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index 6613561..95c1857 100644 (file)
 */
 
 #include "tbb/tbb_config.h"
+#include "tbb/global_control.h"
 #include <cstdio>
 
 #include "../../common/utility/utility.h"
+#include "../../common/utility/get_default_num_threads.h"
 
 #if __TBB_FLOW_GRAPH_CPP11_FEATURES
 
 bool verbose = false;            // prints bin details and other diagnostics to screen
 bool silent = false;             // suppress all output except for time
 
-int get_default_num_threads() {
-    static int threads = 0;
-    if (threads == 0)
-        threads = tbb::task_scheduler_init::default_num_threads();
-    return threads;
-}
-
 #endif // __TBB_FLOW_GRAPH_CPP11_FEATURES
 
 int main(int argc, char *argv[]) {
 #if __TBB_FLOW_GRAPH_CPP11_FEATURES
     try {
-        utility::thread_number_range threads(get_default_num_threads);
+        utility::thread_number_range threads(utility::get_default_num_threads);
         utility::parse_cli_arguments(argc, argv,
                                      utility::cli_argument_pack()
                                      //"-h" option for displaying help is present implicitly
@@ -66,19 +61,19 @@ int main(int argc, char *argv[]) {
 
         tick_count start = tick_count::now();
         for(int p = threads.first; p <= threads.last; p = threads.step(p)) {
-            task_scheduler_init init(p);
+            tbb::global_control c(tbb::global_control::max_allowed_parallelism, p);
             if (!silent)  cout << "graph test running on " << p << " threads.\n";
-            
+
             graph g;
 
             { // test buffer: 0, 1
                 buffer b(g);
                 toggle input(g);
                 led output(g, "OUTPUT", false); // false means we will explicitly call display to see LED
-                
+
                 make_edge(input.get_out(), input_port<0>(b));
                 make_edge(output_port<0>(b), output.get_in());
-                
+
                 if (!silent) printf("Testing buffer...\n");
                 input.activate(); // 0
                 g.wait_for_all();
@@ -94,10 +89,10 @@ int main(int argc, char *argv[]) {
                 not_gate n(g);
                 toggle input(g);
                 led output(g, "OUTPUT", false);
-                
+
                 make_edge(input.get_out(), input_port<0>(n));
                 make_edge(output_port<0>(n), output.get_in());
-                
+
                 if (!silent) printf("Testing not_gate...\n");
                 input.activate(); // 0
                 g.wait_for_all();
@@ -114,11 +109,11 @@ int main(int argc, char *argv[]) {
                 toggle input0(g);
                 toggle input1(g);
                 led output(g, "OUTPUT", false);
-                
+
                 make_edge(input0.get_out(), input_port<0>(a));
                 make_edge(input1.get_out(), input_port<1>(a));
                 make_edge(output_port<0>(a), output.get_in());
-                
+
                 if (!silent) printf("Testing and_gate...\n");
                 input1.activate();  input0.activate();  // 0 0
                 g.wait_for_all();
@@ -144,12 +139,12 @@ int main(int argc, char *argv[]) {
                 toggle input1(g);
                 toggle input2(g);
                 led output(g, "OUTPUT", false);
-                
+
                 make_edge(input0.get_out(), input_port<0>(o));
                 make_edge(input1.get_out(), input_port<1>(o));
                 make_edge(input2.get_out(), input_port<2>(o));
                 make_edge(output_port<0>(o), output.get_in());
-                
+
                 if (!silent) printf("Testing or_gate...\n");
                 input2.activate();  input1.activate();  input0.activate();  // 0 0 0
                 g.wait_for_all();
@@ -190,11 +185,11 @@ int main(int argc, char *argv[]) {
                 toggle input0(g);
                 toggle input1(g);
                 led output(g, "OUTPUT", false);
-                
+
                 make_edge(input0.get_out(), input_port<0>(x));
                 make_edge(input1.get_out(), input_port<1>(x));
                 make_edge(output_port<0>(x), output.get_in());
-                
+
                 if (!silent) printf("Testing xor_gate...\n");
                 input1.activate();  input0.activate();  // 0 0
                 g.wait_for_all();
@@ -220,11 +215,11 @@ int main(int argc, char *argv[]) {
                 toggle input0(g);
                 toggle input1(g);
                 led output(g, "OUTPUT", false);
-                
+
                 make_edge(input0.get_out(), input_port<0>(n));
                 make_edge(input1.get_out(), input_port<1>(n));
                 make_edge(output_port<0>(n), output.get_in());
-                
+
                 if (!silent) printf("Testing nor_gate...\n");
                 input1.activate();  input0.activate();  // 0 0
                 g.wait_for_all();
@@ -252,7 +247,7 @@ int main(int argc, char *argv[]) {
                 xor_gate<2> x(g);
                 nor_gate<2> n(g);
                 digit output(g, "OUTPUT", false);
-                
+
                 make_edge(input0.get_out(), input_port<0>(a));
                 make_edge(input1.get_out(), input_port<1>(a));
                 make_edge(output_port<0>(a), input_port<0>(output));
@@ -268,7 +263,7 @@ int main(int argc, char *argv[]) {
                 make_edge(input0.get_out(), input_port<0>(n));
                 make_edge(input1.get_out(), input_port<1>(n));
                 make_edge(output_port<0>(n), input_port<3>(output));
-                
+
                 if (!silent) printf("Testing steady_signal...\n");
                 input0.activate();  // 1
                 input1.activate();  // 0
@@ -300,31 +295,31 @@ int main(int argc, char *argv[]) {
                 toggle CarryIN(g);
                 led Sum(g, "SUM");
                 led CarryOUT(g, "CarryOUT");
-                
+
                 make_edge(A.get_out(), input_port<P::A0>(my_adder));
                 make_edge(B.get_out(), input_port<P::B0>(my_adder));
                 make_edge(CarryIN.get_out(), input_port<P::CI>(my_adder));
                 make_edge(output_port<P::S0>(my_adder), Sum.get_in());
                 make_edge(output_port<1>(my_adder), CarryOUT.get_in());
-                
+
                 A.activate();
                 B.activate();
                 CarryIN.activate();
-                
+
                 if (!silent) printf("A on\n");
                 A.flip();
                 g.wait_for_all();
                 if (!silent) Sum.display();
                 if (!silent) CarryOUT.display();
                 assert((Sum.get_value() == high) && (CarryOUT.get_value() == low));
-                
+
                 if (!silent) printf("A off\n");
                 A.flip();
                 g.wait_for_all();
                 if (!silent) Sum.display();
                 if (!silent) CarryOUT.display();
                 assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
-                
+
                 if (!silent) printf("B on\n");
                 B.flip();
                 g.wait_for_all();
@@ -337,7 +332,7 @@ int main(int argc, char *argv[]) {
                 if (!silent) Sum.display();
                 if (!silent) CarryOUT.display();
                 assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
-                
+
                 if (!silent) printf("CarryIN on\n");
                 CarryIN.flip();
                 g.wait_for_all();
@@ -350,7 +345,7 @@ int main(int argc, char *argv[]) {
                 if (!silent) Sum.display();
                 if (!silent) CarryOUT.display();
                 assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
-                
+
                 if (!silent) printf("A&B on\n");
                 A.flip();
                 B.flip();
@@ -365,7 +360,7 @@ int main(int argc, char *argv[]) {
                 if (!silent) Sum.display();
                 if (!silent) CarryOUT.display();
                 assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
-                
+
                 if (!silent) printf("A&CarryIN on\n");
                 A.flip();
                 CarryIN.flip();
@@ -380,7 +375,7 @@ int main(int argc, char *argv[]) {
                 if (!silent) Sum.display();
                 if (!silent) CarryOUT.display();
                 assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
-                
+
                 if (!silent) printf("B&CarryIN on\n");
                 B.flip();
                 CarryIN.flip();
@@ -395,7 +390,7 @@ int main(int argc, char *argv[]) {
                 if (!silent) Sum.display();
                 if (!silent) CarryOUT.display();
                 assert((Sum.get_value() == low) && (CarryOUT.get_value() == low));
-                
+
                 if (!silent) printf("A&B&CarryIN on\n");
                 A.flip();
                 B.flip();
@@ -429,7 +424,7 @@ int main(int argc, char *argv[]) {
                 make_edge(output_port<P::S0>(two_adder), input_port<0>(Sum));
 
                 make_edge(A[1].get_out(), input_port<P::A1>(two_adder));
-                make_edge(B[1].get_out(), input_port<P::B1>(two_adder)); 
+                make_edge(B[1].get_out(), input_port<P::B1>(two_adder));
                 make_edge(output_port<P::S1>(two_adder), input_port<1>(Sum));
 
                 make_edge(CarryIN.get_out(), input_port<P::CI>(two_adder));
@@ -484,21 +479,21 @@ int main(int argc, char *argv[]) {
 
                     make_edge(CarryIN.get_out(), input_port<P::CI>(four_adder));
                     make_edge(output_port<P::CO>(four_adder), CarryOUT.get_in());
-                
+
                 // Activate all switches at low state
                 for (int i=0; i<4; ++i) {
                     A[i].activate();
                     B[i].activate();
                 }
                 CarryIN.activate();
-                
+
                 if (!silent) printf("1+0\n");
                 A[0].flip();
                 g.wait_for_all();
                 if (!silent) Sum.display();
                 if (!silent) CarryOUT.display();
                 assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low));
-                
+
                 if (!silent) printf("0+1\n");
                 A[0].flip();
                 B[0].flip();
@@ -506,7 +501,7 @@ int main(int argc, char *argv[]) {
                 if (!silent) Sum.display();
                 if (!silent) CarryOUT.display();
                 assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low));
-                
+
                 if (!silent) printf("3+4\n");
                 A[0].flip();
                 A[1].flip();
@@ -516,7 +511,7 @@ int main(int argc, char *argv[]) {
                 if (!silent) Sum.display();
                 if (!silent) CarryOUT.display();
                 assert((Sum.get_value() == 7) && (CarryOUT.get_value() == low));
-                
+
                 if (!silent) printf("6+1\n");
                 A[0].flip();
                 A[2].flip();
@@ -526,7 +521,7 @@ int main(int argc, char *argv[]) {
                 if (!silent) Sum.display();
                 if (!silent) CarryOUT.display();
                 assert((Sum.get_value() == 7) && (CarryOUT.get_value() == low));
-                
+
                 if (!silent) printf("0+0+carry\n");
                 A[1].flip();
                 A[2].flip();
@@ -536,7 +531,7 @@ int main(int argc, char *argv[]) {
                 if (!silent) Sum.display();
                 if (!silent) CarryOUT.display();
                 assert((Sum.get_value() == 1) && (CarryOUT.get_value() == low));
-                
+
                 if (!silent) printf("15+15+carry\n");
                 A[0].flip();
                 A[1].flip();
@@ -550,7 +545,7 @@ int main(int argc, char *argv[]) {
                 if (!silent) Sum.display();
                 if (!silent) CarryOUT.display();
                 assert((Sum.get_value() == 0xf) && (CarryOUT.get_value() == high));
-                
+
                 if (!silent) printf("8+8\n");
                 A[0].flip();
                 A[1].flip();
@@ -563,7 +558,7 @@ int main(int argc, char *argv[]) {
                 if (!silent) Sum.display();
                 if (!silent) CarryOUT.display();
                 assert((Sum.get_value() == 0) && (CarryOUT.get_value() == high));
-                
+
                 if (!silent) printf("0+0\n");
                 A[3].flip();
                 B[3].flip();
@@ -581,7 +576,7 @@ int main(int argc, char *argv[]) {
                 led Q(g, " Q", verbose); // if true, LEDs print at every state change
                 led notQ(g, "~Q", verbose);
 
-                make_edge(D.get_out(), input_port<0>(my_d_latch)); 
+                make_edge(D.get_out(), input_port<0>(my_d_latch));
                 make_edge(E.get_out(), input_port<1>(my_d_latch));
                 make_edge(output_port<0>(my_d_latch), Q.get_in());
                 make_edge(output_port<1>(my_d_latch), notQ.get_in());
@@ -595,7 +590,7 @@ int main(int argc, char *argv[]) {
                 if (!silent && !verbose) { Q.display(); notQ.display(); }
                 assert((Q.get_value() == high) && (notQ.get_value() == low));
                 E.reset();
-                
+
                 if (!silent) printf("Toggling D\n");
                 E.activate();
                 D.flip();
@@ -603,7 +598,7 @@ int main(int argc, char *argv[]) {
                 if (!silent && !verbose) { Q.display(); notQ.display(); }
                 assert((Q.get_value() == low) && (notQ.get_value() == high));
                 E.reset();
-                
+
                 if (!silent) printf("Toggling D\n");
                 E.activate();
                 D.flip();
@@ -611,7 +606,7 @@ int main(int argc, char *argv[]) {
                 if (!silent && !verbose) { Q.display(); notQ.display(); }
                 assert((Q.get_value() == high) && (notQ.get_value() == low));
                 E.reset();
-                
+
                 if (!silent) printf("Toggling D\n");
                 E.activate();
                 D.flip();
@@ -619,7 +614,7 @@ int main(int argc, char *argv[]) {
                 if (!silent && !verbose) { Q.display(); notQ.display(); }
                 assert((Q.get_value() == low) && (notQ.get_value() == high));
                 E.reset();
-                
+
                 if (!silent) printf("Toggling D\n");
                 E.activate();
                 D.flip();
index 9bb9271..bc927db 100644 (file)
@@ -33,18 +33,21 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:   release test
 
 release: $(SRCFILES)
 ifeq ($(compiler),xl)
        # Avoiding "1586-346 (U) An error occurred during code generation.  The code generation return code was 40." with -O3.
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(EXE) $(SRCFILES) -ltbb -ltbbmalloc $(LIBS)
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(EXE) $(SRCFILES) -ltbb -ltbbmalloc $(LIBS) $(CXX0XFLAGS)
 else
-       $(CXX) -O3 -DNDEBUG $(CXXFLAGS) -o $(EXE) $(SRCFILES) -ltbb -ltbbmalloc $(LIBS)
+       $(CXX) -O3 -DNDEBUG $(CXXFLAGS) -o $(EXE) $(SRCFILES) -ltbb -ltbbmalloc $(LIBS) $(CXX0XFLAGS)
 endif
 
 debug:  $(SRCFILES)
-       $(CXX) -g -O0 -DTBB_USE_DEBUG -D_DEBUG $(CXXFLAGS) -o $(EXE) $(SRCFILES) -ltbb_debug -ltbbmalloc_debug $(LIBS)
+       $(CXX) -g -O0 -DTBB_USE_DEBUG -D_DEBUG $(CXXFLAGS) -o $(EXE) $(SRCFILES) -ltbb_debug -ltbbmalloc_debug $(LIBS) $(CXX0XFLAGS)
 
 profile: override CXXFLAGS += -DTBB_USE_THREADING_TOOLS -g
 profile: release
index a29633e..2e39b69 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <RandomizedBaseAddress>false</RandomizedBaseAddress>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <RandomizedBaseAddress>false</RandomizedBaseAddress>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index 2397a73..12461ff 100644 (file)
 #define _MAIN_C_ 1
 #include "som.h"
 
-#include "tbb/task_scheduler_init.h"
 #include "tbb/flow_graph.h"
 #include "tbb/blocked_range2d.h"
 #include "tbb/tick_count.h"
+#include "tbb/task_arena.h"
 #include "../../common/utility/utility.h"
+#include "../../common/utility/get_default_num_threads.h"
 
 #define RED 0
 #define GREEN 1
@@ -96,12 +97,19 @@ queue_node<search_result_type> *q[SPECULATION_CNT];  // queue for function nodes
 search_node_array_type* s_array[SPECULATION_CNT];  // 2d array of function nodes
 graph_array_type* g_array[SPECULATION_CNT];        // 2d array of graphs
 
+// All graphs must locate in the same arena.
+graph* construct_graph(task_arena& ta) {
+    graph* result;
+    ta.execute([&result]{result = new graph;});
+    return result;
+}
+
 // build a set of SPECULATION_CNT graphs, each of which consists of a broadcast_node,
 //    xranges x yranges function_nodes, and one queue_node for output.
 //    once speculation starts, if i % SPECULATION_CNT is the current graph, (i+1) % SPECULATION_CNT
 //    is the first speculation, and so on.
 void
-build_BMU_graph(SOMap &map1) {
+build_BMU_graph(SOMap &map1, task_arena& ta) {
     // build current graph
     xsize = ((int)map1.size() + xranges - 1) / xranges;
     ysize = ((int)map1[0].size() + yranges - 1) / yranges;
@@ -110,7 +118,7 @@ build_BMU_graph(SOMap &map1) {
     for(int ii = 0; ii < xranges*yranges+1;++ii) function_node_execs.push_back(0);
 
     for(int scnt = 0; scnt < SPECULATION_CNT; ++scnt) {
-        g[scnt] = new graph;
+        g[scnt] = construct_graph(ta);
         send_to[scnt] = new b_node(*(g[scnt]));  // broadcast node to the function_nodes
         q[scnt] = new queue_node<search_result_type>(*(g[scnt]));  // output queue
 
@@ -131,7 +139,7 @@ build_BMU_graph(SOMap &map1) {
                 int ymax = (j + ysize) > (int)map1[0].size() ? (int)map1[0].size() : j + ysize;
                 subsquare_type sst(i,xmax,1,j,ymax,1);
                 BMU_search_body bb(map1,sst,function_node_execs[offset]);
-                graph *g_local = new graph;
+                graph *g_local = construct_graph(ta);
                 search_node *s = new search_node(*g_local, serial, bb); // copies Body
                 (*g_array[scnt])[xindex].push_back(g_local);
                 (*s_array[scnt])[xindex].push_back(s);
@@ -252,8 +260,8 @@ graph_BMU( int indx ) {  // indx ranges over [0 .. SPECULATION_CNT -1]
     // end of one epoch
 }
 
-void graph_teach(SOMap &map1, teaching_vector_type &in) {
-    build_BMU_graph(map1);
+void graph_teach(SOMap &map1, teaching_vector_type &in, task_arena& ta) {
+    build_BMU_graph(map1, ta);
     // normally the training would pick random exemplars to teach the SOM.  We need
     // the process to be reproducible, so we will pick the exemplars in order, [0, in.size())
     int next_j = 0;
@@ -306,8 +314,8 @@ int
 main(int argc, char** argv) {
     int l_speculation_start;
     utility::thread_number_range threads( 
-            task_scheduler_init::default_num_threads,
-            task_scheduler_init::default_num_threads()  // run only the default number of threads if none specified
+            utility::get_default_num_threads,
+            utility::get_default_num_threads()  // run only the default number of threads if none specified
     );
 
     utility::parse_cli_arguments(argc,argv,
@@ -340,7 +348,8 @@ main(int argc, char** argv) {
     // adjust nPasses so the 1x1 time is somewhere around serial_time_adjust seconds.
    // make sure the example test runs for at least 0.5 second.
     for(;;) {
-        task_scheduler_init init(1);
+        // Restrict max concurrency level via task_arena interface
+        task_arena ta(1);
         SOMap map1(xMax,yMax);
         speculation_start = nPasses + 1;  // Don't speculate
 
@@ -348,7 +357,7 @@ main(int argc, char** argv) {
         yranges = 1;
         map1.initialize(InitializeGradient, max_range, min_range);
         tick_count t0 = tick_count::now();
-        graph_teach(map1, my_teaching);
+        graph_teach(map1, my_teaching, ta);
         tick_count t1 = tick_count::now();
         double nSeconds = (t1-t0).seconds();
         if(nSeconds < 0.5) {
@@ -387,7 +396,8 @@ main(int argc, char** argv) {
     }
     double single_time;  // for speedup calculations
     for(int p = threads.first; p <= threads.last; ++p) {
-        task_scheduler_init init(p);
+        // Restrict max concurrency level via task_arena interface
+        task_arena ta(p);
         if ( extra_debug )printf( " -------------- Running with %d threads. ------------\n", p);
        // run the SOM build for a series of subranges
         for(xranges = 1; xranges <= xRangeMax; ++xranges) {
@@ -404,7 +414,7 @@ main(int argc, char** argv) {
     
                 if(extra_debug) printf( "Start learning for [%d,%d] ----------- \n", xranges,yranges);
                 tick_count t0 = tick_count::now();
-                graph_teach(map1, my_teaching);
+                graph_teach(map1, my_teaching, ta);
                 tick_count t1 = tick_count::now();
                 
                 if ( extra_debug )printf( "Done learning for [%d,%d], which took %g seconds ", xranges,yranges, (t1-t0).seconds());
index 96c8393..8402dd0 100644 (file)
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                                CLANG_WARN_COMMA = YES;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                                CLANG_WARN_COMMA = YES;
index e460ece..87308f2 100644 (file)
@@ -91,7 +91,7 @@
     </ClCompile>
     <Link>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalLibraryDirectories>$(INTELOCLSDKROOT)lib\x86;$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(INTELOCLSDKROOT)lib\x86;$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <AdditionalDependencies>OpenCL.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
     </ClCompile>
     <Link>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalLibraryDirectories>$(INTELOCLSDKROOT)lib\x64;$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(INTELOCLSDKROOT)lib\x64;$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <AdditionalDependencies>OpenCL.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>$(INTELOCLSDKROOT)lib\x86;$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(INTELOCLSDKROOT)lib\x86;$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <AdditionalDependencies>OpenCL.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalLibraryDirectories>$(INTELOCLSDKROOT)lib\x64;$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(INTELOCLSDKROOT)lib\x64;$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <AdditionalDependencies>OpenCL.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
index 57428a4..709a2c7 100644 (file)
 
 using namespace std;
 
+Cell::Cell(const Cell& other)
+    : op( other.op )
+    , value( other.value )
+    , successor( other.successor )
+{
+    ref_count = other.ref_count.load();
+
+    input[0] = other.input[0];
+    input[1] = other.input[1];
+}
+
 void Graph::create_random_dag( size_t number_of_nodes ) {
     my_vertex_set.resize(number_of_nodes);
     for( size_t k=0; k<number_of_nodes; ++k ) {
@@ -37,10 +48,10 @@ void Graph::create_random_dag( size_t number_of_nodes ) {
             case 2:
                 c.op = OP_SUB;
                 break;
-            case 3: 
+            case 3:
                 c.op = OP_ADD;
                 break;
-            case 4: 
+            case 4:
                 c.op = OP_MUL;
                 break;
         }
index fe19188..4cfd6f3 100644 (file)
@@ -15,8 +15,8 @@
 */
 
 #include "Matrix.h"
-#include "tbb/atomic.h"
 #include <vector>
+#include <atomic>
 
 enum OpKind {
     // Use Cell's value
@@ -40,7 +40,7 @@ public:
 
     //! Inputs to this cell
     Cell* input[2];
-   
+
     //! Type of value stored in a Cell
     typedef Matrix value_type;
 
@@ -51,13 +51,16 @@ public:
     std::vector<Cell*> successor;
 
     //! Reference count of number of inputs that are not yet updated.
-    tbb::atomic<int> ref_count;
+    std::atomic<int> ref_count;
 
     //! Update the Cell's value.
     void update();
 
     //! Default constructor
     Cell() {}
+
+    //! Copy constructor
+    Cell(const Cell& other);
 };
 
 //! A directed graph where the vertices are Cells.
index ba91676..0409e97 100644 (file)
@@ -35,13 +35,16 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:   release test
 
 release: *.cpp
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS)
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS) $(CXX0XFLAGS)
 
 debug: *.cpp
-       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS)
+       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS) $(CXX0XFLAGS)
 
 clean:
        $(RM) $(PROG) *.o *.d
index d96f8f5..ec33f8f 100644 (file)
    traversal of a directed acyclic graph. */
 
 #include <cstdlib>
-#include "tbb/task_scheduler_init.h"
 #include "tbb/tick_count.h"
+#include "tbb/global_control.h"
 #include "../../common/utility/utility.h"
+#include "../../common/utility/get_default_num_threads.h"
 #include <iostream>
 #include <vector>
 #include "Graph.h"
@@ -32,13 +33,12 @@ void ParallelPreorderTraversal( const std::vector<Cell*>& root_set );
 //------------------------------------------------------------------------
 // Test driver
 //------------------------------------------------------------------------
-utility::thread_number_range threads(tbb::task_scheduler_init::default_num_threads);
 static unsigned nodes = 1000;
 static unsigned traversals = 500;
 static bool SilentFlag = false;
 
 //! Parse the command line.
-static void ParseCommandLine( int argc, const char* argv[] ) {
+static void ParseCommandLine( int argc, const char* argv[], utility::thread_number_range& threads ) {
     utility::parse_cli_arguments(
             argc,argv,
             utility::cli_argument_pack()
@@ -52,13 +52,14 @@ static void ParseCommandLine( int argc, const char* argv[] ) {
 
 int main( int argc, const char* argv[] ) {
     try {
+        utility::thread_number_range threads(utility::get_default_num_threads);
         tbb::tick_count main_start = tbb::tick_count::now();
-        ParseCommandLine(argc,argv);
+        ParseCommandLine(argc,argv,threads);
 
         // Start scheduler with given number of threads.
         for( int p=threads.first; p<=threads.last; p = threads.step(p) ) {
             tbb::tick_count t0 = tbb::tick_count::now();
-            tbb::task_scheduler_init init(p);
+            tbb::global_control c(tbb::global_control::max_allowed_parallelism, p);
             srand(2);
             size_t root_set_size = 0;
             {
index 4f66cc8..455d3cf 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index 10431bb..6cedebc 100644 (file)
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                ENABLE_TESTABILITY = YES;
                                GCC_ENABLE_CPP_RTTI = YES;
                                GCC_MODEL_TUNING = "";
                                        "$(TBBROOT)/include",
                                        /opt/intel/tbb/include,
                                );
+                               ICC_CXX_LANG_DIALECT = "c++11";
                                LD_RUNPATH_SEARCH_PATHS = "$(TBBROOT)/lib /opt/intel/tbb/lib";
                                LIBRARY_SEARCH_PATHS = (
                                        "$(TBBROOT)/lib",
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                GCC_ENABLE_CPP_RTTI = YES;
                                GCC_MODEL_TUNING = "";
                                GCC_VERSION = "";
                                        "$(TBBROOT)/include",
                                        /opt/intel/tbb/include,
                                );
+                               ICC_CXX_LANG_DIALECT = "c++11";
                                LD_RUNPATH_SEARCH_PATHS = "$(TBBROOT)/lib /opt/intel/tbb/lib";
                                LIBRARY_SEARCH_PATHS = (
                                        "$(TBBROOT)/lib",
index 9ecddf2..bd31fa4 100644 (file)
@@ -32,13 +32,16 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:   release test
 
 release: src/Evolution.cpp src/Update_state.cpp src/Game_of_life.cpp
-       $(CXX) -O2 -DNDEBUG -D_CONSOLE $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS)
+       $(CXX) -O2 -DNDEBUG -D_CONSOLE $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS) $(CXX0XFLAGS)
 
 debug: src/Evolution.cpp src/Update_state.cpp src/Game_of_life.cpp
-       $(CXX) -O0 -D_CONSOLE -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS)
+       $(CXX) -O0 -D_CONSOLE -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS) $(CXX0XFLAGS)
 
 clean:
        rm -f $(PROG) *.o *.d
index 1a6c3ad..ffc3334 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;user32.lib</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AssemblyDebug>true</AssemblyDebug>
       <SubSystem>Windows</SubSystem>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;user32.lib</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AssemblyDebug>true</AssemblyDebug>
       <SubSystem>Windows</SubSystem>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;user32.lib</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;user32.lib</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
       <SubSystem>Console</SubSystem>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <ProgramDatabaseFile>$(TargetDir)$(TargetName).pdb</ProgramDatabaseFile>
       <SubSystem>Console</SubSystem>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index 75fb1e5..b11c155 100644 (file)
 */
 
 /*
-    Evolution.cpp: implementation file for evolution classes; evolution 
-                  classes do looped evolution of patterns in a defined 
+    Evolution.cpp: implementation file for evolution classes; evolution
+                  classes do looped evolution of patterns in a defined
                   2 dimensional space
 */
 
 #include "Evolution.h"
 #include "Board.h"
+#include "../../../common/utility/get_default_num_threads.h"
 
 #ifdef USE_SSE
 #define GRAIN_SIZE 14
@@ -35,8 +36,8 @@
 */
 
 /**
-    Evolution::UpdateMatrix() - moves the calculated destination data 
-    to the source data block. No destination zeroing is required since it will 
+    Evolution::UpdateMatrix() - moves the calculated destination data
+    to the source data block. No destination zeroing is required since it will
     be completely overwritten during the next calculation cycle.
 **/
 void Evolution::UpdateMatrix()
@@ -63,7 +64,7 @@ void SequentialEvolution::Run(double execution_time, int nthread)
     tbb::tick_count t0 = tbb::tick_count::now();
     while (!m_done)
     {
-        if( !is_paused ) 
+        if( !is_paused )
         {
             tbb::tick_count t = tbb::tick_count::now();
             Step();
@@ -99,7 +100,7 @@ void SequentialEvolution::Run(double execution_time, int nthread)
 //! SequentialEvolution::Step() - override of step method
 void SequentialEvolution::Step()
 {
-        if( !is_paused ) 
+        if( !is_paused )
     {
 #ifdef USE_SSE
     UpdateState(m_matrix, m_matrix->data, 0, m_matrix->height);
@@ -121,7 +122,7 @@ void ParallelEvolution::Run()
 #else
 void ParallelEvolution::Run(double execution_time, int nthread)
 {
-    if(nthread == tbb::task_scheduler_init::automatic)
+    if(nthread == utility::get_default_num_threads())
         printf("Starting game (Parallel evolution for automatic number of thread(s))\n");
     else
         printf("Starting game (Parallel evolution for %d thread(s))\n", nthread);
@@ -132,13 +133,13 @@ void ParallelEvolution::Run(double execution_time, int nthread)
 
 #ifndef _CONSOLE
     //! start task scheduler as necessary
-    if (m_pInit == NULL)
+    if (m_pGlobControl == NULL)
     {
-        m_pInit = new tbb::task_scheduler_init();
+        m_pGlobControl = new tbb::global_control(tbb::global_control::max_allowed_parallelism, utility::get_default_num_threads());
     }
     m_evt_start_parallel->WaitOne();
 #else
-    tbb::task_scheduler_init init(nthread);
+    tbb::global_control* pGlobControl = new tbb::global_control(tbb::global_control::max_allowed_parallelism, nthread);
 #endif
 
     double  work_time = m_serial_time;
@@ -146,7 +147,7 @@ void ParallelEvolution::Run(double execution_time, int nthread)
 
     while (!m_done)
     {
-        if( !is_paused ) 
+        if( !is_paused )
         {
             tbb::tick_count t = tbb::tick_count::now();
             Step();
@@ -157,7 +158,7 @@ void ParallelEvolution::Run(double execution_time, int nthread)
             if ( real_work_time < work_time )
                 continue;
             m_parallel_time += real_work_time;
-            m_board->draw(m_nIteration); 
+            m_board->draw(m_nIteration);
 #else
             m_parallel_time += real_work_time;
 #endif
@@ -174,19 +175,21 @@ void ParallelEvolution::Run(double execution_time, int nthread)
         if(m_parallel_time > execution_time)
         {
             printf("iterations count = %d time = %g\n", m_nIteration, m_parallel_time);
-            init.terminate();
+            delete pGlobControl; pGlobControl = NULL;
             break;
         }
 #endif
     }
+    if (pGlobControl)
+        delete pGlobControl;
 }
 
 /**
     class tbb_parallel_task
-    
-    TBB requires a class for parallel loop implementations. The actual 
-    loop "chunks" are performed using the () operator of the class. 
-    The blocked_range contains the range to calculate. Please see the 
+
+    TBB requires a class for parallel loop implementations. The actual
+    loop "chunks" are performed using the () operator of the class.
+    The blocked_range contains the range to calculate. Please see the
     TBB documentation for more information.
 **/
 #ifndef _CONSOLE
@@ -203,7 +206,7 @@ public:
         return;
     }
 
-    void operator()( const tbb::blocked_range<size_t>& r ) const 
+    void operator()( const tbb::blocked_range<size_t>& r ) const
     {
         int begin = (int)r.begin();            //! capture lower range number for this chunk
         int end = (int)r.end();                //! capture upper range number for this chunk
index ab6f076..57c3df4 100644 (file)
@@ -14,9 +14,9 @@
     limitations under the License.
 */
 
-/** 
-    Evolution.h: Header file for evolution classes; evolution classes do 
-    looped evolution of patterns in a defined 2 dimensional space 
+/**
+    Evolution.h: Header file for evolution classes; evolution classes do
+    looped evolution of patterns in a defined 2 dimensional space
 **/
 
 #ifndef __EVOLUTION_H__
 
 #define WIN32_LEAN_AND_MEAN
 
-#include "tbb/task_scheduler_init.h"
 #include "tbb/blocked_range.h"
 #include "tbb/parallel_for.h"
 #include "tbb/tick_count.h"
+#include "tbb/global_control.h"
 
 #ifndef _CONSOLE
 #include <windows.h>
@@ -55,7 +55,7 @@ class Evolution
 public:
     Evolution( Matrix *m,                //! beginning matrix including initial pattern
                BoardPtr board              //! the board to update
-             ) : m_matrix(m), m_board(board), 
+             ) : m_matrix(m), m_board(board),
                  m_size(m_matrix->height * m_matrix->width), m_done(false)
     {
         //! allocate memory for second matrix data block
@@ -80,7 +80,7 @@ public:
 
     //! Quit() - tell the thread to terminate
     virtual void Quit() { m_done = true; }
-    
+
     //! Step() - performs a single evolutionary generation computation on the game matrix
     virtual void Step() = 0;
 
@@ -92,23 +92,23 @@ public:
         else
             is_paused = false;
     }
-    
+
 protected:
-    /** 
-        UpdateMatrix() - moves the previous destination data to the source 
+    /**
+        UpdateMatrix() - moves the previous destination data to the source
         data block and zeros out destination.
     **/
     void UpdateMatrix();
 
 protected:
     Matrix*         m_matrix;       //! Pointer to initial matrix
-    char*           m_dest;         //! Pointer to calculation destination data    
+    char*           m_dest;         //! Pointer to calculation destination data
     BoardPtr        m_board;        //! The game board to update
     int             m_size;         //! size of the matrix data block
     volatile bool   m_done;         //! a flag used to terminate the thread
     Int32           m_nIteration;   //! current calculation cycle index
     volatile bool   is_paused;      //! is needed to perform next iteration
-    
+
     //! Calculation time of the sequential version (since the start), seconds.
     /**
         This member is updated by the sequential version and read by parallel,
@@ -137,7 +137,7 @@ public:
     SequentialEvolution(Matrix *m, BoardPtr board)
                        : Evolution(m, board)
     {}
-#ifndef _CONSOLE        
+#ifndef _CONSOLE
     virtual void Run() override;
     virtual void Step() override;
 #else
@@ -163,15 +163,15 @@ public:
                      : Evolution(m, board),
                        m_parallel_time(0)
     {
-        // instantiate a task_scheduler_init object and save a pointer to it
-        m_pInit = NULL;
+        // instantiate a global_control object and save a pointer to it
+        m_pGlobControl = NULL;
     }
-    
+
     ~ParallelEvolution()
     {
-        //! delete task_scheduler_init object
-        if (m_pInit != NULL)
-            delete m_pInit;
+        //! delete global_control object
+        if (m_pGlobControl != NULL)
+            delete m_pGlobControl;
     }
 #ifndef _CONSOLE
     virtual void Run() override;
@@ -180,10 +180,10 @@ public:
     virtual void Run(double execution_time, int nthread);
     virtual void Step();
 #endif
-    
+
 
 private:
-    tbb::task_scheduler_init* m_pInit;
+    tbb::global_control* m_pGlobControl;
 
     double m_parallel_time;
 };
index 43dfc10..16e8691 100644 (file)
@@ -20,6 +20,7 @@
 */
 #include "Board.h"
 #include "Form1.h"
+#include "../../../common/utility/get_default_num_threads.h"
 
 #define WIN32_LEAN_AND_MEAN
 
@@ -149,7 +150,7 @@ bool ParseCommandLine(int argc, char * argv [])
     //! command line without parameters
     if(argc == 1)
     {
-        low = tbb::task_scheduler_init::automatic;
+        low = utility::get_default_num_threads();
         high = low;
         execution_time = 5;
         return true;
index de4c66f..011fbff 100644 (file)
@@ -38,6 +38,9 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:   release test
 
 resources:
@@ -51,19 +54,19 @@ endif # macOS*
 release: $(SRCFILES) resources
 ifeq ($(compiler),xl)
        # Avoiding "1586-346 (U) An error occurred during code generation.  The code generation return code was 40." with -O3.
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(EXE) $(SRCFILES) -ltbb -ltbbmalloc $(LIBS)
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(EXE) $(SRCFILES) -ltbb -ltbbmalloc $(LIBS) $(CXX0XFLAGS)
 else
 ifeq ($(UI),mac)
-       $(CXX_UI) -O3 -DNDEBUG $(CXXFLAGS) -c $(MACUISOURCES)
+       $(CXX_UI) -O3 -DNDEBUG $(CXXFLAGS) -c $(MACUISOURCES) $(CXX0XFLAGS)
 endif # macOS
-       $(CXX) -O3 -DNDEBUG $(CXXFLAGS) -o $(EXE) $(SRCFILES) $(MACUIOBJS) -ltbb -ltbbmalloc $(LIBS)
+       $(CXX) -O3 -DNDEBUG $(CXXFLAGS) -o $(EXE) $(SRCFILES) $(MACUIOBJS) -ltbb -ltbbmalloc $(LIBS) $(CXX0XFLAGS)
 endif
 
 debug:  $(SRCFILES) resources
 ifeq ($(UI),mac)
-       $(CXX_UI) -g -O0 -DTBB_USE_DEBUG -D_DEBUG $(CXXFLAGS) -c $(MACUISOURCES)
+       $(CXX_UI) -g -O0 -DTBB_USE_DEBUG -D_DEBUG $(CXXFLAGS) -c $(MACUISOURCES) $(CXX0XFLAGS)
 endif # macOS
-       $(CXX) -g -O0 -DTBB_USE_DEBUG -D_DEBUG $(CXXFLAGS) -o $(EXE) $(SRCFILES) $(MACUIOBJS) -ltbb_debug -ltbbmalloc_debug $(LIBS)
+       $(CXX) -g -O0 -DTBB_USE_DEBUG -D_DEBUG $(CXXFLAGS) -o $(EXE) $(SRCFILES) $(MACUIOBJS) -ltbb_debug -ltbbmalloc_debug $(LIBS) $(CXX0XFLAGS)
 
 clean:
        $(RM) $(EXE) *.o *.d
index dc5e8f9..f55108d 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;tbbmalloc_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;tbbmalloc_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;tbbmalloc.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;tbbmalloc.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;tbbmalloc.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;tbbmalloc.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;tbbmalloc_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;tbbmalloc_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
index c996e1e..ed0fb4e 100644 (file)
@@ -27,7 +27,6 @@
 #include <cstring>
 
 #include "tbb/tick_count.h"
-#include "tbb/task_scheduler_init.h"
 #include "pover_global.h"
 #include "polyover.h"
 #include "pover_video.h"
@@ -39,7 +38,7 @@ using namespace std;
 const char *faceNames[] = { "North", "East", "South", "West" };
 #endif
 
-/** 
+/**
 **/
 int main( int argc, char **argv) {
     pover_video poly;
@@ -107,7 +106,7 @@ void Usage(int argc, char **argv) {
     if(cmdTail == NULL)  {
         cmdTail = *argv;
     }
-    else { 
+    else {
         cmdTail++;
     }
     cout << cmdTail << " [threads[:threads2]] [--polys npolys] [--size nnnxnnn] [--seed nnn]" << std::endl;
@@ -363,7 +362,7 @@ bool GenerateMap(Polygon_map_t **newMap, int xSize, int ySize, int gNPolygons, c
         (**newMap)[polyIndx].get(&xlow,&ylow,&xhigh,&yhigh);
         xlnew = xlow;
         xhnew = xhigh;
-        ylnew = ylow; 
+        ylnew = ylow;
         yhnew = yhigh;
         // can this polygon be expanded along the chosen side?
         switch(checkSide) {
index 62a7b8a..2f517e0 100644 (file)
 #include <assert.h>
 #include "tbb/tick_count.h"
 #include "tbb/blocked_range.h"
-#include "tbb/task_scheduler_init.h"
 #include "tbb/parallel_for.h"
-#include "tbb/mutex.h"
 #include "tbb/spin_mutex.h"
+#include "tbb/global_control.h"
+#include "../../common/utility/get_default_num_threads.h"
 #include "polyover.h"
 #include "polymain.h"
 #include "pover_video.h"
@@ -125,8 +125,8 @@ void NaiveParallelOverlay(Polygon_map_t *&result_map, Polygon_map_t &polymap1, P
 // -----------------------------------
     bool automatic_threadcount = false;
 
-    if(gThreadsLow == THREADS_UNSET || gThreadsLow == tbb::task_scheduler_init::automatic) {
-        gThreadsLow = gThreadsHigh = tbb::task_scheduler_init::automatic;
+    if(gThreadsLow == THREADS_UNSET || gThreadsLow == utility::get_default_num_threads()) {
+        gThreadsLow = gThreadsHigh = utility::get_default_num_threads();
         automatic_threadcount = true;
     }
     result_map = new Polygon_map_t;
@@ -140,7 +140,7 @@ void NaiveParallelOverlay(Polygon_map_t *&result_map, Polygon_map_t &polymap1, P
     int grain_size = gGrainSize;
 
     for(int nthreads = gThreadsLow; nthreads <= gThreadsHigh; nthreads++) {
-        tbb::task_scheduler_init init(nthreads);
+        tbb::global_control c(tbb::global_control::max_allowed_parallelism, nthreads);
         if(gIsGraphicalVersion) {
             RPolygon *xp = new RPolygon(0, 0, gMapXSize-1, gMapYSize-1, 0, 0, 0);  // Clear the output space
             delete xp;
@@ -200,7 +200,7 @@ void split_at( Flagged_map_t& in_map, Flagged_map_t &left_out, Flagged_map_t &ri
 // vectors of pointers, and each range owns its maps (has to free them on destruction.)
 template <typename T>
 class blocked_range_with_maps {
-    
+
     typedef blocked_range<T> my_range_type;
 
 private:
@@ -361,8 +361,8 @@ void SplitParallelOverlay(Polygon_map_t **result_map, Polygon_map_t *polymap1, P
     double domainSplitParallelTime;
     tbb::tick_count t0, t1;
     tbb::spin_mutex *resultMutex;
-    if(gThreadsLow == THREADS_UNSET || gThreadsLow == tbb::task_scheduler_init::automatic ) {
-        gThreadsLow = gThreadsHigh = tbb::task_scheduler_init::automatic;
+    if(gThreadsLow == THREADS_UNSET || gThreadsLow == utility::get_default_num_threads() ) {
+        gThreadsLow = gThreadsHigh = utility::get_default_num_threads();
         automatic_threadcount = true;
     }
     *result_map = new Polygon_map_t;
@@ -380,7 +380,7 @@ void SplitParallelOverlay(Polygon_map_t **result_map, Polygon_map_t *polymap1, P
     grain_size = gGrainSize;
 #endif
     for(nthreads = gThreadsLow; nthreads <= gThreadsHigh; nthreads++) {
-        tbb::task_scheduler_init init(nthreads);
+        tbb::global_control c(tbb::global_control::max_allowed_parallelism, nthreads);
         if(gIsGraphicalVersion) {
             RPolygon *xp = new RPolygon(0, 0, gMapXSize-1, gMapYSize-1, 0, 0, 0);  // Clear the output space
             delete xp;
@@ -477,8 +477,8 @@ void SplitParallelOverlayCV(concurrent_Polygon_map_t **result_map, Polygon_map_t
     bool automatic_threadcount = false;
     double domainSplitParallelTime;
     tbb::tick_count t0, t1;
-    if(gThreadsLow == THREADS_UNSET || gThreadsLow == tbb::task_scheduler_init::automatic ) {
-        gThreadsLow = gThreadsHigh = tbb::task_scheduler_init::automatic;
+    if(gThreadsLow == THREADS_UNSET || gThreadsLow == utility::get_default_num_threads() ) {
+        gThreadsLow = gThreadsHigh = utility::get_default_num_threads();
         automatic_threadcount = true;
     }
     *result_map = new concurrent_Polygon_map_t;
@@ -495,7 +495,7 @@ void SplitParallelOverlayCV(concurrent_Polygon_map_t **result_map, Polygon_map_t
     grain_size = gGrainSize;
 #endif
     for(nthreads = gThreadsLow; nthreads <= gThreadsHigh; nthreads++) {
-        tbb::task_scheduler_init init(nthreads);
+        tbb::global_control c(tbb::global_control::max_allowed_parallelism, nthreads);
         if(gIsGraphicalVersion) {
             RPolygon *xp = new RPolygon(0, 0, gMapXSize-1, gMapYSize-1, 0, 0, 0);  // Clear the output space
             delete xp;
@@ -516,7 +516,7 @@ void SplitParallelOverlayCV(concurrent_Polygon_map_t **result_map, Polygon_map_t
         }
 #if _DEBUG
         {
-            
+
             Polygon_map_t s_result_map;
             for(concurrent_Polygon_map_t::const_iterator ci = (*result_map)->begin(); ci != (*result_map)->end(); ++ci) {
                 s_result_map.push_back(*ci);
@@ -602,8 +602,8 @@ void SplitParallelOverlayETS(ETS_Polygon_map_t **result_map, Polygon_map_t *poly
     bool automatic_threadcount = false;
     double domainSplitParallelTime;
     tbb::tick_count t0, t1;
-    if(gThreadsLow == THREADS_UNSET || gThreadsLow == tbb::task_scheduler_init::automatic ) {
-        gThreadsLow = gThreadsHigh = tbb::task_scheduler_init::automatic;
+    if(gThreadsLow == THREADS_UNSET || gThreadsLow == utility::get_default_num_threads() ) {
+        gThreadsLow = gThreadsHigh = utility::get_default_num_threads();
         automatic_threadcount = true;
     }
     *result_map = new ETS_Polygon_map_t;
@@ -620,7 +620,7 @@ void SplitParallelOverlayETS(ETS_Polygon_map_t **result_map, Polygon_map_t *poly
     grain_size = gGrainSize;
 #endif
     for(nthreads = gThreadsLow; nthreads <= gThreadsHigh; nthreads++) {
-        tbb::task_scheduler_init init(nthreads);
+        tbb::global_control c(tbb::global_control::max_allowed_parallelism, nthreads);
         if(gIsGraphicalVersion) {
             RPolygon *xp = new RPolygon(0, 0, gMapXSize-1, gMapYSize-1, 0, 0, 0);  // Clear the output space
             delete xp;
@@ -642,7 +642,7 @@ void SplitParallelOverlayETS(ETS_Polygon_map_t **result_map, Polygon_map_t *poly
         }
 #if _DEBUG
         {
-            
+
             Polygon_map_t s_result_map;
             flattened2d<ETS_Polygon_map_t> psv = flatten2d(**result_map);
             s_result_map.push_back(RPolygon(0,0,mapxSize, mapySize));
index ddc09ff..3a0e5af 100644 (file)
@@ -18,7 +18,6 @@
  * polyover.h : extern declarations for polyover.cpp
 */
 #include "rpolygon.h"
-#include "tbb/mutex.h"
 #include "tbb/spin_mutex.h"
 
 extern void OverlayOnePolygonWithMap(Polygon_map_t *resultMap, RPolygon *myPoly, Polygon_map_t  *map2, tbb::spin_mutex *rMutex);
index 15cd450..bccf825 100644 (file)
@@ -22,7 +22,7 @@
 #include "polymain.h"
 #include "pover_video.h"
 #include "tbb/tick_count.h"
-#include "tbb/task_scheduler_init.h"
+#include "../../common/utility/get_default_num_threads.h"
 #ifndef _WIN32
 #include <sys/time.h>
 #include <unistd.h>
@@ -48,14 +48,14 @@ using namespace std;
 
 bool g_next_frame() {
     if(++n_next_frame_calls >= frame_skips) { // the data race here is benign
-        n_next_frame_calls = 0; 
+        n_next_frame_calls = 0;
         return gVideo->next_frame();
-    } 
+    }
     return gVideo->running;
 }
 
 bool g_last_frame() {
-    if(n_next_frame_calls) return gVideo->next_frame(); 
+    if(n_next_frame_calls) return gVideo->next_frame();
     return gVideo->running;
 }
 
@@ -109,7 +109,7 @@ void pover_video::on_process() {
         if(gCsvFile.is_open()) {
             gCsvFile << "Serial Time," << gSerialTime << std::endl;
             gCsvFile << "Threads,";
-            if(gThreadsLow == THREADS_UNSET || gThreadsLow == tbb::task_scheduler_init::automatic) {
+            if(gThreadsLow == THREADS_UNSET || gThreadsLow == utility::get_default_num_threads()) {
                 gCsvFile << "Threads,Automatic";
             }
             else {
index b2b4b93..c3c1e34 100644 (file)
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = YES;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++11";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_ENABLE_OBJC_ARC = YES;
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = YES;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++11";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_ENABLE_OBJC_ARC = YES;
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
index b66999d..2202524 100644 (file)
@@ -29,7 +29,7 @@ TBBLIB_DEBUG = -ltbb_debug
 ifeq ($(offload), mic)
 override CXXFLAGS += -D__TBB_MIC_OFFLOAD=1 -offload-attribute-target=mic
 # Replace -ltbb with -tbb in the offload mode
-TBBLIB = -tbb
+TBBLIB = -ltbb
 TBBLIB_DEBUG += -offload-option,mic,ld,"-ltbb_debug"
 # Currently only console mode is supported in offload version
 override UI=con
@@ -48,6 +48,9 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:   release test
 
 resources:
@@ -60,15 +63,15 @@ endif # macOS*
 
 release: resources
 ifeq ($(UI),mac)
-       $(CXX_UI) -O2 -DNDEBUG $(CXXFLAGS) -c $(MACUISOURCES)
+       $(CXX_UI) -O2 -DNDEBUG $(CXXFLAGS) -c $(MACUISOURCES) $(CXX0XFLAGS)
 endif # macOS
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(EXE) $(SOURCES) $(MACUIOBJS) $(TBBLIB) $(LIBS)
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(EXE) $(SOURCES) $(MACUIOBJS) $(TBBLIB) $(LIBS) $(CXX0XFLAGS)
 
 debug: resources
 ifeq ($(UI),mac)
-       $(CXX_UI) -g -O0 -DTBB_USE_DEBUG $(CXXFLAGS) -c $(MACUISOURCES)
+       $(CXX_UI) -g -O0 -DTBB_USE_DEBUG $(CXXFLAGS) -c $(MACUISOURCES) $(CXX0XFLAGS)
 endif # macOS
-       $(CXX) -g -O0 -DTBB_USE_DEBUG $(CXXFLAGS) -o $(EXE) $(SOURCES) $(MACUIOBJS) $(TBBLIB_DEBUG) $(LIBS)
+       $(CXX) -g -O0 -DTBB_USE_DEBUG $(CXXFLAGS) -o $(EXE) $(SOURCES) $(MACUIOBJS) $(TBBLIB_DEBUG) $(LIBS) $(CXX0XFLAGS)
 
 clean:
        $(RM) $(EXE) *.o *.d
index 56059f3..cb43ded 100644 (file)
 
 #include <iostream>
 #include "tbb/tick_count.h"
+#include "tbb/global_control.h"
 #include "../../common/utility/utility.h"
+#include "../../common/utility/get_default_num_threads.h"
 
 #include "seismic_video.h"
 #include "universe.h"
-#include "tbb/task_scheduler_init.h"
 
 Universe u;
 
@@ -40,23 +41,9 @@ struct RunOptions {
     }
 };
 
-int do_get_default_num_threads() {
-    int threads;
-#if __TBB_MIC_OFFLOAD
-    #pragma offload target(mic) out(threads)
-#endif // __TBB_MIC_OFFLOAD
-    threads = tbb::task_scheduler_init::default_num_threads();
-    return threads;
-}
-
-int get_default_num_threads() {
-    static int threads = do_get_default_num_threads();
-    return threads;
-}
-
 RunOptions ParseCommandLine(int argc, char *argv[]){
     // zero number of threads means to run serial version
-    utility::thread_number_range threads(get_default_num_threads,0,get_default_num_threads());
+    utility::thread_number_range threads(utility::get_default_num_threads,0,utility::get_default_num_threads());
 
     int numberOfFrames = 0;
     bool silent = false;
@@ -106,7 +93,7 @@ int main(int argc, char *argv[])
 
                 #pragma offload target(mic) in(u, numberOfFrames, p, dmem), out(pMem:length(memSize))
                 {
-                    // It is necessary to update the pointer on mic 
+                    // It is necessary to update the pointer on mic
                     // since the address spaces on host and on target are different
                     dmem.set_address(pMem);
                     u.SetDrawingMemory(dmem);
@@ -117,7 +104,7 @@ int main(int argc, char *argv[])
                             u.SerialUpdateUniverse();
                         }
                     } else {
-                        tbb::task_scheduler_init init(p);
+                        tbb::global_control c(tbb::global_control::max_allowed_parallelism, p);
                         for( int i=0; i<numberOfFrames; ++i ) {
                             u.ParallelUpdateUniverse();
                         }
index 3338911..9e6ad79 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
index e19d705..c66848f 100644 (file)
@@ -16,7 +16,7 @@
 
 #include "seismic_video.h"
 #include "universe.h"
-#include "tbb/task_scheduler_init.h"
+#include "tbb/global_control.h"
 
 const char * const SeismicVideo::titles[2] = {"Seismic Simulation: Serial", "Seismic Simulation: Parallel"};
 void SeismicVideo::on_mouse(int x, int y, int key) {
@@ -37,7 +37,7 @@ void SeismicVideo::on_key(int key) {
 }
 
 void SeismicVideo::on_process() {
-    tbb::task_scheduler_init Init(threadsHigh);
+    tbb::global_control c(tbb::global_control::max_allowed_parallelism, threadsHigh);
     for( int frames = 0; numberOfFrames_==0 || frames<numberOfFrames_; ++frames ) {
         if( initIsParallel )
             u_.ParallelUpdateUniverse();
index e7b91fd..c865d44 100644 (file)
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++11";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_ENABLE_OBJC_ARC = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++11";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_ENABLE_OBJC_ARC = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
index 9451b80..6b946d7 100644 (file)
@@ -69,6 +69,9 @@ endif # X
 
 MYCXXFLAGS = $(CXXFLAGS) $(UI_CXXFLAGS)
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all: build run
 release: build
 debug: build_debug
@@ -168,9 +171,9 @@ ifeq ($(UI),mac)
        cp ../../common/gui/xcode/tbbExample/tbbExample-Info.plist $(NAME)$(SUFFIX).app/Contents/Info.plist
        cp ../../common/gui/xcode/tbbExample/PkgInfo $(NAME)$(SUFFIX).app/Contents
        cp ../../common/gui/xcode/tbbExample/en.lproj/* $(APPRES)/en.lproj
-       $(CXX_UI) $(MYCXXFLAGS) $(CXXFLAGS) -c $(MACUISOURCES)
+       $(CXX_UI) $(MYCXXFLAGS) $(CXXFLAGS) -c $(MACUISOURCES) $(CXX0XFLAGS)
 endif # macOS*
-       $(CXX) $(MYCXXFLAGS) -o $@ $(SOURCE) $(MACUIOBJS) $(LIBS)
+       $(CXX) $(MYCXXFLAGS) -o $@ $(SOURCE) $(MACUIOBJS) $(LIBS) $(CXX0XFLAGS)
        $(RM) *.o
 
 clean: VERSION = *
index 2e7881e..a465d92 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
index 36106de..325605e 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
@@ -182,7 +182,7 @@ void DirectXBase::SetDpi(float dpi)
 void DirectXBase::UpdateForWindowSizeChange()
 {
     // Only handle window size changed if there is no pending DPI change.
-    if (m_dpi != DisplayProperties::LogicalDpi)
+    if (m_dpi != DisplayInformation::GetForCurrentView()->LogicalDpi)
         return;
 
     if (m_window->Bounds.Width  != m_windowBounds.Width ||
@@ -17,7 +17,6 @@
 
 #include "pch.h"
 #include "DirectXPage.xaml.h"
-#include "tbb/tbb.h"
 
 using namespace tbbTachyon;
 
@@ -59,15 +58,15 @@ DirectXPage::DirectXPage() :
     m_renderer->Initialize(
         Window::Current->CoreWindow,
         this,
-        DisplayProperties::LogicalDpi
+               DisplayInformation::GetForCurrentView()->LogicalDpi
         );
 
     m_eventToken = CompositionTarget::Rendering::add(ref new EventHandler<Object^>(this, &DirectXPage::OnRendering));
 
-    int num_threads = 2*tbb::task_scheduler_init::default_num_threads();
+    int num_threads = 2*utility::get_default_num_threads();
     // The thread slider has geometric sequence with several intermediate steps for each interval between 2^N and 2^(N+1).
     // The nearest (from below) the power of 2.
-    int i_base = log2(num_threads);
+    int i_base = int(log2(num_threads));
     int base = 1 << i_base;
     // The step size for the current interval.
     int step = base / num_interval_steps;
@@ -75,7 +74,7 @@ DirectXPage::DirectXPage() :
     int i_step = (num_threads-base)/step;
 
     ThreadsSlider->Maximum = (i_base-interval_step_power)*num_interval_steps + i_step;
-    global_number_of_threads = m_number_of_threads = tbb::task_scheduler_init::automatic;
+    global_number_of_threads = m_number_of_threads = utility::get_default_num_threads();
 }
 
 DirectXPage::~DirectXPage()
@@ -118,9 +117,9 @@ void tbbTachyon::DirectXPage::ThreadsSliderValueChanged(Platform::Object^ sender
     int step = max(1,base/num_interval_steps);
     m_number_of_threads = base + (pos%num_interval_steps)*step;
 
-    if (m_number_of_threads == 0) m_number_of_threads = tbb::task_scheduler_init::automatic;
+    if (m_number_of_threads == 0) m_number_of_threads = utility::get_default_num_threads();
 
-    NumberOfThreadsTextBlock->Text="Number Of Threads: " + (m_number_of_threads == tbb::task_scheduler_init::automatic? "Auto": m_number_of_threads.ToString());
+    NumberOfThreadsTextBlock->Text="Number Of Threads: " + (m_number_of_threads == utility::get_default_num_threads()? "Auto": m_number_of_threads.ToString());
     if (global_number_of_threads != m_number_of_threads){
         ThreadsApply->Visibility=Windows::UI::Xaml::Visibility::Visible;
     }else{
diff --git a/examples/parallel_for/tachyon/msvs/uwp/Package.appxmanifest b/examples/parallel_for/tachyon/msvs/uwp/Package.appxmanifest
new file mode 100644 (file)
index 0000000..71d2555
--- /dev/null
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<Package
+  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
+  xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
+  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
+  IgnorableNamespaces="uap mp">
+
+  <Identity
+    Name="551ef478-a6dc-40b3-a3ff-10052625a781"
+    Publisher="CN=Administrator"
+    Version="1.0.0.0" />
+
+  <mp:PhoneIdentity PhoneProductId="551ef478-a6dc-40b3-a3ff-10052625a781" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
+
+  <Properties>
+    <DisplayName>tbbTachyon</DisplayName>
+    <PublisherDisplayName>Administrator</PublisherDisplayName>
+    <Logo>Assets\StoreLogo.png</Logo>
+  </Properties>
+
+  <Dependencies>
+    <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
+  </Dependencies>
+
+  <Resources>
+    <Resource Language="x-generate"/>
+  </Resources>
+
+  <Applications>
+    <Application Id="App"
+      Executable="$targetnametoken$.exe"
+      EntryPoint="tbbTachyon.App">
+      <uap:VisualElements
+        DisplayName="tbbTachyon"
+        Square150x150Logo="Assets\Square150x150Logo.png"
+        Square44x44Logo="Assets\Square44x44Logo.png"
+        Description="tbbTachyon"
+        BackgroundColor="transparent">
+        <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
+        <uap:SplashScreen Image="Assets\SplashScreen.png" />
+      </uap:VisualElements>
+    </Application>
+  </Applications>
+
+  <Capabilities>
+    <Capability Name="internetClient" />
+  </Capabilities>
+</Package>
\ No newline at end of file
@@ -29,9 +29,14 @@ if ("%4") == ("") set dat_file="%output_dir%\..\..\dat\balls.dat"
 :: Actually we can set install root by ourselves
 if ("%TBBROOT%") == ("") set TBBROOT=%~dp0..\..\..\..\..\
 
-:: ordered from oldest to newest, so we end with newest available version
-if ("%VS110COMNTOOLS%") NEQ ("") set vc_dir=vc11_ui
-if ("%VS120COMNTOOLS%") NEQ ("") set vc_dir=vc12_ui
+:: Getting vs folders ordered from oldest to newest, so we end with newest available version
+if ("%VS140COMNTOOLS%") NEQ ("") set vc_dir=vc14_uwp
+:: To use Microsoft* Visual Studio* 2017 IDE, make sure the variable VS150COMNTOOLS is set in your IDE instance.
+:: If it is not, try running Microsoft Visual Studio 2017 from Microsoft* Developer Command Prompt* for VS 2017.
+:: For details, see https://developercommunity.visualstudio.com/content/problem/730/vs154-env-var-vs150comntools-missing-from-build-sy.html
+if ("%VS150COMNTOOLS%") NEQ ("") set vc_dir=vc14_uwp
+:: The same comment also applies to Microsoft Visual Studio 2019 and variable VS160COMNTOOLS
+if ("%VS160COMNTOOLS%") NEQ ("") set vc_dir=vc14_uwp
 echo Using %vc_dir% libraries
 
 if exist "%TBBROOT%\bin\%arch%\%vc_dir%\tbb%postfix%.dll" set interim_path=bin\%arch%
diff --git a/examples/parallel_for/tachyon/msvs/uwp/tbbTachyon.sln b/examples/parallel_for/tachyon/msvs/uwp/tbbTachyon.sln
new file mode 100644 (file)
index 0000000..594bd78
--- /dev/null
@@ -0,0 +1,32 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tbbTachyon", "tbbTachyon.vcxproj", "{77FEB0A5-648A-4561-8A9D-61C7818B4490}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|x64 = Debug|x64
+               Debug|x86 = Debug|x86
+               Release|x64 = Release|x64
+               Release|x86 = Release|x86
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {77FEB0A5-648A-4561-8A9D-61C7818B4490}.Debug|x64.ActiveCfg = Debug|x64
+               {77FEB0A5-648A-4561-8A9D-61C7818B4490}.Debug|x64.Build.0 = Debug|x64
+               {77FEB0A5-648A-4561-8A9D-61C7818B4490}.Debug|x64.Deploy.0 = Debug|x64
+               {77FEB0A5-648A-4561-8A9D-61C7818B4490}.Debug|x86.ActiveCfg = Debug|Win32
+               {77FEB0A5-648A-4561-8A9D-61C7818B4490}.Debug|x86.Build.0 = Debug|Win32
+               {77FEB0A5-648A-4561-8A9D-61C7818B4490}.Debug|x86.Deploy.0 = Debug|Win32
+               {77FEB0A5-648A-4561-8A9D-61C7818B4490}.Release|x64.ActiveCfg = Release|x64
+               {77FEB0A5-648A-4561-8A9D-61C7818B4490}.Release|x64.Build.0 = Release|x64
+               {77FEB0A5-648A-4561-8A9D-61C7818B4490}.Release|x64.Deploy.0 = Release|x64
+               {77FEB0A5-648A-4561-8A9D-61C7818B4490}.Release|x86.ActiveCfg = Release|Win32
+               {77FEB0A5-648A-4561-8A9D-61C7818B4490}.Release|x86.Build.0 = Release|Win32
+               {77FEB0A5-648A-4561-8A9D-61C7818B4490}.Release|x86.Deploy.0 = Release|Win32
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="Debug|Win32">
       <Configuration>Debug</Configuration>
     </ProjectConfiguration>
   </ItemGroup>
   <PropertyGroup Label="Globals">
-    <ProjectGuid>{e20cb432-6730-4021-a372-1c81a333518a}</ProjectGuid>
+    <ProjectGuid>{77feb0a5-648a-4561-8a9d-61c7818b4490}</ProjectGuid>
     <RootNamespace>tbbTachyon</RootNamespace>
     <DefaultLanguage>en-US</DefaultLanguage>
-    <VCTargetsPath Condition="'$(VCTargetsPath11)' != '' and '$(VSVersion)' == '' and '$(VisualStudioVersion)' == ''">$(VCTargetsPath11)</VCTargetsPath>
-    <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+    <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
     <AppContainerApplication>true</AppContainerApplication>
+    <ApplicationType>Windows Store</ApplicationType>
+    <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
+    <WindowsTargetPlatformMinVersion>10.0.10586.0</WindowsTargetPlatformMinVersion>
+    <ApplicationTypeRevision>10.0</ApplicationTypeRevision>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
-    <PlatformToolset>v120</PlatformToolset>
-    <UseIntelTBB>true</UseIntelTBB>
+    <PlatformToolset>v140</PlatformToolset>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
-    <PlatformToolset>v120</PlatformToolset>
-    <UseIntelTBB>true</UseIntelTBB>
+    <PlatformToolset>v140</PlatformToolset>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>false</WholeProgramOptimization>
-    <PlatformToolset>v120</PlatformToolset>
-    <UseIntelTBB>true</UseIntelTBB>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>false</WholeProgramOptimization>
-    <PlatformToolset>v120</PlatformToolset>
-    <UseIntelTBB>true</UseIntelTBB>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <PlatformToolset>v140</PlatformToolset>
+    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
+    <Import Project="$(VSINSTALLDIR)\Common7\IDE\Extensions\Microsoft\VsGraphics\ImageContentTask.props" />
+    <Import Project="$(VSINSTALLDIR)\Common7\IDE\Extensions\Microsoft\VsGraphics\MeshContentTask.props" />
+    <Import Project="$(VSINSTALLDIR)\Common7\IDE\Extensions\Microsoft\VsGraphics\ShaderGraphContentTask.props" />
   </ImportGroup>
   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
   </ImportGroup>
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup>
+    
     <PackageCertificateKeyFile>tbbTachyon_TemporaryKey.pfx</PackageCertificateKeyFile>
     <AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>
-    <PackageCertificateThumbprint>5E3EA4A6008AD66D2487EFC68BB366981685295D</PackageCertificateThumbprint>
+    
   </PropertyGroup>
+  
   <ItemDefinitionGroup>
     <Link>
       <AdditionalDependencies>d2d1.lib; d3d11.lib; dxgi.lib; ole32.lib; windowscodecs.lib; dwrite.lib; dxguid.lib; %(AdditionalDependencies)</AdditionalDependencies>
@@ -1,34 +1,5 @@
 ï»¿<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Page Include="Common\StandardStyles.xaml">
-      <Filter>Resources\Common</Filter>
-    </Page>
-    <Image Include="Assets\Logo.png">
-      <Filter>Resources\Assets</Filter>
-    </Image>
-    <Image Include="Assets\SmallLogo.png">
-      <Filter>Resources\Assets</Filter>
-    </Image>
-    <Image Include="Assets\StoreLogo.png">
-      <Filter>Resources\Assets</Filter>
-    </Image>
-    <Image Include="Assets\SplashScreen.png">
-      <Filter>Resources\Assets</Filter>
-    </Image>
-    <Filter Include="Resources">
-      <UniqueIdentifier>{a5d732ac-1380-4b99-910c-c5685c48ec08}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Resources\Common">
-      <UniqueIdentifier>e20cb432-6730-4021-a372-1c81a333518a</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Resources\Assets">
-      <UniqueIdentifier>ac5c7e6e-0221-4a78-85c7-20768e92cf5a</UniqueIdentifier>
-    </Filter>
-    <Page Include="DirectXPage.xaml">
-      <Filter>Frontend</Filter>
-    </Page>
-  </ItemGroup>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
     <ClCompile Include="App.xaml.cpp" />
     <ClCompile Include="DirectXPage.xaml.cpp" />
@@ -50,6 +21,9 @@
     <ClCompile Include="..\..\src\camera.cpp">
       <Filter>Backend</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\..\common\gui\convideo.cpp">
+      <Filter>Backend</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\src\coordsys.cpp">
       <Filter>Backend</Filter>
     </ClCompile>
     <ClCompile Include="..\..\src\light.cpp">
       <Filter>Backend</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\main.cpp">
+      <Filter>Backend</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\src\objbound.cpp">
       <Filter>Backend</Filter>
     </ClCompile>
     <ClCompile Include="..\..\src\parse.cpp">
       <Filter>Backend</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\plane.cpp">
+    <ClCompile Include="..\..\src\ppm.cpp">
       <Filter>Backend</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\ppm.cpp">
+    <ClCompile Include="..\..\src\plane.cpp">
       <Filter>Backend</Filter>
     </ClCompile>
     <ClCompile Include="..\..\src\pthread.cpp">
     <ClCompile Include="..\..\src\vol.cpp">
       <Filter>Backend</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\..\..\common\gui\convideo.cpp">
-      <Filter>Backend</Filter>
-    </ClCompile>
-    <ClCompile Include="..\..\src\main.cpp">
-      <Filter>Backend</Filter>
-    </ClCompile>
     <ClCompile Include="DirectXBase.cpp">
       <Filter>Frontend</Filter>
     </ClCompile>
     </ClInclude>
   </ItemGroup>
   <ItemGroup>
-    <None Include="Assets\balls.dat">
-      <Filter>Resources\Assets</Filter>
-    </None>
+    <Image Include="Assets\Logo.png">
+      <Filter>Resources\Assests</Filter>
+    </Image>
+    <Image Include="Assets\SmallLogo.png">
+      <Filter>Resources\Assests</Filter>
+    </Image>
+    <Image Include="Assets\SplashScreen.png">
+      <Filter>Resources\Assests</Filter>
+    </Image>
+    <Image Include="Assets\StoreLogo.png">
+      <Filter>Resources\Assests</Filter>
+    </Image>
+  </ItemGroup>
+  <ItemGroup>
     <None Include="tbb.dll">
       <Filter>Libraries</Filter>
     </None>
-    <None Include="tbbmalloc.dll">
+    <None Include="tbb_debug.dll">
       <Filter>Libraries</Filter>
     </None>
-    <None Include="tbb_debug.dll">
+    <None Include="tbbmalloc.dll">
       <Filter>Libraries</Filter>
     </None>
     <None Include="tbbmalloc_debug.dll">
     <None Include="tbbTachyon_TemporaryKey.pfx">
       <Filter>Frontend</Filter>
     </None>
+    <None Include="Assets\balls.dat">
+      <Filter>Resources\Assests</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <Page Include="DirectXPage.xaml">
+      <Filter>Frontend</Filter>
+    </Page>
+    <Page Include="Common\StandardStyles.xaml">
+      <Filter>Resources\Common</Filter>
+    </Page>
   </ItemGroup>
   <ItemGroup>
     <Filter Include="Libraries">
-      <UniqueIdentifier>{a70d1cf5-5cc8-4f50-a6d2-92d2b973df86}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="Scripts">
-      <UniqueIdentifier>{eb414f7a-2d2d-4ff5-93fe-458cc3021423}</UniqueIdentifier>
+      <UniqueIdentifier>{5aa279ad-b96c-4b37-b7b8-ac9e2fc6a71a}</UniqueIdentifier>
     </Filter>
     <Filter Include="Backend">
-      <UniqueIdentifier>{77eb2f1c-7dec-4360-8989-e9ad18034e10}</UniqueIdentifier>
+      <UniqueIdentifier>{e4177cac-d0b5-40da-a461-f198ad2a979a}</UniqueIdentifier>
     </Filter>
     <Filter Include="Frontend">
-      <UniqueIdentifier>{d825a994-3d08-4764-9945-ec9aafc1f496}</UniqueIdentifier>
+      <UniqueIdentifier>{7d1b3680-1522-4d95-8632-7824b4d5cdbe}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Resources">
+      <UniqueIdentifier>{5446688c-27e2-4099-bda8-776ce360b3e4}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Resources\Assests">
+      <UniqueIdentifier>{b39c6427-41fc-44e7-b9f6-55284a523b3f}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Resources\Common">
+      <UniqueIdentifier>{1f1ca390-e43c-42ba-b04d-6c004ef14b52}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Scripts">
+      <UniqueIdentifier>{16f9ea87-9c30-407c-8e9e-818f60e1c163}</UniqueIdentifier>
     </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <CustomBuild Include="copy_libraries_and_assets.bat">
-      <Filter>Scripts</Filter>
-    </CustomBuild>
   </ItemGroup>
   <ItemGroup>
     <ApplicationDefinition Include="App.xaml">
       <Filter>Frontend</Filter>
     </AppxManifest>
   </ItemGroup>
-</Project>
+  <ItemGroup>
+    <CustomBuild Include="copy_libraries_and_assets.bat">
+      <Filter>Scripts</Filter>
+    </CustomBuild>
+  </ItemGroup>
+</Project>
\ No newline at end of file
@@ -20,7 +20,6 @@
 #include <process.h>
 #include <thread>
 #include "../../src/tachyon_video.h"
-#include "tbb/tbb.h"
 
 using namespace Microsoft::WRL;
 using namespace Windows::Foundation;
@@ -133,9 +132,9 @@ void tbbTachyonRenderer::Render()
 #if SHOW_TEXT
     if (video && video->running)
         global_elapsedTime=(long)(time(NULL)-global_startTime);
-    
+
     Platform::String^ text= "Running in " +
-        (global_number_of_threads == tbb::task_scheduler_init::automatic? "all hardware threads: ":
+        (global_number_of_threads == utility::get_default_num_threads()? "all hardware threads: ":
             global_number_of_threads.ToString() + (global_number_of_threads==1?" thread: ":" threads: ")) +
         global_elapsedTime.ToString() + (global_elapsedTime>1?" seconds":" second");
 
diff --git a/examples/parallel_for/tachyon/msvs/win8ui/Package.appxmanifest b/examples/parallel_for/tachyon/msvs/win8ui/Package.appxmanifest
deleted file mode 100644 (file)
index df3c07a..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest">
-  <Identity Name="36816596-d167-42e1-bcc0-cd3ec4577997" Publisher="CN=tbbtest" Version="1.0.0.18" />
-  <Properties>
-    <DisplayName>Tachyon Demo</DisplayName>
-    <PublisherDisplayName>test</PublisherDisplayName>
-    <Logo>Assets\StoreLogo.png</Logo>
-  </Properties>
-  <Prerequisites>
-    <OSMinVersion>6.2.0</OSMinVersion>
-    <OSMaxVersionTested>6.2.0</OSMaxVersionTested>
-  </Prerequisites>
-  <Resources>
-    <Resource Language="x-generate" />
-  </Resources>
-  <Applications>
-    <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="tbbTachyon.App">
-      <VisualElements DisplayName="Tachyon Demo" Logo="Assets\Logo.png" SmallLogo="Assets\SmallLogo.png" Description="Tachyon Demo demonstrates how to use Intel(R) Threading Building Blocks library for Windows Store applications." ForegroundText="light" BackgroundColor="#464646">
-        <DefaultTile ShowName="allLogos" />
-        <SplashScreen Image="Assets\SplashScreen.png" />
-        <InitialRotationPreference>
-          <Rotation Preference="landscape" />
-        </InitialRotationPreference>
-      </VisualElements>
-    </Application>
-  </Applications>
-  <Capabilities>
-    <Capability Name="internetClient" />
-  </Capabilities>
-</Package>
\ No newline at end of file
diff --git a/examples/parallel_for/tachyon/msvs/win8ui/tbbTachyon.sln b/examples/parallel_for/tachyon/msvs/win8ui/tbbTachyon.sln
deleted file mode 100644 (file)
index ed64646..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0.40629.0
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tbbTachyon", "tbbTachyon.vcxproj", "{E20CB432-6730-4021-A372-1C81A333518A}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E6DDEA39-7910-47F9-A0E3-56AD7E62ACBD}"
-EndProject
-Global
-       GlobalSection(SolutionConfigurationPlatforms) = preSolution
-               Debug|Win32 = Debug|Win32
-               Debug|x64 = Debug|x64
-               Release|Win32 = Release|Win32
-               Release|x64 = Release|x64
-       EndGlobalSection
-       GlobalSection(ProjectConfigurationPlatforms) = postSolution
-               {E20CB432-6730-4021-A372-1C81A333518A}.Debug|Win32.ActiveCfg = Debug|Win32
-               {E20CB432-6730-4021-A372-1C81A333518A}.Debug|Win32.Build.0 = Debug|Win32
-               {E20CB432-6730-4021-A372-1C81A333518A}.Debug|Win32.Deploy.0 = Debug|Win32
-               {E20CB432-6730-4021-A372-1C81A333518A}.Debug|x64.ActiveCfg = Debug|x64
-               {E20CB432-6730-4021-A372-1C81A333518A}.Debug|x64.Build.0 = Debug|x64
-               {E20CB432-6730-4021-A372-1C81A333518A}.Debug|x64.Deploy.0 = Debug|x64
-               {E20CB432-6730-4021-A372-1C81A333518A}.Release|Win32.ActiveCfg = Release|Win32
-               {E20CB432-6730-4021-A372-1C81A333518A}.Release|Win32.Build.0 = Release|Win32
-               {E20CB432-6730-4021-A372-1C81A333518A}.Release|Win32.Deploy.0 = Release|Win32
-               {E20CB432-6730-4021-A372-1C81A333518A}.Release|x64.ActiveCfg = Release|x64
-               {E20CB432-6730-4021-A372-1C81A333518A}.Release|x64.Build.0 = Release|x64
-               {E20CB432-6730-4021-A372-1C81A333518A}.Release|x64.Deploy.0 = Release|x64
-       EndGlobalSection
-       GlobalSection(SolutionProperties) = preSolution
-               HideSolutionNode = FALSE
-       EndGlobalSection
-EndGlobal
index 442083e..3e4965a 100644 (file)
@@ -97,8 +97,8 @@ void initoptions(argoptions * opt) {
     opt->verbosemode = -1;
     opt->antialiasing = -1;
     opt->displaymode = -1;
-    opt->boundmode = -1; 
-    opt->boundthresh = -1; 
+    opt->boundmode = -1;
+    opt->boundthresh = -1;
     opt->usecamfile = -1;
 }
 
@@ -120,7 +120,7 @@ int CreateScene() {
 
     // scene->hres and scene->vres should be equal to screen resolution
     scene->hres = global_xwinsize = global_xsize;
-    scene->vres = global_ywinsize = global_ysize;  
+    scene->vres = global_ywinsize = global_ysize;
 
     return 0;
 }
@@ -137,7 +137,7 @@ unsigned int __stdcall example_main(void *)
         tachyon.init_console();
 
         // always using window even if(!global_usegraphics)
-        global_usegraphics = 
+        global_usegraphics =
             tachyon.init_window(global_xwinsize, global_ywinsize);
         if(!tachyon.running)
             exit(-1);
@@ -149,7 +149,7 @@ unsigned int __stdcall example_main(void *)
             global_startTime=(long) time(NULL);
             global_isCancelled=false;
             if (video)video->running = true;
-            tbb::task_scheduler_init init (global_number_of_threads);
+            tbb::global_control c(tbb::global_control::max_allowed_parallelism, global_number_of_threads);
             memset(g_pImg, 0, sizeof(unsigned int) * global_xsize * global_ysize);
             tachyon.main_loop();
             global_elapsedTime = (long)(time(NULL)-global_startTime);
@@ -262,7 +262,7 @@ int useoptions(argoptions * opt, SceneHandle scene) {
 
   if (opt->antialiasing != -1) {
     /* need new api code for this */
-  } 
+  }
 
   if (opt->displaymode != -1) {
     rt_displaymode(scene, opt->displaymode);
@@ -277,7 +277,7 @@ int useoptions(argoptions * opt, SceneHandle scene) {
   }
 
   return 0;
-}    
+}
 
 argoptions ParseCommandLine(int argc, const char *argv[]) {
     argoptions opt;
@@ -362,7 +362,7 @@ int main (int argc, char *argv[]) {
 
         tachyon.title = global_window_title;
         // always using window even if(!global_usegraphics)
-        global_usegraphics = 
+        global_usegraphics =
             tachyon.init_window(global_xwinsize, global_ywinsize);
         if(!tachyon.running)
             return -1;
index 8d2da92..bef7853 100644 (file)
@@ -81,19 +81,20 @@ static int colors[NUM_COLORS][3] = {
     {1,152,231},    {79,235,237},   {52,193,72},    {67,136,151},   {78,87,179},    {143,255,9},
 };
 
-#include "tbb/atomic.h"
+#include <atomic>
 #include "tbb/enumerable_thread_specific.h"
 // storage and counter for thread numbers in order of first task run
 typedef tbb::enumerable_thread_specific< int > thread_id_t;
 thread_id_t thread_ids (-1);
-tbb::atomic<int> thread_number;
+std::atomic<int> thread_number;
 
 #endif
 
-#include "tbb/task_scheduler_init.h"
 #include "tbb/parallel_for.h"
 #include "tbb/spin_mutex.h"
 #include "tbb/blocked_range2d.h"
+#include "tbb/global_control.h"
+#include "../../../common/utility/get_default_num_threads.h"
 
 static tbb::spin_mutex MyMutex, MyMutex2;
 
@@ -108,7 +109,7 @@ static color_t render_one_pixel (int x, int y, unsigned int *local_mbox, unsigne
     ray primary, sample;
     color col, avcol;
     int R,G,B;
-    intersectstruct local_intersections;    
+    intersectstruct local_intersections;
     int alias;
     /* end private */
 
@@ -117,11 +118,11 @@ static color_t render_one_pixel (int x, int y, unsigned int *local_mbox, unsigne
     primary.flags = RT_RAY_REGULAR;
 
     serial++;
-    primary.serial = serial;  
+    primary.serial = serial;
     primary.mbox = local_mbox;
     primary.maxdist = FHUGE;
     primary.scene = &scene;
-    col=trace(&primary);  
+    col=trace(&primary);
 
     serial = primary.serial;
 
@@ -131,7 +132,7 @@ static color_t render_one_pixel (int x, int y, unsigned int *local_mbox, unsigne
 
             serial++; /* increment serial number */
             sample=primary;  /* copy the regular primary ray to start with */
-            sample.serial = serial; 
+            sample.serial = serial;
 
             {
                 tbb::spin_mutex::scoped_lock lock (MyMutex);
@@ -140,7 +141,7 @@ static color_t render_one_pixel (int x, int y, unsigned int *local_mbox, unsigne
                 sample.d.z+=((rand() % 100) - 50) / jitterscale;
             }
 
-            avcol=trace(&sample);  
+            avcol=trace(&sample);
 
             serial = sample.serial; /* update our overall serial # */
 
@@ -172,7 +173,7 @@ static color_t render_one_pixel (int x, int y, unsigned int *local_mbox, unsigne
     G = int((1.0 - alpha) * G + alpha * blend[1]);
     B = int((1.0 - alpha) * B + alpha * blend[2]);
 #endif
-    
+
     return video->get_color(R, G, B);
 }
 
@@ -226,10 +227,10 @@ public:
 void * thread_trace(thr_parms * parms)
 {
 #if !WIN8UI_EXAMPLE
-    int n, nthreads = tbb::task_scheduler_init::automatic;
+    int n, nthreads = utility::get_default_num_threads();
     char *nthreads_str = getenv ("TBB_NUM_THREADS");
     if (nthreads_str && (sscanf (nthreads_str, "%d", &n) > 0) && (n > 0)) nthreads = n;
-    tbb::task_scheduler_init init (nthreads);
+    tbb::global_control c(tbb::global_control::max_allowed_parallelism, nthreads);
 #endif
 
     // shared but read-only so could be private too
@@ -261,5 +262,5 @@ void * thread_trace(thr_parms * parms)
 #endif
         tbb::parallel_for (tbb::blocked_range2d<int> (starty, stopy, grain_size, startx, stopx, grain_size), parallel_task (), tbb::auto_partitioner());
 
-    return(NULL);  
+    return(NULL);
 }
index d5a409b..92940f2 100644 (file)
@@ -68,10 +68,11 @@ static int stopy;
 static flt jitterscale;
 static int totaly;
 
-#include "tbb/task_scheduler_init.h"
 #include "tbb/parallel_for.h"
 #include "tbb/spin_mutex.h"
 #include "tbb/blocked_range.h"
+#include "tbb/global_control.h"
+#include "../../../common/utility/get_default_num_threads.h"
 
 static tbb::spin_mutex MyMutex, MyMutex2;
 
@@ -82,7 +83,7 @@ static color_t render_one_pixel (int x, int y, unsigned int *local_mbox, unsigne
     ray primary, sample;
     color col, avcol;
     int R,G,B;
-    intersectstruct local_intersections;    
+    intersectstruct local_intersections;
     int alias;
     /* end private */
 
@@ -91,11 +92,11 @@ static color_t render_one_pixel (int x, int y, unsigned int *local_mbox, unsigne
     primary.flags = RT_RAY_REGULAR;
 
     serial++;
-    primary.serial = serial;  
+    primary.serial = serial;
     primary.mbox = local_mbox;
     primary.maxdist = FHUGE;
     primary.scene = &scene;
-    col=trace(&primary);  
+    col=trace(&primary);
 
     serial = primary.serial;
 
@@ -105,7 +106,7 @@ static color_t render_one_pixel (int x, int y, unsigned int *local_mbox, unsigne
 
             serial++; /* increment serial number */
             sample=primary;  /* copy the regular primary ray to start with */
-            sample.serial = serial; 
+            sample.serial = serial;
 
             {
                 tbb::spin_mutex::scoped_lock lock (MyMutex);
@@ -114,7 +115,7 @@ static color_t render_one_pixel (int x, int y, unsigned int *local_mbox, unsigne
                 sample.d.z+=((rand() % 100) - 50) / jitterscale;
             }
 
-            avcol=trace(&sample);  
+            avcol=trace(&sample);
 
             serial = sample.serial; /* update our overall serial # */
 
@@ -170,10 +171,10 @@ public:
 
 void * thread_trace(thr_parms * parms)
 {
-    int n, nthreads = tbb::task_scheduler_init::automatic;
+    int n, nthreads = utility::get_default_num_threads();
     char *nthreads_str = getenv ("TBB_NUM_THREADS");
     if (nthreads_str && (sscanf (nthreads_str, "%d", &n) > 0) && (n > 0)) nthreads = n;
-    tbb::task_scheduler_init init (nthreads);
+    tbb::global_control c(tbb::global_control::max_allowed_parallelism, nthreads);
 
     // shared but read-only so could be private too
     all_parms = parms;
@@ -197,5 +198,5 @@ void * thread_trace(thr_parms * parms)
     else
         tbb::parallel_for (tbb::blocked_range<int> (starty, stopy, grain_size), parallel_task (), tbb::auto_partitioner() );
 
-    return(NULL);  
+    return(NULL);
 }
index a29342e..c472abb 100644 (file)
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = YES;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++11";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_ENABLE_OBJC_ARC = YES;
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = YES;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++11";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_ENABLE_OBJC_ARC = YES;
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++11";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_ENABLE_MODULES = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++11";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_ENABLE_MODULES = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
index 4fcccbb..b70624c 100644 (file)
@@ -35,15 +35,18 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:   release test
 
 release: *.cpp
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o convex_hull_sample convex_hull_sample.cpp -ltbb $(LIBS)
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o convex_hull_bench convex_hull_bench.cpp -ltbb $(LIBS)
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o convex_hull_sample convex_hull_sample.cpp -ltbb $(LIBS) $(CXX0XFLAGS)
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o convex_hull_bench convex_hull_bench.cpp -ltbb $(LIBS) $(CXX0XFLAGS)
 
 debug: *.cpp
-       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o convex_hull_sample convex_hull_sample.cpp -ltbb_debug $(LIBS)
-       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o convex_hull_bench convex_hull_bench.cpp -ltbb_debug $(LIBS)
+       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o convex_hull_sample convex_hull_sample.cpp -ltbb_debug $(LIBS) $(CXX0XFLAGS)
+       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o convex_hull_bench convex_hull_bench.cpp -ltbb_debug $(LIBS) $(CXX0XFLAGS)
 
 clean:
        $(RM) convex_hull_bench convex_hull_sample *.o *.d
index a624635..7ed556d 100644 (file)
@@ -29,8 +29,9 @@
 #include <functional>
 #include <climits>
 #include "tbb/tick_count.h"
-#include "tbb/task_scheduler_init.h"
+#include "tbb/global_control.h"
 #include "../../common/utility/utility.h"
+#include "../../common/utility/get_default_num_threads.h"
 #include "../../common/utility/fast_random.h"
 
 using namespace std;
@@ -38,7 +39,6 @@ using namespace std;
 namespace cfg {
     // convex hull problem user set parameters
     long   numberOfPoints  = 5000000; // problem size
-    utility::thread_number_range threads(tbb::task_scheduler_init::default_num_threads);
 
     // convex hull grain sizes for 3 subproblems. Be sure 16*GS < 512Kb
     const size_t generateGrainSize = 25000;
@@ -52,12 +52,12 @@ namespace util {
     vector<string> OUTPUT;
 
     // utility functionality
-    void ParseInputArgs(int argc, char* argv[]) {
+    void ParseInputArgs(int argc, char* argv[], utility::thread_number_range& threads) {
         utility::parse_cli_arguments(
                 argc,argv,
                 utility::cli_argument_pack()
                     //"-h" option for displaying help is present implicitly
-                    .positional_arg(cfg::threads,"n-of-threads",utility::thread_number_range_desc)
+                    .positional_arg(threads,"n-of-threads",utility::thread_number_range_desc)
                     .positional_arg(cfg::numberOfPoints,"n-of-points","number of points")
                     .arg(silent,"silent","no output except elapsed time")
                     .arg(verbose,"verbose","turns verbose ON")
index 986497a..0336d89 100644 (file)
@@ -175,7 +175,6 @@ int main(int argc, char* argv[]) {
 
 #else // USETBB - parallel version of Quick Hull algorithm
 
-#include "tbb/task_scheduler_init.h"
 #include "tbb/parallel_for.h"
 #include "tbb/parallel_reduce.h"
 #include "tbb/blocked_range.h"
@@ -566,7 +565,8 @@ void quickhull(const pointVec_t &points, pointVec_t &hull, bool buffered) {
 }
 
 int main(int argc, char* argv[]) {
-    util::ParseInputArgs(argc, argv);
+    utility::thread_number_range threads(utility::get_default_num_threads);
+    util::ParseInputArgs(argc, argv, threads);
 
     int             nthreads;
     util::my_time_t tm_init, tm_start, tm_end;
@@ -577,11 +577,11 @@ int main(int argc, char* argv[]) {
     std::cout << "Starting STL locked unbuffered push_back version of QUICK HULL algorithm" << std::endl;
 #endif // USECONCVEC
 
-    for(nthreads=cfg::threads.first; nthreads<=cfg::threads.last; nthreads=cfg::threads.step(nthreads)) {
+    for(nthreads=threads.first; nthreads<=threads.last; nthreads=threads.step(nthreads)) {
         pointVec_t      points;
         pointVec_t      hull;
 
-        tbb::task_scheduler_init init(nthreads);
+        tbb::global_control c(tbb::global_control::max_allowed_parallelism, nthreads);
         tm_init = util::gettime();
         initialize<FillRNDPointsVector>(points);
         tm_start = util::gettime();
@@ -599,11 +599,11 @@ int main(int argc, char* argv[]) {
     std::cout << "Starting STL locked buffered version of QUICK HULL algorithm" << std::endl;
 #endif
 
-    for(nthreads=cfg::threads.first; nthreads<=cfg::threads.last; nthreads=cfg::threads.step(nthreads)) {
+    for(nthreads=threads.first; nthreads<=threads.last; nthreads=threads.step(nthreads)) {
         pointVec_t      points;
         pointVec_t      hull;
 
-        tbb::task_scheduler_init init(nthreads);
+        tbb::global_control c(tbb::global_control::max_allowed_parallelism, nthreads);
 
         tm_init = util::gettime();
         initialize<FillRNDPointsVector_buf>(points);
index fbe3ecc..9d5bae2 100644 (file)
@@ -24,7 +24,6 @@
 */
 #include "convex_hull.h"
 
-#include "tbb/task_scheduler_init.h"
 #include "tbb/parallel_for.h"
 #include "tbb/parallel_reduce.h"
 #include "tbb/blocked_range.h"
@@ -255,9 +254,10 @@ void quickhull(const pointVec_t &points, pointVec_t &hull) {
 }
 
 int main(int argc, char* argv[]) {
+    utility::thread_number_range threads(utility::get_default_num_threads);
     util::my_time_t tm_main_begin = util::gettime();
 
-    util::ParseInputArgs(argc, argv);
+    util::ParseInputArgs(argc, argv, threads);
 
     pointVec_t      points;
     pointVec_t      hull;
@@ -269,8 +269,8 @@ int main(int argc, char* argv[]) {
         std::cout << "Starting TBB-buffered version of QUICK HULL algorithm" << std::endl;
     }
 
-    for(nthreads=cfg::threads.first; nthreads<=cfg::threads.last; nthreads=cfg::threads.step(nthreads)) {
-        tbb::task_scheduler_init init(nthreads);
+    for(nthreads=threads.first; nthreads<=threads.last; nthreads=threads.step(nthreads)) {
+        tbb::global_control c(tbb::global_control::max_allowed_parallelism, nthreads);
 
         points.clear();
         util::my_time_t tm_init = util::gettime();
index 99067be..4f00735 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index 118b35d..d893719 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index 53cdf2e..bbbac1f 100644 (file)
@@ -44,13 +44,16 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:   release test
 
 release: main.cpp primes.cpp 
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ $(TBBLIB) $(LIBS)
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ $(TBBLIB) $(LIBS) $(CXX0XFLAGS)
 
 debug: main.cpp primes.cpp
-       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ $(TBBLIB_DEBUG) $(LIBS)
+       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ $(TBBLIB_DEBUG) $(LIBS) $(CXX0XFLAGS)
 
 clean:
        $(RM) $(PROG) *.o *.d
index a397d00..2dfd397 100644 (file)
@@ -43,23 +43,9 @@ struct RunOptions{
     {}
 };
 
-int do_get_default_num_threads() {
-    int threads;
-    #if __TBB_MIC_OFFLOAD
-    #pragma offload target(mic) out(threads)
-    #endif // __TBB_MIC_OFFLOAD
-    threads = tbb::task_scheduler_init::default_num_threads();
-    return threads;
-}
-
-int get_default_num_threads() {
-    static int threads = do_get_default_num_threads();
-    return threads;
-}
-
 //! Parse the command line.
 static RunOptions ParseCommandLine( int argc, const char* argv[] ) {
-    utility::thread_number_range threads( get_default_num_threads, 0, get_default_num_threads() );
+    utility::thread_number_range threads( utility::get_default_num_threads, 0, utility::get_default_num_threads() );
     NumberType grainSize = 1000;
     bool silent = false;
     NumberType number = 100000000;
index 697045e..af2746f 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index c45bd04..bf663b3 100644 (file)
@@ -33,7 +33,6 @@
 #include <cstdlib>
 #include <cctype>
 #include "tbb/parallel_reduce.h"
-#include "tbb/task_scheduler_init.h"
 
 using namespace std;
 
@@ -285,7 +284,7 @@ public:
 //! Count number of primes between 0 and n
 /** This is the parallel version. */
 NumberType ParallelCountPrimes( NumberType n , int number_of_threads, NumberType grain_size ) {
-    tbb::task_scheduler_init init(number_of_threads);
+    tbb::global_control c(tbb::global_control::max_allowed_parallelism, number_of_threads);
 
     // Two is special case
     NumberType count = n>=2;
index 023d85b..dd57557 100644 (file)
@@ -21,7 +21,7 @@
 #pragma offload_attribute (push,target(mic))
 #endif // __TBB_MIC_OFFLOAD
 
-#include "tbb/task_scheduler_init.h"
+#include "../../common/utility/get_default_num_threads.h"
 #include <cstddef>
 typedef std::size_t NumberType;
 
@@ -31,7 +31,7 @@ NumberType SerialCountPrimes( NumberType n);
 
 //! Count number of primes between 0 and n
 /** This is the parallel version. */
-NumberType ParallelCountPrimes( NumberType n, int numberOfThreads= tbb::task_scheduler_init::automatic, NumberType grainSize = 1000);
+NumberType ParallelCountPrimes( NumberType n, int numberOfThreads= utility::get_default_num_threads(), NumberType grainSize = 1000);
 
 #if __TBB_MIC_OFFLOAD
 #pragma offload_attribute (pop)
index 92c013d..a645b2c 100644 (file)
                .circ {
                        list-style-type:circle
                }
-               
+
                .single {
                        padding: 0 0.5em;
                }
-               
+
                /* ------------------------------------------------- */
                /* Table styles                                      */
                table{
                }
                th{
                        border:1px #dddddd solid;
-                       padding-top:2px;                 
+                       padding-top:2px;
                        padding-bottom:0px;
-                       padding-right:3px;               
+                       padding-right:3px;
                        padding-left:3px;
                }
                td{
                        padding-right:5px;
                        vertical-align:top;
                }
-               
+
                .specs {
                        border-collapse:collapse;
                }
                        padding: 0 0.2em 0.2em;
                        text-align: center;
                }
-               .specs td tr:last-child td, 
+               .specs td tr:last-child td,
                .specs td tr:last-child th {
                        padding: 0 0.2em;
                }
                        font-style: italic;
                }
        </style>
-       <title>Intel&reg; Threading Building Blocks. Samples on pipeline algorithm</title>
+       <title>Intel&reg; Threading Building Blocks. Samples on parallel_pipeline algorithm</title>
 </head>
 <body>
-       
+
        <div id="banner">
                <img class="logo" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEMAAAAsCAYAAAA+aAX8AAAAAXNSR0IArs4c6QAAAARnQU1BAACx
                                jwv8YQUAAAAJcEhZcwAALiIAAC4iAari3ZIAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVh
                                iIfWc2AQusxPgvq484vH2eUgtpYHH0Hteeqb75ZwMQ+j+cDg9PlwFDwd6o9sr0KtbWI/tSPgp32M
                                76H+s6mNX3030df5neGq1OtbZDUbOIlFoFaha0L9j0qfCHeAerDqVtODU8+hNThZfR1fHHbpG6kx
                                9Or1LzUmVVz+HJXDAAAAAElFTkSuQmCC">
-               <h1 class="title">Intel&reg; Threading Building Blocks.<br>Samples on <code>pipeline</code> algorithm</h1>
+               <h1 class="title">Intel&reg; Threading Building Blocks.<br>Samples on <code>parallel_pipeline</code> algorithm</h1>
        </div>
-       
+
        <p>
-               This directory has examples of the <code>pipeline</code> algorithm.
+               This directory has examples of the <code>parallel_pipeline</code> algorithm.
        </p>
 
        <div class="changes">
                <div class="show-hide">
                        <p>
                                Intel and the Intel logo are trademarks of Intel Corporation in the U.S. and/or other countries.
-                               <br>* Other names and brands may be claimed as the property of others. 
+                               <br>* Other names and brands may be claimed as the property of others.
                                <br>&copy; 2019, Intel Corporation
                        </p>
                </div>
index fe0427c..50cfba9 100644 (file)
@@ -36,13 +36,16 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:   release test
 
 release: $(SOURCES)
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS)
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS) $(CXX0XFLAGS)
 
 debug: $(SOURCES)
-       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS)
+       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS) $(CXX0XFLAGS)
 
 clean:
        $(RM) $(PROG) *.o *.d input.txt output.txt
index 67aea8c..e70fd32 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index 7f2b267..b806066 100644 (file)
                .circ {
                        list-style-type:circle
                }
-               
+
                .single {
                        padding: 0 0.5em;
                }
-               
+
                /* ------------------------------------------------- */
                /* Table styles                                      */
                table{
                }
                th{
                        border:1px #dddddd solid;
-                       padding-top:2px;                 
+                       padding-top:2px;
                        padding-bottom:0px;
-                       padding-right:3px;               
+                       padding-right:3px;
                        padding-left:3px;
                }
                td{
                        padding-right:5px;
                        vertical-align:top;
                }
-               
+
                .specs {
                        border-collapse:collapse;
                }
                        padding: 0 0.2em 0.2em;
                        text-align: center;
                }
-               .specs td tr:last-child td, 
+               .specs td tr:last-child td,
                .specs td tr:last-child th {
                        padding: 0 0.2em;
                }
        <title>Intel&reg; Threading Building Blocks. Square sample</title>
 </head>
 <body>
-       
+
        <div id="banner">
                <img class="logo" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEMAAAAsCAYAAAA+aAX8AAAAAXNSR0IArs4c6QAAAARnQU1BAACx
                                jwv8YQUAAAAJcEhZcwAALiIAAC4iAari3ZIAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVh
                                9Or1LzUmVVz+HJXDAAAAAElFTkSuQmCC">
                <h1 class="title">Intel&reg; Threading Building Blocks.<br>Square sample</h1>
        </div>
-       
+
        <p>
-               Text filter that demonstrates class pipeline. Example program reads a file 
+               Text filter that demonstrates the use of parallel_pipeline. Example program reads a file
                containing decimal integers in text format, and changes each to its square.
        </p>
 
                        </p>
                </div>
        </div>
-       
+
        <div class="changes">
                <div class="h3-alike">Files</div>
                <input type="checkbox" checked="checked">
                                <dt><tt>square <i>-h</i></tt>
                                <dd>Prints the help for command line options
                                <dt><tt>square [<i>n-of-threads</i>=value] [<i>input-file</i>=value] [<i>output-file</i>=value] [<i>max-slice-size</i>=value] [<i>silent</i>]</tt>
-                               <dt><tt>square [<i>n-of-threads</i> [<i>input-file</i> [<i>output-file</i> [<i>max-slice-size</i>]]]] [<i>silent</i>]</tt> 
+                               <dt><tt>square [<i>n-of-threads</i> [<i>input-file</i> [<i>output-file</i> [<i>max-slice-size</i>]]]] [<i>silent</i>]</tt>
                                <dd><i>n-of-threads</i> is the number of threads to use; a range of the form <i>low</i>[:<i>high</i>], where low and optional high are non-negative integers or 'auto' for a platform-specific default number.<br>
                                        <i>input-file</i> is an input file name.<br>
                                        <i>output-file</i> is an output file name. <br>
                                </dl>
                </div>
        </div>
-       
+
        <br>
        <a href="../index.html">Up to parent directory</a>
        <hr>
                <div class="show-hide">
                        <p>
                                Intel and the Intel logo are trademarks of Intel Corporation in the U.S. and/or other countries.
-                               <br>* Other names and brands may be claimed as the property of others. 
+                               <br>* Other names and brands may be claimed as the property of others.
                                <br>&copy; 2019, Intel Corporation
                        </p>
                </div>
-       </div>  
-       
+       </div>
+
 </body>
 </html>
index cb7361a..bcba460 100644 (file)
 //
 // Example program that reads a file of decimal integers in text format
 // and changes each to its square.
-// 
+//
 #include "tbb/pipeline.h"
 #include "tbb/tick_count.h"
-#include "tbb/task_scheduler_init.h"
 #include "tbb/tbb_allocator.h"
 #include <cstring>
 #include <cstdlib>
 #include <cstdio>
 #include <cctype>
+#include "tbb/global_control.h"
 #include "../../common/utility/utility.h"
+#include "../../common/utility/get_default_num_threads.h"
 
 extern void generate_if_needed(const char*);
 
@@ -49,10 +50,10 @@ public:
         t->physical_end = t->begin()+max_size;
         return t;
     }
-    //! Free a TextSlice object 
+    //! Free a TextSlice object
     void free() {
         tbb::tbb_allocator<char>().deallocate((char*)this,sizeof(TextSlice)+(physical_end-begin())+1);
-    } 
+    }
     //! Pointer to beginning of sequence
     char* begin() {return (char*)(this+1);}
     //! Pointer to one past last character in sequence
@@ -74,109 +75,103 @@ size_t MAX_CHAR_PER_INPUT_SLICE = 4000;
 string InputFileName = "input.txt";
 string OutputFileName = "output.txt";
 
-class MyInputFilter: public tbb::filter {
+TextSlice* next_slice = NULL;
+
+class MyInputFunc {
 public:
-    MyInputFilter( FILE* input_file_ );
-    ~MyInputFilter();
+    MyInputFunc(FILE* input_file_);
+    MyInputFunc(const MyInputFunc& f) : input_file(f.input_file) { }
+    ~MyInputFunc();
+    TextSlice* operator()(tbb::flow_control& fc) const;
 private:
     FILE* input_file;
-    TextSlice* next_slice;
-    void* operator()(void*) /*override*/;
 };
 
-MyInputFilter::MyInputFilter( FILE* input_file_ ) : 
-    filter(serial_in_order),
-    input_file(input_file_),
-    next_slice( TextSlice::allocate( MAX_CHAR_PER_INPUT_SLICE ) )
-{ 
-}
+MyInputFunc::MyInputFunc(FILE* input_file_) :
+    input_file(input_file_) { }
 
-MyInputFilter::~MyInputFilter() {
-    next_slice->free();
+MyInputFunc::~MyInputFunc() {
 }
-void* MyInputFilter::operator()(void*) {
+
+TextSlice* MyInputFunc::operator()(tbb::flow_control& fc) const {
     // Read characters into space that is available in the next slice.
+    if (!next_slice)
+        next_slice = TextSlice::allocate(MAX_CHAR_PER_INPUT_SLICE);
     size_t m = next_slice->avail();
-    size_t n = fread( next_slice->end(), 1, m, input_file );
-    if( !n && next_slice->size()==0 ) {
+    size_t n = fread(next_slice->end(), 1, m, input_file);
+    if (!n && next_slice->size() == 0) {
         // No more characters to process
+        fc.stop();
         return NULL;
-    } else {
+    }
+    else {
         // Have more characters to process.
-        TextSlice& t = *next_slice;
-        next_slice = TextSlice::allocate( MAX_CHAR_PER_INPUT_SLICE );
-        char* p = t.end()+n;
-        if( n==m ) {
-            // Might have read partial number.  If so, transfer characters of partial number to next slice.
-            while( p>t.begin() && isdigit(p[-1]) ) 
+        TextSlice* t = next_slice;
+        next_slice = TextSlice::allocate(MAX_CHAR_PER_INPUT_SLICE);
+        char* p = t->end() + n;
+        if (n == m) {
+            // Might have read partial number.
+            // If so, transfer characters of partial number to next slice.
+            while (p > t->begin() && isdigit(p[-1]))
                 --p;
-            next_slice->append( p, t.end()+n );
+            assert(p > t->begin()); // Number too large to fit in buffer
+            next_slice->append(p, t->end() + n);
         }
-        t.set_end(p);
-        return &t;
+        t->set_end(p);
+        return t;
     }
 }
-    
-//! Filter that changes each decimal number to its square.
-class MyTransformFilter: public tbb::filter {
+
+// Functor that changes each decimal number to its square.
+class MyTransformFunc {
 public:
-    MyTransformFilter();
-    void* operator()( void* item ) /*override*/;
+    TextSlice* operator()(TextSlice* input) const;
 };
 
-MyTransformFilter::MyTransformFilter() : 
-    tbb::filter(parallel) 
-{}  
-
-void* MyTransformFilter::operator()( void* item ) {
-    TextSlice& input = *static_cast<TextSlice*>(item);
+TextSlice* MyTransformFunc::operator()(TextSlice* input) const {
     // Add terminating null so that strtol works right even if number is at end of the input.
-    *input.end() = '\0';
-    char* p = input.begin();
-    TextSlice& out = *TextSlice::allocate( 2*MAX_CHAR_PER_INPUT_SLICE );
-    char* q = out.begin();
-    for(;;) {
-        while( p<input.end() && !isdigit(*p) ) 
-            *q++ = *p++; 
-        if( p==input.end() ) 
+    *input->end() = '\0';
+    char* p = input->begin();
+    TextSlice* out = TextSlice::allocate(2 * MAX_CHAR_PER_INPUT_SLICE);
+    char* q = out->begin();
+    for (;;) {
+        while (p < input->end() && !isdigit(*p))
+            *q++ = *p++;
+        if (p == input->end())
             break;
-        long x = strtol( p, &p, 10 );
-        // Note: no overflow checking is needed here, as we have twice the 
-        // input string length, but the square of a non-negative integer n 
+        long x = strtol(p, &p, 10);
+        // Note: no overflow checking is needed here, as we have twice the
+        // input string length, but the square of a non-negative integer n
         // cannot have more than twice as many digits as n.
-        long y = x*x; 
-        sprintf(q,"%ld",y);
-        q = strchr(q,0);
+        long y = x * x;
+        sprintf(q, "%ld", y);
+        q = strchr(q, 0);
     }
-    out.set_end(q);
-    input.free();
-    return &out;
+    out->set_end(q);
+    input->free();
+    return out;
 }
-         
-//! Filter that writes each buffer to a file.
-class MyOutputFilter: public tbb::filter {
+
+// Functor that writes a TextSlice to a file.
+class MyOutputFunc {
     FILE* my_output_file;
 public:
-    MyOutputFilter( FILE* output_file );
-    void* operator()( void* item ) /*override*/;
+    MyOutputFunc(FILE* output_file);
+    void operator()(TextSlice* item) const;
 };
 
-MyOutputFilter::MyOutputFilter( FILE* output_file ) : 
-    tbb::filter(serial_in_order),
+MyOutputFunc::MyOutputFunc(FILE* output_file) :
     my_output_file(output_file)
 {
 }
 
-void* MyOutputFilter::operator()( void* item ) {
-    TextSlice& out = *static_cast<TextSlice*>(item);
-    size_t n = fwrite( out.begin(), 1, out.size(), my_output_file );
-    if( n!=out.size() ) {
-        fprintf(stderr,"Can't write into file '%s'\n", OutputFileName.c_str());
+void MyOutputFunc::operator()(TextSlice* out) const {
+    size_t n = fwrite(out->begin(), 1, out->size(), my_output_file);
+    if (n != out->size()) {
+        fprintf(stderr, "Can't write into file '%s'\n", OutputFileName.c_str());
         exit(1);
     }
-    out.free();
-    return NULL;
+    out->free();
 }
 
 bool silent = false;
@@ -194,26 +189,22 @@ int run_pipeline( int nthreads )
         return 0;
     }
 
-    // Create the pipeline
-    tbb::pipeline pipeline;
-
-    // Create file-reading writing stage and add it to the pipeline
-    MyInputFilter input_filter( input_file );
-    pipeline.add_filter( input_filter );
-
-    // Create squaring stage and add it to the pipeline
-    MyTransformFilter transform_filter; 
-    pipeline.add_filter( transform_filter );
-
-    // Create file-writing stage and add it to the pipeline
-    MyOutputFilter output_filter( output_file );
-    pipeline.add_filter( output_filter );
-
-    // Run the pipeline
     tbb::tick_count t0 = tbb::tick_count::now();
-    // Need more than one token in flight per thread to keep all threads 
+
+    // Need more than one token in flight per thread to keep all threads
     // busy; 2-4 works
-    pipeline.run( nthreads*4 );
+    tbb::parallel_pipeline(
+        nthreads*4,
+        tbb::make_filter<void,TextSlice*>(
+            tbb::filter::serial_in_order, MyInputFunc(input_file) )
+    &
+        tbb::make_filter<TextSlice*,TextSlice*>(
+            tbb::filter::parallel, MyTransformFunc() )
+    &
+        tbb::make_filter<TextSlice*,void>(
+            tbb::filter::serial_in_order, MyOutputFunc(output_file) )
+    );
+
     tbb::tick_count t1 = tbb::tick_count::now();
 
     fclose( output_file );
@@ -230,7 +221,7 @@ int main( int argc, char* argv[] ) {
 
         // The 1st argument is the function to obtain 'auto' value; the 2nd is the default value
         // The example interprets 0 threads as "run serially, then fully subscribed"
-        utility::thread_number_range threads( tbb::task_scheduler_init::default_num_threads, 0 );
+        utility::thread_number_range threads( utility::get_default_num_threads, 0 );
 
         utility::parse_cli_arguments(argc,argv,
             utility::cli_argument_pack()
@@ -246,21 +237,21 @@ int main( int argc, char* argv[] ) {
         if ( threads.first ) {
             for(int p = threads.first;  p <= threads.last; p=threads.step(p) ) {
                 if ( !silent ) printf("threads = %d ", p);
-                tbb::task_scheduler_init init(p);
+                tbb::global_control c(tbb::global_control::max_allowed_parallelism, p);
                 if(!run_pipeline (p))
                     return 1;
             }
         } else { // Number of threads wasn't set explicitly. Run serial and parallel version
             { // serial run
                 if ( !silent ) printf("serial run   ");
-                tbb::task_scheduler_init init_serial(1);
+                tbb::global_control c(tbb::global_control::max_allowed_parallelism, 1);
                 if(!run_pipeline (1))
                     return 1;
             }
             { // parallel run (number of threads is selected automatically)
                 if ( !silent ) printf("parallel run ");
-                tbb::task_scheduler_init init_parallel;
-                if(!run_pipeline (init_parallel.default_num_threads()))
+                tbb::global_control c(tbb::global_control::max_allowed_parallelism, utility::get_default_num_threads());
+                if(!run_pipeline (utility::get_default_num_threads()))
                     return 1;
             }
         }
index 1ff4478..757ed89 100644 (file)
@@ -34,13 +34,16 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:   release test
 
 release: *.cpp
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbbmalloc -ltbb $(LIBS)
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbbmalloc -ltbb $(LIBS) $(CXX0XFLAGS)
 
 debug: *.cpp
-       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbbmalloc_debug -ltbb_debug $(LIBS)
+       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbbmalloc_debug -ltbb_debug $(LIBS) $(CXX0XFLAGS)
 
 clean:
        $(RM) $(PROG) *.o *.d
index 8c8fa69..eeaa9df 100644 (file)
 // Pass stdmalloc as the 1st command line parameter to use the default "operator new"
 // and see the performance difference.
 #include "tbb/scalable_allocator.h"
+#include "tbb/global_control.h"
 #include "TreeMaker.h"
 #include "tbb/tick_count.h"
-#include "tbb/task_scheduler_init.h"
 
 #include "../../common/utility/utility.h"
+#include "../../common/utility/get_default_num_threads.h"
 
 using namespace std;
 
@@ -52,7 +53,7 @@ int main( int argc, const char *argv[] ) {
 
         // The 1st argument is the function to obtain 'auto' value; the 2nd is the default value
         // The example interprets 0 threads as "run serially, then fully subscribed"
-        utility::thread_number_range threads( tbb::task_scheduler_init::default_num_threads, 0 );
+        utility::thread_number_range threads( utility::get_default_num_threads, 0 );
         long number_of_nodes = 10000000;
         bool silent = false;
         bool use_stdmalloc = false;
@@ -68,7 +69,7 @@ int main( int argc, const char *argv[] ) {
 
         TreeNode* root;
         { // In this scope, TBB will use default number of threads for tree creation
-            tbb::task_scheduler_init init;
+            tbb::global_control c(tbb::global_control::max_allowed_parallelism, utility::get_default_num_threads());
 
             if( use_stdmalloc ) {
                 if ( !silent ) printf("Tree creation using standard operator new\n");
@@ -85,13 +86,13 @@ int main( int argc, const char *argv[] ) {
         if ( threads.first ) {
             for(int p = threads.first;  p <= threads.last; p = threads.step(p) ) {
                 if ( !silent ) printf("threads = %d\n", p );
-                tbb::task_scheduler_init init( p );
+                tbb::global_control c(tbb::global_control::max_allowed_parallelism, p);
                 Run ( "SimpleParallelSumTree", SimpleParallelSumTree, root, silent );
                 Run ( "OptimizedParallelSumTree", OptimizedParallelSumTree, root, silent );
             }
         } else { // Number of threads wasn't set explicitly. Run serial and two parallel versions
             Run ( "SerialSumTree", SerialSumTree, root, silent );
-            tbb::task_scheduler_init init;
+            tbb::global_control c(tbb::global_control::max_allowed_parallelism, utility::get_default_num_threads());
             Run ( "SimpleParallelSumTree", SimpleParallelSumTree, root, silent );
             Run ( "OptimizedParallelSumTree", OptimizedParallelSumTree, root, silent );
         }
index 8f96871..24d19af 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;tbbmalloc_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;tbbmalloc_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;tbbmalloc.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;tbbmalloc.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index 8639a36..7e5ab98 100644 (file)
@@ -35,6 +35,9 @@ SOURCES= ../../common/gui/$(UI)video.cpp fractal.cpp main.cpp
 
 override CXXFLAGS += $(UI_CXXFLAGS)
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:   release test
 
 resources:
@@ -47,15 +50,15 @@ endif # macOS*
 
 release: $(SOURCES) resources
 ifeq ($(UI),mac)
-       $(CXX_UI) -O2 -DNDEBUG $(CXXFLAGS) -c $(MACUISOURCES)
+       $(CXX_UI) -O2 -DNDEBUG $(CXXFLAGS) -c $(MACUISOURCES) $(CXX0XFLAGS)
 endif # macOS
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(EXE) $(SOURCES) $(MACUIOBJS) -ltbb $(LIBS)
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(EXE) $(SOURCES) $(MACUIOBJS) -ltbb $(LIBS) $(CXX0XFLAGS)
 
 debug: resources
 ifeq ($(UI),mac)
-       $(CXX_UI) -g -O0 -DTBB_USE_DEBUG $(CXXFLAGS) -c $(MACUISOURCES)
+       $(CXX_UI) -g -O0 -DTBB_USE_DEBUG $(CXXFLAGS) -c $(MACUISOURCES) $(CXX0XFLAGS)
 endif # macOS
-       $(CXX) -g -O0 -DTBB_USE_DEBUG $(CXXFLAGS) -o $(EXE) $(SOURCES) $(MACUIOBJS) -ltbb_debug $(LIBS)
+       $(CXX) -g -O0 -DTBB_USE_DEBUG $(CXXFLAGS) -o $(EXE) $(SOURCES) $(MACUIOBJS) -ltbb_debug $(LIBS) $(CXX0XFLAGS)
 
 clean:
        $(RM) $(EXE) *.o *.d
index 3a0686d..6abc45b 100644 (file)
 
 #include "tbb/parallel_for.h"
 #include "tbb/blocked_range2d.h"
-#include "tbb/task_scheduler_init.h"
-#include "tbb/task_arena.h"
-#include "tbb/task_group.h"
 #include "tbb/tick_count.h"
 
 #include <math.h>
 #include <stdio.h>
 
-// Included for __TBB_CPP11_LAMBDAS_PRESENT definition
-#include "tbb/tbb_config.h"
-
 video *v;
 extern bool silent;
 extern bool schedule_auto;
@@ -173,16 +167,9 @@ void fractal_group::calc_fractal( int num ) {
     }
 }
 
-void fractal_group::set_priorities() {
-    // set the high priority for the active area and the normal priority for another area
-    context[active].set_priority( tbb::priority_high );
-    context[active^1].set_priority( tbb::priority_low );
-}
-
-void fractal_group::switch_priorities( int new_active ) {
+void fractal_group::switch_active( int new_active ) {
     if( new_active!=-1 ) active = new_active;
     else                 active = 1-active; // assumes 'active' is only 0 or 1
-    set_priorities();
     draw_borders();
 }
 
@@ -191,73 +178,29 @@ void fractal_group::set_num_frames_at_least( int n ) {
     if ( num_frames[1]<n ) num_frames[1] = n;
 }
 
-#if !__TBB_CPP11_LAMBDAS_PRESENT
-class task_group_body {
-    fractal_group &fg;
-public:
-    task_group_body(fractal_group &_fg) : fg(_fg) { }
-
-    void operator() () const { fg.calc_fractal( 1 ); }
-};
-
-class arena_body {
-    task_group_body &tg_body;
-    tbb::task_group &task_group;
-public:
-    arena_body( task_group_body &_tg_body, tbb::task_group &_task_group )
-        :  tg_body( _tg_body ), task_group( _task_group )  { }
-
-    void operator() () const { task_group.run( tg_body ); }
-};
-
-class arena_body_wait {
-    tbb::task_group &group;
-public:
-    arena_body_wait( tbb::task_group &gr ) : group(gr) { }
-
-    void operator() () const { group.wait(); }
-};
-#endif
-
 void fractal_group::run( bool create_second_fractal ) {
-    // initialize task scheduler
-    tbb::task_scheduler_init init( num_threads );
+    // First argument of arenas construntor is used to restrict concurrency
+    arenas[0].initialize(num_threads);
+    arenas[1].initialize(num_threads / 2);
 
-    // create contexts to manage fractal priorities
-    context = new tbb::task_group_context[2];
-
-    set_priorities();
     draw_borders();
 
-    tbb::task_arena arena;
-    tbb::task_group gr;
-
     // the second fractal is calculating on separated thread
     if ( create_second_fractal ) {
-#if __TBB_CPP11_LAMBDAS_PRESENT
-        arena.execute( [&] {
-            gr.run( [&] { calc_fractal( 1 ); } );
+        arenas[1].execute( [&] {
+            groups[1].run( [&] { calc_fractal( 1 ); } );
         } );
-#else
-        task_group_body tg_body( *this );
-        arena_body a_body( tg_body, gr );
-        arena.execute( a_body );
-#endif
     }
 
-    // calculate the first fractal
-    calc_fractal( 0 );
+    arenas[0].execute( [&] {
+        groups[0].run( [&] { calc_fractal( 0 ); } );
+    } );
 
     if ( create_second_fractal ) {
-#if __TBB_CPP11_LAMBDAS_PRESENT
-        // wait for second fractal
-        arena.execute( [&] { gr.wait(); } );
-#else
-        arena.execute( arena_body_wait( gr ) );
-#endif
+        arenas[1].execute( [&] { groups[1].wait(); } );
     }
 
-    delete[] context;
+    arenas[0].execute( [&] { groups[0].wait(); } );
 }
 
 void fractal_group::draw_borders() {
@@ -296,6 +239,6 @@ void fractal_group::mouse_click( int x, int y ) {
     }
 
     if ( new_active != -1 && new_active != active ) {
-        switch_priorities( new_active );
+        switch_active( new_active );
     }
 }
index 0cdd9c5..9433749 100644 (file)
 #ifndef FRACTAL_H_
 #define FRACTAL_H_
 
+#include <atomic>
 #include "../../common/gui/video.h"
+#include "../../common/utility/get_default_num_threads.h"
 
 #include "tbb/task.h"
-#include "tbb/task_scheduler_init.h"
-#include "tbb/atomic.h"
+#include "tbb/task_arena.h"
+#include "tbb/task_group.h"
 
 //! Fractal class
 class fractal {
@@ -82,9 +84,12 @@ class fractal_group {
     //! Fractals definition
     fractal f0, f1;
     //! Number of frames to calculate
-    tbb::atomic<int> num_frames[2];
-    //! Task group contexts to manage priorities
-    tbb::task_group_context *context;
+    std::atomic<int> num_frames[2];
+
+    //! Contexts, arenas and groups for concurrent computation
+    tbb::task_group_context context[2];
+    tbb::task_arena arenas[2];
+    tbb::task_group groups[2];
 
     //! Border type enumeration
     enum BORDER_TYPE {
@@ -105,7 +110,7 @@ class fractal_group {
 public:
     //! Constructor
     fractal_group( const drawing_memory &_dm,
-            int num_threads = tbb::task_scheduler_init::automatic,
+            int num_threads = utility::get_default_num_threads(),
             unsigned int max_iterations = 100000, int num_frames = 1 );
     //! Run calculation
     void run( bool create_second_fractal=true );
@@ -117,8 +122,8 @@ public:
     int get_num_threads() const { return num_threads; }
     //! Reset the number of frames to be not less than the given value
     void set_num_frames_at_least( int n );
-    //! Switches the priorities of two fractals
-    void switch_priorities( int new_active=-1 );
+    //! Switch active fractal
+    void switch_active( int new_active=-1 );
     //! Get active fractal
     fractal& get_active_fractal() { return  active ? f1 : f0; }
 
index 7b340d6..8e323ce 100644 (file)
@@ -41,8 +41,6 @@ private:
         switch ( key&0xff ) {
             case esc_key:
                 running = false; break;
-            case ' ': // space
-                if( fg ) fg->switch_priorities(); break;
 
             case 'q':
                 if( fg ) fg->active_fractal_zoom_in(); break;
index 8f2eb34..5a865d5 100644 (file)
@@ -23,7 +23,6 @@
 #include "fractal_video.h"
 
 #include "tbb/tick_count.h"
-#include "tbb/task_scheduler_init.h"
 
 #include "../../common/utility/utility.h"
 
@@ -40,7 +39,7 @@ int main(int argc, char *argv[])
         // It is used for console mode for test with different number of threads and also has
         // meaning for GUI: threads.first  - use separate event/updating loop thread (>0) or not (0).
         //                  threads.second - initialization value for scheduler
-        utility::thread_number_range threads( tbb::task_scheduler_init::default_num_threads );
+        utility::thread_number_range threads( utility::get_default_num_threads );
         int num_frames = -1;
         int max_iterations = 1000000;
 
index 34ad785..719c4c5 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;$(DXSDK_DIR)\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;$(DXSDK_DIR)\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
index b6ca4b5..2954edc 100644 (file)
        </div>
        
        <p>
-               The example calculates two classical Mandelbrot fractals with different priorities. 
+               The example calculates two classical Mandelbrot fractals with different concurrency levels. 
        <br><br>
-               The application window is divided into two areas where fractals are rendered. With mouse click on an area the user can change the priority of the calculating fractal. In the clicked area the fractal priority is changed to be "high" and the priority of the other fractal is changed to "low". The fractal with "high" priority we will call active.
-               The example also has the console mode but in this mode the priorities could not be changed during execution.
+               The application window is divided into two areas where fractals are rendered.
+               The example also has the console mode.
        </p>
 
        <div class="changes">
                        </p>
                        <dl>
                                <dt>&lt;left mouse button&gt;
-                               <dd>Make the fractal active and change its priority to high
-                               <dt>&lt;space&gt;
-                               <dd>Switch priorities
+                               <dd>Make the fractal active
                                <dt>&lt;w&gt;
                                <dd>Move the active fractal up
                                <dt>&lt;a&gt;
index 6f087b7..6742437 100644 (file)
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = YES;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                CLANG_ENABLE_OBJC_ARC = YES;
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = YES;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                CLANG_ENABLE_OBJC_ARC = YES;
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++11";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_ENABLE_MODULES = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++11";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_ENABLE_MODULES = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
index e244193..e19bb95 100644 (file)
                <div class="show-hide">
                        <dl>
                                <dt><a href="fractal/readme.html">fractal</a>
-                               <dd>The example calculates two classical Mandelbrot fractals with different priorities.
+                               <dd>The example calculates two classical Mandelbrot fractals with different concurrency limits.
                        </dl>
                </div>
        </div>
index cad72ac..1054b7f 100644 (file)
@@ -23,9 +23,6 @@ ifneq (,$(shell which icc 2>/dev/null))
     CXX=icpc
 endif
 
-# autodetect C++11 support
-include ../../common/examples-common.inc
-
 TBBLIB = -ltbb
 TBBLIB_DEBUG = -ltbb_debug
 
@@ -49,6 +46,9 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:   release test
 
 release: *.cpp
index beda25a..dea92b0 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;tbbmalloc_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;tbbmalloc_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;tbbmalloc.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;tbbmalloc.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index 2948fc4..380d2f8 100644 (file)
@@ -15,6 +15,7 @@
 */
 
 #include "../../common/utility/utility.h"
+#include "../../common/utility/get_default_num_threads.h"
 
 #if __TBB_MIC_OFFLOAD
 #pragma offload_attribute (push,target(mic))
 #include <cstdio>
 #include <cstdlib>
 #include <string>
+#include <atomic>
 
-#include "tbb/atomic.h"
 #include "tbb/tick_count.h"
-#include "tbb/task_scheduler_init.h"
 #include "tbb/task_group.h"
+#include "tbb/global_control.h"
 
 #pragma warning(disable: 4996)
 
@@ -37,7 +38,7 @@ const unsigned BOARD_DIM=9;
 using namespace tbb;
 using namespace std;
 
-tbb::atomic<unsigned> nSols;
+std::atomic<unsigned> nSols;
 bool find_one = false;
 bool verbose = false;
 unsigned short init_values[BOARD_SIZE] = {1,0,0,9,0,0,0,8,0,0,8,0,2,0,0,0,0,0,0,0,5,0,0,0,7,0,0,0,5,2,1,0,0,4,0,0,0,0,0,0,0,5,0,0,7,4,0,0,7,0,0,0,3,0,0,3,0,0,0,2,0,0,5,0,0,0,0,0,0,1,0,0,5,0,0,0,1,0,0,0,0};
@@ -53,7 +54,7 @@ void read_board(const char *filename) {
     FILE *fp;
     int input;
     fp = fopen(filename, "r");
-    if (!fp) { 
+    if (!fp) {
         fprintf(stderr, "sudoku: Could not open input file '%s'.\n", filename);
         exit(1);
     }
@@ -82,7 +83,7 @@ void print_board(board_element *b) {
 void print_potential_board(board_element *b) {
     for (unsigned row=0; row<BOARD_DIM; ++row) {
         for (unsigned col=0; col<BOARD_DIM; ++col) {
-            if (b[row*BOARD_DIM+col].solved_element) 
+            if (b[row*BOARD_DIM+col].solved_element)
                 printf("  %4d ", b[row*BOARD_DIM+col].solved_element);
             else
                 printf(" [%4d]", b[row*BOARD_DIM+col].potential_set);
@@ -101,7 +102,7 @@ void init_board(board_element *b) {
 
 void init_board(board_element *b, unsigned short arr[81]) {
     for (unsigned i=0; i<BOARD_SIZE; ++i) {
-        b[i].solved_element = arr[i]; 
+        b[i].solved_element = arr[i];
         b[i].potential_set = 0;
     }
 }
@@ -242,7 +243,7 @@ void partial_solve(board_element *b, unsigned first_potential_set) {
 }
 
 unsigned solve(int p) {
-    task_scheduler_init init(p);
+    tbb::global_control c(tbb::global_control::max_allowed_parallelism, p);
     nSols = 0;
     board_element *start_board = (board_element *)malloc(BOARD_SIZE*sizeof(board_element));
     init_board(start_board, init_values);
@@ -259,25 +260,11 @@ unsigned solve(int p) {
 #pragma offload_attribute (pop)
 #endif // __TBB_MIC_OFFLOAD
 
-int do_get_default_num_threads() {
-    int threads;
-    #if __TBB_MIC_OFFLOAD
-    #pragma offload target(mic) out(threads)
-    #endif // __TBB_MIC_OFFLOAD
-    threads = tbb::task_scheduler_init::default_num_threads();
-    return threads;
-}
-
-int get_default_num_threads() {
-    static int threads = do_get_default_num_threads();
-    return threads;
-}
-
 int main(int argc, char *argv[]) {
     try {
         tbb::tick_count mainStartTime = tbb::tick_count::now();
 
-        utility::thread_number_range threads(get_default_num_threads);
+        utility::thread_number_range threads(utility::get_default_num_threads);
         string filename = "";
         bool silent = false;
 
index 694c16b..062e16b 100644 (file)
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                ENABLE_TESTABILITY = YES;
                                GCC_ENABLE_CPP_RTTI = YES;
                                GCC_MODEL_TUNING = "";
                                        "$(TBBROOT)/include",
                                        /opt/intel/tbb/include,
                                );
+                               ICC_CXX_LANG_DIALECT = "c++11";
                                LD_RUNPATH_SEARCH_PATHS = "$(TBBROOT)/lib /opt/intel/tbb/lib";
                                LIBRARY_SEARCH_PATHS = (
                                        "$(TBBROOT)/lib",
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                GCC_ENABLE_CPP_RTTI = YES;
                                GCC_MODEL_TUNING = "";
                                GCC_VERSION = "";
                                        "$(TBBROOT)/include",
                                        /opt/intel/tbb/include,
                                );
+                               ICC_CXX_LANG_DIALECT = "c++11";
                                LD_RUNPATH_SEARCH_PATHS = "$(TBBROOT)/lib /opt/intel/tbb/lib";
                                LIBRARY_SEARCH_PATHS = (
                                        "$(TBBROOT)/lib",
index 0a6d6f5..8392bf9 100644 (file)
 cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR)
 
 project(fibonacci CXX)
+
+if (NOT CMAKE_CXX_STANDARD)
+    set(CMAKE_CXX_STANDARD 11)
+    set(CXX_STANDARD_REQUIRED ON)
+endif()
+
 add_executable(fibonacci Fibonacci.cpp)
 
 # find_package will search for available TBBConfig using variables CMAKE_PREFIX_PATH and TBB_DIR.
index 937c7f4..04d3df7 100644 (file)
 #include <cstdlib>
 #include <cassert>
 #include <utility>
+#include <thread>
+#include <atomic>
+#include <mutex>
 #include "tbb/task.h"
-#include "tbb/task_scheduler_init.h"
 #include "tbb/tick_count.h"
 #include "tbb/blocked_range.h"
 #include "tbb/concurrent_vector.h"
 #include "tbb/parallel_reduce.h"
 #include "tbb/parallel_scan.h"
 #include "tbb/pipeline.h"
-#include "tbb/atomic.h"
-#include "tbb/mutex.h"
 #include "tbb/spin_mutex.h"
 #include "tbb/queuing_mutex.h"
-#include "tbb/tbb_thread.h"
+#include "tbb/global_control.h"
 
 using namespace std;
 using namespace tbb;
@@ -117,9 +117,9 @@ value SerialQueueFib(int n)
         Q.push(Matrix1110);
     Matrix2x2 A, B;
     while(true) {
-        while( !Q.try_pop(A) ) this_tbb_thread::yield();
+        while( !Q.try_pop(A) ) std::this_thread::yield();
         if(Q.empty()) break;
-        while( !Q.try_pop(B) ) this_tbb_thread::yield();
+        while( !Q.try_pop(B) ) std::this_thread::yield();
         Q.push(A * B);
     }
     return A.v[0][0];
@@ -163,6 +163,19 @@ public:
     }
 };
 
+#if __TBB_CPP11_PRESENT
+template<>
+void SharedSerialFibBody<std::mutex>::operator()( const blocked_range<int>& range ) const {
+    for(;;) {
+        std::lock_guard<std::mutex> lock(mutex);
+        if(SharedI >= SharedN) break;
+        value sum = SharedA + SharedB;
+        SharedA = SharedB; SharedB = sum;
+        ++SharedI;
+    }
+}
+#endif
+
 //! Root function
 template<class M>
 value SharedSerialFib(int n)
@@ -323,60 +336,66 @@ value ParallelQueueFib(int n)
     return M.v[0][0]; // and result number
 }
 
-// *** Queue with pipeline *** //
+// *** Queue with parallel_pipeline *** //
+
+typedef concurrent_queue<Matrix2x2> queue_t;
+namespace parallel_pipeline_ns {
+    std::atomic<int> N; //< index of Fibonacci number minus 1
+    queue_t Queue;
+}
+
+//! functor to fills queue
+struct InputFunc {
+    InputFunc( ) { }
+    queue_t* operator()(tbb::flow_control& fc) const {
+        using namespace parallel_pipeline_ns;
 
-//! filter to fills queue
-class InputFilter: public filter {
-    tbb::atomic<int> N; //< index of Fibonacci number minus 1
-public:
-    concurrent_queue<Matrix2x2> Queue;
-    //! fill filter arguments
-    InputFilter( int n ) : filter(false /*is not serial*/) { N = n; }
-    //! executing filter
-    void* operator()(void*) /*override*/ {
         int n = --N;
-        if(n <= 0) return 0;
+        if(n <= 0) {
+            fc.stop();
+            return NULL;
+        }
         Queue.push( Matrix1110 );
         return &Queue;
     }
 };
-//! filter to process queue
-class MultiplyFilter: public filter {
-public:
-    MultiplyFilter( ) : filter(false /*is not serial*/) { }
-    //! executing filter
-    void* operator()(void*p) /*override*/ {
-        concurrent_queue<Matrix2x2> &Queue = *static_cast<concurrent_queue<Matrix2x2> *>(p);
+//! functor to process queue
+struct MultiplyFunc {
+    MultiplyFunc( ) { }
+    void operator()(queue_t* queue) const {
+        //concurrent_queue<Matrix2x2> &Queue = *static_cast<concurrent_queue<Matrix2x2> *>(p);
         Matrix2x2 m1, m2;
         // get two elements
-        while( !Queue.try_pop( m1 ) ) this_tbb_thread::yield();
-        while( !Queue.try_pop( m2 ) ) this_tbb_thread::yield();
+        while( !queue->try_pop( m1 ) ) std::this_thread::yield();
+        while( !queue->try_pop( m2 ) ) std::this_thread::yield();
         m1 = m1 * m2; // process them
-        Queue.push( m1 ); // and push back
-        return this; // just nothing
+        queue->push( m1 ); // and push back
     }
 };
 //! Root function
 value ParallelPipeFib(int n)
 {
-    InputFilter input( n-1 );
-    MultiplyFilter process;
-    // Create the pipeline
-    pipeline pipeline;
-    // add filters
-    pipeline.add_filter( input ); // first
-    pipeline.add_filter( process ); // second
-
-    input.Queue.push( Matrix1110 );
-    // Run the pipeline
-    pipeline.run( n ); // must be larger then max threads number
-    pipeline.clear(); // do not forget clear the pipeline
-
-    assert( input.Queue.unsafe_size()==1 );
+    using namespace parallel_pipeline_ns;
+
+    N = n-1;
+    Queue.push( Matrix1110 );
+
+    tbb::parallel_pipeline(
+        n,
+        tbb::make_filter<void,queue_t*>(
+            tbb::filter::parallel, InputFunc() )
+    &
+        tbb::make_filter<queue_t*,void>(
+            tbb::filter::parallel, MultiplyFunc() )
+    );
+
+    assert( Queue.unsafe_size()==1 );
     Matrix2x2 M;
-    bool result = input.Queue.try_pop( M ); // get last element
+    bool result = Queue.try_pop( M ); // get last element
     assert( result );
-    return M.v[0][0]; // get value
+    value res = M.v[0][0]; // get value
+    Queue.clear();
+    return res;
 }
 
 // *** parallel_reduce *** //
@@ -564,7 +583,7 @@ int main(int argc, char* argv[])
     for( unsigned long i=0; i<ntrial; ++i ) {
         for(int threads = NThread.low; threads <= NThread.high; threads *= 2)
         {
-            task_scheduler_init scheduler_init(threads);
+            tbb::global_control c(tbb::global_control::max_allowed_parallelism, threads);
             if(Verbose) printf("\nThreads number is %d\n", threads);
 
             sum = Measure("Shared serial (mutex)\t", SharedSerialFib<mutex>, NumbersCount); assert(result == sum);
index 6c202c7..35e5b96 100644 (file)
@@ -33,13 +33,16 @@ else ifeq ($(shell uname), Darwin)
 override CXXFLAGS += -Wl,-rpath,$(TBBROOT)/lib
 endif
 
+# autodetect C++11 support
+include ../../common/examples-common.inc
+
 all:   release test
 
 release: *.cpp
-       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS)
+       $(CXX) -O2 -DNDEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb $(LIBS) $(CXX0XFLAGS)
 
 debug: *.cpp
-       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS)
+       $(CXX) -O0 -g -DTBB_USE_DEBUG $(CXXFLAGS) -o $(PROG) $^ -ltbb_debug $(LIBS) $(CXX0XFLAGS)
 
 clean:
        $(RM) $(PROG) *.o *.d
index 39aba72..bab01d2 100644 (file)
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb_debug.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc12;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\ia32\vc_mt;$(TBBROOT)\lib\ia32\vc14;$(SolutionDir)\..\..\..\..\lib\ia32\vc_mt;$(SolutionDir)\..\..\..\..\lib\ia32\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
     </ClCompile>
     <Link>
       <AdditionalDependencies>tbb.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc12;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc12;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>$(TBBROOT)\lib\intel64\vc_mt;$(TBBROOT)\lib\intel64\vc14;$(SolutionDir)\..\..\..\..\lib\intel64\vc_mt;$(SolutionDir)\..\..\..\..\lib\intel64\vc14;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Console</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
index 09a61b7..ef35973 100644 (file)
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                ENABLE_TESTABILITY = YES;
                                GCC_ENABLE_CPP_RTTI = YES;
                                GCC_MODEL_TUNING = "";
                                        "$(TBBROOT)/include",
                                        /opt/intel/tbb/include,
                                );
+                               ICC_CXX_LANG_DIALECT = "c++11";
                                LD_RUNPATH_SEARCH_PATHS = "$(TBBROOT)/lib /opt/intel/tbb/lib";
                                LIBRARY_SEARCH_PATHS = (
                                        "$(TBBROOT)/lib",
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
                                GCC_ENABLE_CPP_RTTI = YES;
                                GCC_MODEL_TUNING = "";
                                GCC_VERSION = "";
                                        "$(TBBROOT)/include",
                                        /opt/intel/tbb/include,
                                );
+                               ICC_CXX_LANG_DIALECT = "c++11";
                                LD_RUNPATH_SEARCH_PATHS = "$(TBBROOT)/lib /opt/intel/tbb/lib";
                                LIBRARY_SEARCH_PATHS = (
                                        "$(TBBROOT)/lib",
index 5b42a67..cfe6ccf 100644 (file)
     limitations under the License.
 */
 
+#include "../../tbb/internal/_deprecated_header_message_guard.h"
+
+#if !defined(__TBB_show_deprecation_message_parallel_for_H) && defined(__TBB_show_deprecated_header_message)
+#define  __TBB_show_deprecation_message_parallel_for_H
+#pragma message("TBB Warning: serial/tbb/parallel_for.h is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.")
+#endif
+
+#if defined(__TBB_show_deprecated_header_message)
+#undef __TBB_show_deprecated_header_message
+#endif
+
 #ifndef __TBB_SERIAL_parallel_for_H
 #define __TBB_SERIAL_parallel_for_H
 
@@ -94,35 +105,35 @@ void start_for< Range, Body, Partitioner >::execute() {
 //! Parallel iteration over range with default partitioner.
 /** @ingroup algorithms **/
 template<typename Range, typename Body>
-void parallel_for( const Range& range, const Body& body ) {
+__TBB_DEPRECATED_VERBOSE void parallel_for( const Range& range, const Body& body ) {
     serial::interface9::start_for<Range,Body,const __TBB_DEFAULT_PARTITIONER>::run(range,body,__TBB_DEFAULT_PARTITIONER());
 }
 
 //! Parallel iteration over range with simple partitioner.
 /** @ingroup algorithms **/
 template<typename Range, typename Body>
-void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner ) {
+__TBB_DEPRECATED_VERBOSE void parallel_for( const Range& range, const Body& body, const simple_partitioner& partitioner ) {
     serial::interface9::start_for<Range,Body,const simple_partitioner>::run(range,body,partitioner);
 }
 
 //! Parallel iteration over range with auto_partitioner.
 /** @ingroup algorithms **/
 template<typename Range, typename Body>
-void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner ) {
+__TBB_DEPRECATED_VERBOSE void parallel_for( const Range& range, const Body& body, const auto_partitioner& partitioner ) {
     serial::interface9::start_for<Range,Body,const auto_partitioner>::run(range,body,partitioner);
 }
 
 //! Parallel iteration over range with static_partitioner.
 /** @ingroup algorithms **/
 template<typename Range, typename Body>
-void parallel_for( const Range& range, const Body& body, const static_partitioner& partitioner ) {
+__TBB_DEPRECATED_VERBOSE void parallel_for( const Range& range, const Body& body, const static_partitioner& partitioner ) {
     serial::interface9::start_for<Range,Body,const static_partitioner>::run(range,body,partitioner);
 }
 
 //! Parallel iteration over range with affinity_partitioner.
 /** @ingroup algorithms **/
 template<typename Range, typename Body>
-void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner ) {
+__TBB_DEPRECATED_VERBOSE void parallel_for( const Range& range, const Body& body, affinity_partitioner& partitioner ) {
     serial::interface9::start_for<Range,Body,affinity_partitioner>::run(range,body,partitioner);
 }
 
@@ -150,53 +161,53 @@ void parallel_for_impl(Index first, Index last, Index step, const Function& f, P
 
 //! Parallel iteration over a range of integers with explicit step and default partitioner
 template <typename Index, typename Function>
-void parallel_for(Index first, Index last, Index step, const Function& f) {
+__TBB_DEPRECATED_VERBOSE void parallel_for(Index first, Index last, Index step, const Function& f) {
     parallel_for_impl<Index,Function,const auto_partitioner>(first, last, step, f, auto_partitioner());
 }
 //! Parallel iteration over a range of integers with explicit step and simple partitioner
 template <typename Index, typename Function>
-void parallel_for(Index first, Index last, Index step, const Function& f, const simple_partitioner& p) {
+__TBB_DEPRECATED_VERBOSE void parallel_for(Index first, Index last, Index step, const Function& f, const simple_partitioner& p) {
     parallel_for_impl<Index,Function,const simple_partitioner>(first, last, step, f, p);
 }
 //! Parallel iteration over a range of integers with explicit step and auto partitioner
 template <typename Index, typename Function>
-void parallel_for(Index first, Index last, Index step, const Function& f, const auto_partitioner& p) {
+__TBB_DEPRECATED_VERBOSE void parallel_for(Index first, Index last, Index step, const Function& f, const auto_partitioner& p) {
     parallel_for_impl<Index,Function,const auto_partitioner>(first, last, step, f, p);
 }
 //! Parallel iteration over a range of integers with explicit step and static partitioner
 template <typename Index, typename Function>
-void parallel_for(Index first, Index last, Index step, const Function& f, const static_partitioner& p) {
+__TBB_DEPRECATED_VERBOSE void parallel_for(Index first, Index last, Index step, const Function& f, const static_partitioner& p) {
     parallel_for_impl<Index,Function,const static_partitioner>(first, last, step, f, p);
 }
 //! Parallel iteration over a range of integers with explicit step and affinity partitioner
 template <typename Index, typename Function>
-void parallel_for(Index first, Index last, Index step, const Function& f, affinity_partitioner& p) {
+__TBB_DEPRECATED_VERBOSE void parallel_for(Index first, Index last, Index step, const Function& f, affinity_partitioner& p) {
     parallel_for_impl(first, last, step, f, p);
 }
 
 //! Parallel iteration over a range of integers with default step and default partitioner
 template <typename Index, typename Function>
-void parallel_for(Index first, Index last, const Function& f) {
+__TBB_DEPRECATED_VERBOSE void parallel_for(Index first, Index last, const Function& f) {
     parallel_for_impl<Index,Function,const auto_partitioner>(first, last, static_cast<Index>(1), f, auto_partitioner());
 }
 //! Parallel iteration over a range of integers with default step and simple partitioner
 template <typename Index, typename Function>
-void parallel_for(Index first, Index last, const Function& f, const simple_partitioner& p) {
+__TBB_DEPRECATED_VERBOSE void parallel_for(Index first, Index last, const Function& f, const simple_partitioner& p) {
     parallel_for_impl<Index,Function,const simple_partitioner>(first, last, static_cast<Index>(1), f, p);
 }
 //! Parallel iteration over a range of integers with default step and auto partitioner
 template <typename Index, typename Function>
-    void parallel_for(Index first, Index last, const Function& f, const auto_partitioner& p) {
+__TBB_DEPRECATED_VERBOSE void parallel_for(Index first, Index last, const Function& f, const auto_partitioner& p) {
     parallel_for_impl<Index,Function,const auto_partitioner>(first, last, static_cast<Index>(1), f, p);
 }
 //! Parallel iteration over a range of integers with default step and static partitioner
 template <typename Index, typename Function>
-void parallel_for(Index first, Index last, const Function& f, const static_partitioner& p) {
+__TBB_DEPRECATED_VERBOSE void parallel_for(Index first, Index last, const Function& f, const static_partitioner& p) {
     parallel_for_impl<Index,Function,const static_partitioner>(first, last, static_cast<Index>(1), f, p);
 }
 //! Parallel iteration over a range of integers with default step and affinity_partitioner
 template <typename Index, typename Function>
-void parallel_for(Index first, Index last, const Function& f, affinity_partitioner& p) {
+__TBB_DEPRECATED_VERBOSE void parallel_for(Index first, Index last, const Function& f, affinity_partitioner& p) {
     parallel_for_impl(first, last, static_cast<Index>(1), f, p);
 }
 
index 33e8367..9d42c3d 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB__aggregator_H
 #define __TBB__aggregator_H
 
+#define __TBB_aggregator_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #if !TBB_PREVIEW_AGGREGATOR
 #error Set TBB_PREVIEW_AGGREGATOR before including aggregator.h
 #endif
@@ -195,4 +198,7 @@ using interface6::aggregator_operation;
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_aggregator_H_include_area
+
 #endif  // __TBB__aggregator_H
index 03b09d0..d91fd6f 100644 (file)
     limitations under the License.
 */
 
+#include "internal/_deprecated_header_message_guard.h"
+
+#if !defined(__TBB_show_deprecation_message_aligned_space_H) && defined(__TBB_show_deprecated_header_message)
+#define  __TBB_show_deprecation_message_aligned_space_H
+#pragma message("TBB Warning: tbb/aligned_space.h is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.")
+#endif
+
+#if defined(__TBB_show_deprecated_header_message)
+#undef __TBB_show_deprecated_header_message
+#endif
+
 #ifndef __TBB_aligned_space_H
 #define __TBB_aligned_space_H
 
+#define __TBB_aligned_space_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "tbb_stddef.h"
 #include "tbb_machine.h"
 
@@ -26,7 +40,7 @@ namespace tbb {
 /** The elements are not constructed or destroyed by this class.
     @ingroup memory_allocation */
 template<typename T,size_t N=1>
-class aligned_space {
+class __TBB_DEPRECATED_VERBOSE_MSG("tbb::aligned_space is deprecated, use std::aligned_storage") aligned_space {
 private:
     typedef __TBB_TypeWithAlignmentAtLeastAsStrict(T) element_type;
     element_type array[(sizeof(T)*N+sizeof(element_type)-1)/sizeof(element_type)];
@@ -40,4 +54,7 @@ public:
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_aligned_space_H_include_area
+
 #endif /* __TBB_aligned_space_H */
index 92d1e11..33c54af 100644 (file)
     limitations under the License.
 */
 
+#include "internal/_deprecated_header_message_guard.h"
+
+#if !defined(__TBB_show_deprecation_message_atomic_H) && defined(__TBB_show_deprecated_header_message)
+#define  __TBB_show_deprecation_message_atomic_H
+#pragma message("TBB Warning: tbb/atomic.h is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.")
+#endif
+
+#if defined(__TBB_show_deprecated_header_message)
+#undef __TBB_show_deprecated_header_message
+#endif
+
 #ifndef __TBB_atomic_H
 #define __TBB_atomic_H
 
+#define __TBB_atomic_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include <cstddef>
 
 #if _MSC_VER
@@ -400,10 +414,12 @@ public:
 /** See the Reference for details.
     @ingroup synchronization */
 template<typename T>
-struct atomic: internal::atomic_impl<T> {
+struct __TBB_DEPRECATED_VERBOSE_MSG("tbb::atomic is deprecated, use std::atomic")
+atomic: internal::atomic_impl<T> {
 #if __TBB_ATOMIC_CTORS
     atomic() = default;
     constexpr atomic(T arg): internal::atomic_impl<T>(arg) {}
+    constexpr atomic<T>(const atomic<T>& rhs): internal::atomic_impl<T>(rhs) {}
 #endif
     T operator=( T rhs ) {
         // "this" required here in strict ISO C++ because store_with_release is a dependent name
@@ -414,16 +430,20 @@ struct atomic: internal::atomic_impl<T> {
 
 #if __TBB_ATOMIC_CTORS
     #define __TBB_DECL_ATOMIC(T)                                                                    \
-        template<> struct atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {              \
+        template<> struct __TBB_DEPRECATED_VERBOSE_MSG("tbb::atomic is deprecated, use std::atomic")  \
+        atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {                                \
             atomic() = default;                                                                     \
             constexpr atomic(T arg): internal::atomic_impl_with_arithmetic<T,T,char>(arg) {}        \
+            constexpr atomic<T>(const atomic<T>& rhs):                                              \
+                      internal::atomic_impl_with_arithmetic<T,T,char>(rhs) {}                       \
                                                                                                     \
             T operator=( T rhs ) {return store_with_release(rhs);}                                  \
             atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}   \
         };
 #else
     #define __TBB_DECL_ATOMIC(T)                                                                    \
-        template<> struct atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {              \
+        template<> struct __TBB_DEPRECATED_VERBOSE_MSG("tbb::atomic is deprecated, use std::atomic")  \
+        atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {                                \
             T operator=( T rhs ) {return store_with_release(rhs);}                                  \
             atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}   \
         };
@@ -447,15 +467,20 @@ __TBB_DECL_ATOMIC(unsigned long)
    type synonyms on the platform.  Type U should be the wider variant of T from the
    perspective of /Wp64. */
 #define __TBB_DECL_ATOMIC_ALT(T,U) \
-    template<> struct atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {             \
+    template<> struct __TBB_DEPRECATED_VERBOSE_MSG("tbb::atomic is deprecated, use std::atomic") \
+    atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {                               \
         atomic() = default ;                                                                   \
         constexpr atomic(T arg): internal::atomic_impl_with_arithmetic<T,T,char>(arg) {}       \
+        constexpr atomic<T>(const atomic<T>& rhs):                                             \
+                  internal::atomic_impl_with_arithmetic<T,T,char>(rhs) {}                      \
+                                                                                               \
         T operator=( U rhs ) {return store_with_release(T(rhs));}                              \
         atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}  \
     };
 #else
 #define __TBB_DECL_ATOMIC_ALT(T,U) \
-    template<> struct atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {             \
+    template<> struct __TBB_DEPRECATED_VERBOSE_MSG("tbb::atomic is deprecated, use std::atomic") \
+    atomic<T>: internal::atomic_impl_with_arithmetic<T,T,char> {                               \
         T operator=( U rhs ) {return store_with_release(T(rhs));}                              \
         atomic<T>& operator=( const atomic<T>& rhs ) {store_with_release(rhs); return *this;}  \
     };
@@ -478,10 +503,12 @@ __TBB_DECL_ATOMIC(wchar_t)
 #endif /* _MSC_VER||!defined(_NATIVE_WCHAR_T_DEFINED) */
 
 //! Specialization for atomic<T*> with arithmetic and operator->.
-template<typename T> struct atomic<T*>: internal::atomic_impl_with_arithmetic<T*,ptrdiff_t,T> {
+template<typename T> struct __TBB_DEPRECATED_VERBOSE_MSG("tbb::atomic is deprecated, use std::atomic")
+atomic<T*>: internal::atomic_impl_with_arithmetic<T*,ptrdiff_t,T> {
 #if __TBB_ATOMIC_CTORS
     atomic() = default ;
     constexpr atomic(T* arg): internal::atomic_impl_with_arithmetic<T*,ptrdiff_t,T>(arg) {}
+    constexpr atomic(const atomic<T*>& rhs): internal::atomic_impl_with_arithmetic<T*,ptrdiff_t,T>(rhs) {}
 #endif
     T* operator=( T* rhs ) {
         // "this" required here in strict ISO C++ because store_with_release is a dependent name
@@ -496,10 +523,12 @@ template<typename T> struct atomic<T*>: internal::atomic_impl_with_arithmetic<T*
 };
 
 //! Specialization for atomic<void*>, for sake of not allowing arithmetic or operator->.
-template<> struct atomic<void*>: internal::atomic_impl<void*> {
+template<> struct __TBB_DEPRECATED_VERBOSE_MSG("tbb::atomic is deprecated, use std::atomic")
+atomic<void*>: internal::atomic_impl<void*> {
 #if __TBB_ATOMIC_CTORS
     atomic() = default ;
     constexpr atomic(void* arg): internal::atomic_impl<void*>(arg) {}
+    constexpr atomic(const atomic<void*>& rhs): internal::atomic_impl<void*>(rhs) {}
 #endif
     void* operator=( void* rhs ) {
         // "this" required here in strict ISO C++ because store_with_release is a dependent name
@@ -551,4 +580,7 @@ inline atomic<T>& as_atomic( T& t ) {
     #pragma warning (pop)
 #endif // warnings are restored
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_atomic_H_include_area
+
 #endif /* __TBB_atomic_H */
index a8aaf61..917c5fc 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_combinable_H
 #define __TBB_combinable_H
 
+#define __TBB_combinable_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "enumerable_thread_specific.h"
 #include "cache_aligned_allocator.h"
 
@@ -78,4 +81,8 @@ namespace tbb {
 
     };
 } // namespace tbb
+
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_combinable_H_include_area
+
 #endif /* __TBB_combinable_H */
index 8dc4e91..e06324f 100644 (file)
     limitations under the License.
 */
 
+#include "../internal/_deprecated_header_message_guard.h"
+
+#if !defined(__TBB_show_deprecation_message_condition_variable_H) && defined(__TBB_show_deprecated_header_message)
+#define  __TBB_show_deprecation_message_condition_variable_H
+#pragma message("TBB Warning: tbb/compat/condition_variable is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.")
+#endif
+
+#if defined(__TBB_show_deprecated_header_message)
+#undef __TBB_show_deprecated_header_message
+#endif
+
 #ifndef __TBB_condition_variable_H
 #define __TBB_condition_variable_H
 
+#define __TBB_condition_variable_H_include_area
+#include "../internal/_warning_suppress_enable_notice.h"
+
 #if _WIN32||_WIN64
 #include "../machine/windows_api.h"
 
-namespace tbb { 
+namespace tbb {
 namespace interface5 {
-namespace internal { 
+namespace internal {
 struct condition_variable_using_event
 {
     //! Event for blocking waiting threads.
@@ -65,17 +79,17 @@ namespace interface5 {
 
 // C++0x standard working draft 30.4.3
 // Lock tag types
-struct defer_lock_t { }; //! do not acquire ownership of the mutex
-struct try_to_lock_t { }; //! try to acquire ownership of the mutex without blocking
-struct adopt_lock_t { }; //! assume the calling thread has already
-const defer_lock_t defer_lock = {};
-const try_to_lock_t try_to_lock = {};
-const adopt_lock_t adopt_lock = {};
+struct __TBB_DEPRECATED_VERBOSE defer_lock_t { }; //! do not acquire ownership of the mutex
+struct __TBB_DEPRECATED_VERBOSE try_to_lock_t { }; //! try to acquire ownership of the mutex without blocking
+struct __TBB_DEPRECATED_VERBOSE adopt_lock_t { }; //! assume the calling thread has already
+__TBB_DEPRECATED_VERBOSE const defer_lock_t defer_lock = {};
+__TBB_DEPRECATED_VERBOSE const try_to_lock_t try_to_lock = {};
+__TBB_DEPRECATED_VERBOSE const adopt_lock_t adopt_lock = {};
 
 // C++0x standard working draft 30.4.3.1
-//! lock_guard 
+//! lock_guard
 template<typename M>
-class lock_guard : tbb::internal::no_copy {
+class __TBB_DEPRECATED_VERBOSE lock_guard : tbb::internal::no_copy {
 public:
     //! mutex type
     typedef M mutex_type;
@@ -84,7 +98,7 @@ public:
     /** precondition: If mutex_type is not a recursive mutex, the calling thread
         does not own the mutex m. */
     explicit lock_guard(mutex_type& m) : pm(m) {m.lock();}
-    
+
     //! Adopt_lock constructor
     /** precondition: the calling thread owns the mutex m. */
     lock_guard(mutex_type& m, adopt_lock_t) : pm(m) {}
@@ -96,9 +110,9 @@ private:
 };
 
 // C++0x standard working draft 30.4.3.2
-//! unique_lock 
+//! unique_lock
 template<typename M>
-class unique_lock : tbb::internal::no_copy {
+class __TBB_DEPRECATED_VERBOSE unique_lock : tbb::internal::no_copy {
     friend class condition_variable;
 public:
     typedef M mutex_type;
@@ -132,7 +146,7 @@ public:
     unique_lock(mutex_type& m, adopt_lock_t) : pm(&m), owns(true) {}
 
     //! Timed unique_lock acquisition.
-    /** To avoid requiring support for namespace chrono, this method deviates from the working draft in that 
+    /** To avoid requiring support for namespace chrono, this method deviates from the working draft in that
         it uses tbb::tick_count::interval_t to specify the time duration. */
     unique_lock(mutex_type& m, const tick_count::interval_t &i) : pm(&m) {owns = try_lock_for( i );}
 
@@ -165,14 +179,14 @@ public:
             if( !owns ) {
                 pm->lock();
                 owns = true;
-            } else 
+            } else
                 throw_exception_v4( tbb::internal::eid_possible_deadlock );
-        } else 
+        } else
             throw_exception_v4( tbb::internal::eid_operation_not_permitted );
         __TBB_ASSERT( owns, NULL );
     }
 
-    //! Try to lock the mutex. 
+    //! Try to lock the mutex.
     /** If successful, note that this lock owns it. Otherwise, set it false. */
     bool try_lock() {
         if( pm ) {
@@ -180,17 +194,17 @@ public:
                 owns = pm->try_lock();
             else
                 throw_exception_v4( tbb::internal::eid_possible_deadlock );
-        } else 
+        } else
             throw_exception_v4( tbb::internal::eid_operation_not_permitted );
         return owns;
     }
-    //! Try to lock the mutex. 
+
+    //! Try to lock the mutex.
     bool try_lock_for( const tick_count::interval_t &i );
 
     //! Unlock the mutex
     /** And note that this lock no longer owns it. */
-    void unlock() { 
+    void unlock() {
         if( owns ) {
             pm->unlock();
             owns = false;
@@ -208,10 +222,10 @@ public:
 
     //! Release control over the mutex.
     mutex_type* release() {
-        mutex_type* o_pm = pm; 
-        pm = NULL; 
-        owns = false; 
-        return o_pm; 
+        mutex_type* o_pm = pm;
+        pm = NULL;
+        owns = false;
+        return o_pm;
     }
 
     // 30.4.3.2.4 observers
@@ -231,12 +245,12 @@ private:
 };
 
 template<typename M>
-bool unique_lock<M>::try_lock_for( const tick_count::interval_t &i)
-{ 
+__TBB_DEPRECATED_VERBOSE bool unique_lock<M>::try_lock_for( const tick_count::interval_t &i)
+{
     const int unique_lock_tick = 100; /* microseconds; 0.1 milliseconds */
     // the smallest wait-time is 0.1 milliseconds.
     bool res = pm->try_lock();
-    int duration_in_micro; 
+    int duration_in_micro;
     if( !res && (duration_in_micro=int(i.seconds()*1e6))>unique_lock_tick ) {
         tick_count::interval_t i_100( double(unique_lock_tick)/1e6 /* seconds */); // 100 microseconds = 0.1*10E-3
         do {
@@ -248,7 +262,7 @@ bool unique_lock<M>::try_lock_for( const tick_count::interval_t &i)
     return (owns=res);
 }
 
-//! Swap the two unique locks that have the mutexes of same type 
+//! Swap the two unique locks that have the mutexes of same type
 template<typename M>
 void swap(unique_lock<M>& x, unique_lock<M>& y) { x.swap( y ); }
 
@@ -273,24 +287,24 @@ typedef pthread_cond_t condvar_impl_t;
 
 //! cv_status
 /** C++0x standard working draft 30.5 */
-enum cv_status { no_timeout, timeout }; 
+enum cv_status { no_timeout, timeout };
 
 //! condition variable
-/** C++0x standard working draft 30.5.1 
+/** C++0x standard working draft 30.5.1
     @ingroup synchronization */
-class condition_variable : tbb::internal::no_copy {
+class __TBB_DEPRECATED_VERBOSE condition_variable : tbb::internal::no_copy {
 public:
     //! Constructor
-    condition_variable() { 
+    condition_variable() {
 #if _WIN32||_WIN64
-        internal_initialize_condition_variable( my_cv ); 
+        internal_initialize_condition_variable( my_cv );
 #else
         pthread_cond_init( &my_cv, NULL );
 #endif
     }
 
     //! Destructor
-    ~condition_variable() { 
+    ~condition_variable() {
         //precondition: There shall be no thread blocked on *this.
 #if _WIN32||_WIN64
         internal_destroy_condition_variable( my_cv );
@@ -300,18 +314,18 @@ public:
     }
 
     //! Notify one thread and wake it up
-    void notify_one() { 
+    void notify_one() {
 #if _WIN32||_WIN64
-        internal_condition_variable_notify_one( my_cv ); 
+        internal_condition_variable_notify_one( my_cv );
 #else
         pthread_cond_signal( &my_cv );
 #endif
     }
 
-    //! Notify all threads 
-    void notify_all() { 
+    //! Notify all threads
+    void notify_all() {
 #if _WIN32||_WIN64
-        internal_condition_variable_notify_all( my_cv ); 
+        internal_condition_variable_notify_all( my_cv );
 #else
         pthread_cond_broadcast( &my_cv );
 #endif
@@ -445,7 +459,7 @@ inline cv_status condition_variable::wait_for( unique_lock<mutex>& lock, const t
 
 __TBB_DEFINE_PROFILING_SET_NAME(interface5::condition_variable)
 
-} // namespace tbb 
+} // namespace tbb
 
 #if TBB_IMPLEMENT_CPP0X
 
@@ -465,8 +479,11 @@ using tbb::interface5::cv_status;
 using tbb::interface5::timeout;
 using tbb::interface5::no_timeout;
 
-} // namespace std 
+} // namespace std
 
 #endif /* TBB_IMPLEMENT_CPP0X */
 
+#include "../internal/_warning_suppress_disable_notice.h"
+#undef __TBB_condition_variable_H_include_area
+
 #endif /* __TBB_condition_variable_H */
index a134244..a3ca67b 100644 (file)
     limitations under the License.
 */
 
+#include "../internal/_deprecated_header_message_guard.h"
+
+#if !defined(__TBB_show_deprecation_message_ppl_H) && defined(__TBB_show_deprecated_header_message)
+#define  __TBB_show_deprecation_message_ppl_H
+#pragma message("TBB Warning: tbb/compat/ppl.h is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.")
+#endif
+
+#if defined(__TBB_show_deprecated_header_message)
+#undef __TBB_show_deprecated_header_message
+#endif
+
 #ifndef __TBB_compat_ppl_H
 #define __TBB_compat_ppl_H
 
+#define __TBB_ppl_H_include_area
+#include "../internal/_warning_suppress_enable_notice.h"
+
 #include "../task_group.h"
 #include "../parallel_invoke.h"
 #include "../parallel_for_each.h"
@@ -55,4 +69,7 @@ namespace Concurrency {
 
 } // namespace Concurrency
 
+#include "../internal/_warning_suppress_disable_notice.h"
+#undef __TBB_ppl_H_include_area
+
 #endif /* __TBB_compat_ppl_H */
index 9dac430..c41bd03 100644 (file)
     limitations under the License.
 */
 
+#include "../internal/_deprecated_header_message_guard.h"
+
+#if !defined(__TBB_show_deprecation_message_thread_H) && defined(__TBB_show_deprecated_header_message)
+#define  __TBB_show_deprecation_message_thread_H
+#pragma message("TBB Warning: tbb/compat/thread is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.")
+#endif
+
+#if defined(__TBB_show_deprecated_header_message)
+#undef __TBB_show_deprecated_header_message
+#endif
+
 #ifndef __TBB_thread_H
 #define __TBB_thread_H
 
+#define __TBB_thread_H_include_area
+#include "../internal/_warning_suppress_enable_notice.h"
+
 #include "../tbb_config.h"
 
 #if TBB_IMPLEMENT_CPP0X
@@ -31,7 +45,7 @@ namespace this_thread {
     using tbb::this_tbb_thread::get_id;
     using tbb::this_tbb_thread::yield;
 
-    inline void sleep_for(const tbb::tick_count::interval_t& rel_time) {
+    __TBB_DEPRECATED_VERBOSE inline void sleep_for(const tbb::tick_count::interval_t& rel_time) {
         tbb::internal::thread_sleep_v3( rel_time );
     }
 }
@@ -46,6 +60,9 @@ namespace this_thread {
 
 #endif /* TBB_IMPLEMENT_CPP0X */
 
+#include "../internal/_warning_suppress_disable_notice.h"
+#undef __TBB_thread_H_include_area
+
 #else /* __TBB_thread_H */
 
 #if __TBB_COMPAT_THREAD_RECURSION_PROTECTOR
index 86e6cd9..bd9da17 100644 (file)
     limitations under the License.
 */
 
+#include "../internal/_deprecated_header_message_guard.h"
+
+#if !defined(__TBB_show_deprecation_message_tuple_H) && defined(__TBB_show_deprecated_header_message)
+#define  __TBB_show_deprecation_message_tuple_H
+#pragma message("TBB Warning: tbb/compat/tuple is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.")
+#endif
+
+#if defined(__TBB_show_deprecated_header_message)
+#undef __TBB_show_deprecated_header_message
+#endif
+
 #ifndef __TBB_tuple_H
 #define __TBB_tuple_H
 
+#define __TBB_tuple_H_include_area
+#include "../internal/_warning_suppress_enable_notice.h"
+
 #include <utility>
 #include "../tbb_stddef.h"
 
@@ -210,7 +224,7 @@ struct cons{
     typedef __HT head_type;
     typedef __TT tail_type;
 
-    head_type head; 
+    head_type head;
     tail_type tail;
 
     static const int length = 1 + tail_type::length;
@@ -272,12 +286,12 @@ struct cons{
 
 
 template <typename __HT>
-struct cons<__HT,null_type> { 
+struct cons<__HT,null_type> {
 
     typedef __HT head_type;
     typedef null_type tail_type;
 
-    head_type head; 
+    head_type head;
 
     static const int length = 1;
 
@@ -346,7 +360,7 @@ inline const __T wrap_dcons(__T*) { return __T(); }
 
 // tuple definition
 template<typename __T0, typename __T1, typename __T2, typename __T3, typename __T4 __TBB_TYPENAME_T_PACK >
-class tuple : public internal::tuple_traits<__T0, __T1, __T2, __T3, __T4 __TBB_T_PACK >::U {
+class __TBB_DEPRECATED_VERBOSE tuple : public internal::tuple_traits<__T0, __T1, __T2, __T3, __T4 __TBB_T_PACK >::U {
     // friends
     template <typename __T> friend class tuple_size;
     template<int __N, typename __T> friend struct tuple_element;
@@ -362,7 +376,7 @@ class tuple : public internal::tuple_traits<__T0, __T1, __T2, __T3, __T4 __TBB_T
     typedef typename internal::tuple_traits<__T0,__T1,__T2,__T3, __T4 __TBB_T_PACK >::U my_cons;
 
 public:
-    tuple(const __T0& t0=internal::wrap_dcons((__T0*)NULL)
+    __TBB_DEPRECATED_VERBOSE tuple(const __T0& t0=internal::wrap_dcons((__T0*)NULL)
           ,const __T1& t1=internal::wrap_dcons((__T1*)NULL)
           ,const __T2& t2=internal::wrap_dcons((__T2*)NULL)
           ,const __T3& t3=internal::wrap_dcons((__T3*)NULL)
@@ -421,7 +435,7 @@ public:
 
 // empty tuple
 template<>
-class tuple<null_type, null_type, null_type, null_type, null_type __TBB_NULL_TYPE_PACK > : public null_type {
+class __TBB_DEPRECATED_VERBOSE tuple<null_type, null_type, null_type, null_type, null_type __TBB_NULL_TYPE_PACK > : public null_type {
 };
 
 // helper classes
@@ -433,7 +447,7 @@ public:
 };
 
 template <>
-class tuple_size<tuple<> > { 
+class tuple_size<tuple<> > {
 public:
     static const size_t value = 0;
 };
@@ -480,5 +494,8 @@ namespace tbb {
 #undef __TBB_CONST_REF_T_PARAM_PACK
 #undef __TBB_T_PARAM_LIST_PACK
 #undef __TBB_CONST_NULL_REF_PACK
+
+#include "../internal/_warning_suppress_disable_notice.h"
+#undef __TBB_tuple_H_include_area
+
 #endif /* __TBB_tuple_H */
index e3f2a40..6f695f6 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_concurrent_hash_map_H
 #define __TBB_concurrent_hash_map_H
 
+#define __TBB_concurrent_hash_map_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "tbb_stddef.h"
 #include <iterator>
 #include <utility>      // Need std::pair
@@ -122,9 +125,10 @@ namespace interface5 {
 #endif
         //! Constructor
         hash_map_base() {
-            std::memset( this, 0, pointers_per_table*sizeof(segment_ptr_t) // 32*4=128   or 64*8=512
-                + sizeof(my_size) + sizeof(my_mask)  // 4+4 or 8+8
-                + embedded_buckets*sizeof(bucket) ); // n*8 or n*16
+            std::memset(my_table, 0, sizeof(my_table));
+            my_mask = 0;
+            my_size = 0;
+            std::memset(my_embedded_segment, 0, sizeof(my_embedded_segment));
             for( size_type i = 0; i < embedded_block; i++ ) // fill the table
                 my_table[i] = my_embedded_segment + segment_base(i);
             my_mask = embedded_buckets - 1;
@@ -407,6 +411,14 @@ namespace interface5 {
             my_bucket(other.my_bucket),
             my_node(other.my_node)
         {}
+
+        hash_map_iterator& operator=( const hash_map_iterator<Container,typename Container::value_type> &other ) {
+            my_map = other.my_map;
+            my_index = other.my_index;
+            my_bucket = other.my_bucket;
+            my_node = other.my_node;
+            return *this;
+        }
         Value& operator*() const {
             __TBB_ASSERT( hash_map_base::is_valid(my_node), "iterator uninitialized or at end of container?" );
             return my_node->value();
@@ -1630,4 +1642,7 @@ inline void swap(concurrent_hash_map<Key, T, HashCompare, A> &a, concurrent_hash
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_concurrent_hash_map_H_include_area
+
 #endif /* __TBB_concurrent_hash_map_H */
index c28fb6e..c743e41 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_concurrent_lru_cache_H
 #define __TBB_concurrent_lru_cache_H
 
+#define __TBB_concurrent_lru_cache_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #if ! TBB_PREVIEW_CONCURRENT_LRU_CACHE
     #error Set TBB_PREVIEW_CONCURRENT_LRU_CACHE to include concurrent_lru_cache.h
 #endif
@@ -280,4 +283,8 @@ private:
 using interface6::concurrent_lru_cache;
 
 } // namespace tbb
+
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_concurrent_lru_cache_H_include_area
+
 #endif //__TBB_concurrent_lru_cache_H
index d022d88..17b9d07 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_concurrent_map_H
 #define __TBB_concurrent_map_H
 
+#define __TBB_concurrent_map_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #if !TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS
 #error Set TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS to include concurrent_map.h
 #endif
@@ -379,5 +382,8 @@ using interface10::concurrent_multimap;
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_concurrent_map_H_include_area
+
 #endif // __TBB_CONCURRENT_ORDERED_CONTAINERS_PRESENT
 #endif // __TBB_concurrent_map_H
index c5c0399..97afa2f 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_concurrent_priority_queue_H
 #define __TBB_concurrent_priority_queue_H
 
+#define __TBB_concurrent_priority_queue_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "atomic.h"
 #include "cache_aligned_allocator.h"
 #include "tbb_exception.h"
@@ -543,4 +546,7 @@ using interface5::concurrent_priority_queue;
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_concurrent_priority_queue_H_include_area
+
 #endif /* __TBB_concurrent_priority_queue_H */
index be8e8f8..1e67325 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_concurrent_queue_H
 #define __TBB_concurrent_queue_H
 
+#define __TBB_concurrent_queue_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "internal/_concurrent_queue_impl.h"
 #include "internal/_allocator_traits.h"
 
@@ -470,4 +473,7 @@ using strict_ppl::concurrent_queue;
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_concurrent_queue_H_include_area
+
 #endif /* __TBB_concurrent_queue_H */
index 7026994..69c9d2e 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_concurrent_set_H
 #define __TBB_concurrent_set_H
 
+#define __TBB_concurrent_set_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #if !TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS
 #error Set TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS to include concurrent_set.h
 #endif
@@ -294,4 +297,8 @@ using interface10::concurrent_multiset;
 } // namespace tbb
 
 #endif // __TBB_CONCURRENT_ORDERED_CONTAINERS_PRESENT
+
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_concurrent_set_H_include_area
+
 #endif // __TBB_concurrent_set_H
index cc73dad..0941628 100644 (file)
@@ -20,6 +20,9 @@
 #ifndef __TBB_concurrent_unordered_map_H
 #define __TBB_concurrent_unordered_map_H
 
+#define __TBB_concurrent_unordered_map_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "internal/_concurrent_unordered_impl.h"
 
 namespace tbb
@@ -483,4 +486,7 @@ using interface5::concurrent_unordered_multimap;
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_concurrent_unordered_map_H_include_area
+
 #endif// __TBB_concurrent_unordered_map_H
index 93a772b..751488d 100644 (file)
@@ -20,6 +20,9 @@
 #ifndef __TBB_concurrent_unordered_set_H
 #define __TBB_concurrent_unordered_set_H
 
+#define __TBB_concurrent_unordered_set_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "internal/_concurrent_unordered_impl.h"
 
 namespace tbb
@@ -439,4 +442,7 @@ using interface5::concurrent_unordered_multiset;
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_concurrent_unordered_set_H_include_area
+
 #endif// __TBB_concurrent_unordered_set_H
index 461d4c3..5ddc38f 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_concurrent_vector_H
 #define __TBB_concurrent_vector_H
 
+#define __TBB_concurrent_vector_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "tbb_stddef.h"
 #include "tbb_exception.h"
 #include "atomic.h"
@@ -338,6 +341,14 @@ public:
             my_item(other.my_item)
         {}
 
+        vector_iterator& operator=( const vector_iterator<Container,typename Container::value_type>& other )
+        {
+            my_vector=other.my_vector;
+            my_index=other.my_index;
+            my_item=other.my_item;
+            return *this;
+        }
+
         vector_iterator operator+( ptrdiff_t offset ) const {
             return vector_iterator( *my_vector, my_index+offset );
         }
@@ -1378,4 +1389,8 @@ inline void swap(concurrent_vector<T, A> &a, concurrent_vector<T, A> &b)
     #pragma warning (pop)
 #endif // warning 4267,4127 are back
 
+
+#undef __TBB_concurrent_vector_H_include_area
+#include "internal/_warning_suppress_disable_notice.h"
+
 #endif /* __TBB_concurrent_vector_H */
index ba693b3..1337179 100644 (file)
     limitations under the License.
 */
 
+#include "internal/_deprecated_header_message_guard.h"
+
+#if !defined(__TBB_show_deprecation_message_critical_section_H) && defined(__TBB_show_deprecated_header_message)
+#define  __TBB_show_deprecation_message_critical_section_H
+#pragma message("TBB Warning: tbb/critical_section.h is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.")
+#endif
+
+#if defined(__TBB_show_deprecated_header_message)
+#undef __TBB_show_deprecated_header_message
+#endif
+
 #ifndef _TBB_CRITICAL_SECTION_H_
 #define _TBB_CRITICAL_SECTION_H_
 
+#define __TBB_critical_section_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #if _WIN32||_WIN64
 #include "machine/windows_api.h"
 #else
@@ -122,8 +136,12 @@ public:
     static const bool is_fair_mutex = true;
 }; // critical_section_v4
 } // namespace internal
-typedef internal::critical_section_v4 critical_section;
+__TBB_DEPRECATED_VERBOSE_MSG("tbb::critical_section is deprecated, use std::mutex") typedef internal::critical_section_v4 critical_section;
 
 __TBB_DEFINE_PROFILING_SET_NAME(critical_section)
 } // namespace tbb
+
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_critical_section_H_include_area
+
 #endif  // _TBB_CRITICAL_SECTION_H_
index 1bcac28..2af1f14 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_enumerable_thread_specific_H
 #define __TBB_enumerable_thread_specific_H
 
+#define __TBB_enumerable_thread_specific_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "atomic.h"
 #include "concurrent_vector.h"
 #include "tbb_thread.h"
 #include "tbb_profiling.h"
 #include <string.h>  // for memcpy
 
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+#include "task.h" // for task::suspend_point
+#endif
+
 #if _WIN32||_WIN64
 #include "machine/windows_api.h"
 #else
 namespace tbb {
 
 //! enum for selecting between single key and key-per-instance versions
-enum ets_key_usage_type { ets_key_per_instance, ets_no_key };
+enum ets_key_usage_type {
+    ets_key_per_instance
+    , ets_no_key
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    , ets_suspend_aware
+#endif
+};
 
 namespace interface6 {
 
@@ -54,10 +67,33 @@ namespace interface6 {
 
         using namespace tbb::internal;
 
+        template <ets_key_usage_type ETS_key_type>
+        struct ets_key_selector {
+            typedef tbb_thread::id key_type;
+            static key_type current_key() {
+                return tbb::internal::thread_get_id_v3();
+            }
+        };
+
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+        template <>
+        struct ets_key_selector<ets_suspend_aware> {
+            typedef task::suspend_point key_type;
+            static key_type current_key() {
+                return internal_current_suspend_point();
+            }
+        };
+
+        inline task::suspend_point atomic_compare_and_swap(task::suspend_point& location,
+                const task::suspend_point& value, const task::suspend_point& comparand) {
+            return as_atomic(location).compare_and_swap(value, comparand);
+        }
+#endif
+
         template<ets_key_usage_type ETS_key_type>
         class ets_base: tbb::internal::no_copy {
         protected:
-            typedef tbb_thread::id key_type;
+            typedef typename ets_key_selector<ETS_key_type>::key_type key_type;
 #if __TBB_PROTECTED_NESTED_CLASS_BROKEN
         public:
 #endif
@@ -115,8 +151,9 @@ namespace interface6 {
             void table_clear();
             // The following functions are not used in concurrent context,
             // so we don't need synchronization and ITT annotations there.
+            template <ets_key_usage_type E2>
             void table_elementwise_copy( const ets_base& other,
-                                         void*(*add_element)(ets_base&, void*) ) {
+                                         void*(*add_element)(ets_base<E2>&, void*) ) {
                 __TBB_ASSERT(!my_root,NULL);
                 __TBB_ASSERT(!my_count,NULL);
                 if( !other.my_root ) return;
@@ -131,7 +168,7 @@ namespace interface6 {
                             for( size_t j = root->start(tbb::tbb_hash<key_type>()(s1.key)); ; j=(j+1)&mask ) {
                                 slot& s2 = root->at(j);
                                 if( s2.empty() ) {
-                                    s2.ptr = add_element(*this, s1.ptr);
+                                    s2.ptr = add_element(static_cast<ets_base<E2>&>(*this), s1.ptr);
                                     s2.key = s1.key;
                                     break;
                                 }
@@ -165,7 +202,7 @@ namespace interface6 {
 
         template<ets_key_usage_type ETS_key_type>
         void* ets_base<ETS_key_type>::table_lookup( bool& exists ) {
-            const key_type k = tbb::this_tbb_thread::get_id();
+            const key_type k = ets_key_selector<ETS_key_type>::current_key();
 
             __TBB_ASSERT(k != key_type(),NULL);
             void* found;
@@ -238,7 +275,7 @@ namespace interface6 {
 
         //! Specialization that exploits native TLS
         template <>
-        class ets_base<ets_key_per_instance>: protected ets_base<ets_no_key> {
+        class ets_base<ets_key_per_instance>: public ets_base<ets_no_key> {
             typedef ets_base<ets_no_key> super;
 #if _WIN32||_WIN64
 #if __TBB_WIN8UI_SUPPORT
@@ -795,7 +832,7 @@ namespace interface6 {
             return lref.value_committed();
         }
 
-        static void* create_local_by_copy( internal::ets_base<ets_no_key>& base, void* p ) {
+        static void* create_local_by_copy( internal::ets_base<ETS_key_type>& base, void* p ) {
             enumerable_thread_specific& ets = static_cast<enumerable_thread_specific&>(base);
             padded_element& lref = *ets.my_locals.grow_by(1);
             new(lref.value()) T(*static_cast<T*>(p));
@@ -803,7 +840,7 @@ namespace interface6 {
         }
 
 #if __TBB_ETS_USE_CPP11
-        static void* create_local_by_move( internal::ets_base<ets_no_key>& base, void* p ) {
+        static void* create_local_by_move( internal::ets_base<ETS_key_type>& base, void* p ) {
             enumerable_thread_specific& ets = static_cast<enumerable_thread_specific&>(base);
             padded_element& lref = *ets.my_locals.grow_by(1);
             new(lref.value()) T(std::move(*static_cast<T*>(p)));
@@ -884,7 +921,7 @@ namespace interface6 {
         ~enumerable_thread_specific() {
             if(my_construct_callback) my_construct_callback->destroy();
             // Deallocate the hash table before overridden free_array() becomes inaccessible
-            this->internal::ets_base<ets_no_key>::table_clear();
+            this->internal::ets_base<ETS_key_type>::table_clear();
         }
 
         //! returns reference to local, discarding exists
@@ -1130,4 +1167,7 @@ using interface6::flatten2d;
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_enumerable_thread_specific_H_include_area
+
 #endif
index cbdad30..5526f95 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_flow_graph_H
 #define __TBB_flow_graph_H
 
+#define __TBB_flow_graph_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "tbb_stddef.h"
 #include "atomic.h"
 #include "spin_mutex.h"
 #include "tbb_profiling.h"
 #include "task_arena.h"
 
+#if TBB_USE_THREADING_TOOLS && TBB_PREVIEW_FLOW_GRAPH_TRACE && ( __linux__ || __APPLE__ )
+   #if __INTEL_COMPILER
+       // Disabled warning "routine is both inline and noinline"
+       #pragma warning (push)
+       #pragma warning( disable: 2196 )
+   #endif
+   #define __TBB_NOINLINE_SYM __attribute__((noinline))
+#else
+   #define __TBB_NOINLINE_SYM
+#endif 
+
 #if __TBB_PREVIEW_ASYNC_MSG
 #include <vector>    // std::vector in internal::async_storage
 #include <memory>    // std::shared_ptr in async_msg
@@ -83,7 +97,7 @@ namespace flow {
 //! An enumeration the provides the two most common concurrency levels: unlimited and serial
 enum concurrency { unlimited = 0, serial = 1 };
 
-namespace interface10 {
+namespace interface11 {
 
 //! A generic null type
 struct null_type {};
@@ -95,11 +109,9 @@ class continue_msg {};
 template< typename T > class sender;
 template< typename T > class receiver;
 class continue_receiver;
-} // namespaceX
-namespace interface11 {
+
 template< typename T, typename U > class limiter_node;  // needed for resetting decrementer
-}
-namespace interface10 {
+
 template< typename R, typename B > class run_and_put_task;
 
 namespace internal {
@@ -110,6 +122,14 @@ template<typename T, typename M> class round_robin_cache;
 template<typename T, typename M> class predecessor_cache;
 template<typename T, typename M> class reservable_predecessor_cache;
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+namespace order {
+struct following;
+struct preceding;
+}
+template<typename Order, typename... Args> struct node_set;
+#endif
+
 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
 // Holder of edges both for caches and for those nodes which do not have predecessor caches.
 // C == receiver< ... > or sender< ... >, depending.
@@ -156,7 +176,7 @@ private:
 
 } // namespace internal
 
-} // namespace interface10
+} // namespace interfaceX
 } // namespace flow
 } // namespace tbb
 
@@ -165,7 +185,7 @@ private:
 
 namespace tbb {
 namespace flow {
-namespace interface10 {
+namespace interface11 {
 
 // enqueue left task if necessary. Returns the non-enqueued task if there is one.
 static inline tbb::task *combine_tasks(graph& g, tbb::task * left, tbb::task * right) {
@@ -380,7 +400,7 @@ protected:
 
     virtual task* try_put_task_wrapper( const void* p, bool is_async ) = 0;
 
-    virtual graph& graph_reference() = 0;
+    virtual graph& graph_reference() const = 0;
 
     // NOTE: Following part of PROTECTED and PRIVATE sections is copy-paste from original receiver<T> class
 
@@ -397,9 +417,9 @@ template< typename T >
 class sender : public internal::untyped_sender {
 public:
     //! The output type of this sender
-    typedef T output_type;
+    __TBB_DEPRECATED typedef T output_type;
 
-    typedef typename internal::async_helpers<T>::filtered_type filtered_type;
+    __TBB_DEPRECATED typedef typename internal::async_helpers<T>::filtered_type filtered_type;
 
     //! Request an item from the sender
     virtual bool try_get( T & ) { return false; }
@@ -436,9 +456,9 @@ class receiver : public internal::untyped_receiver {
     template< typename, typename > friend struct internal::async_helpers;
 public:
     //! The input type of this receiver
-    typedef T input_type;
+    __TBB_DEPRECATED typedef T input_type;
 
-    typedef typename internal::async_helpers<T>::filtered_type filtered_type;
+    __TBB_DEPRECATED typedef typename internal::async_helpers<T>::filtered_type filtered_type;
 
     //! Put an item to the receiver
     bool try_put( const typename internal::async_helpers<T>::filtered_type& t ) {
@@ -466,20 +486,20 @@ template< typename T >
 class sender {
 public:
     //! The output type of this sender
-    typedef T output_type;
+    __TBB_DEPRECATED typedef T output_type;
 
     //! The successor type for this node
-    typedef receiver<T> successor_type;
+    __TBB_DEPRECATED typedef receiver<T> successor_type;
 
     virtual ~sender() {}
 
     // NOTE: Following part of PUBLIC section is partly copy-pasted in sender<T> under #if __TBB_PREVIEW_ASYNC_MSG
 
     //! Add a new successor to this node
-    virtual bool register_successor( successor_type &r ) = 0;
+    __TBB_DEPRECATED virtual bool register_successor( successor_type &r ) = 0;
 
     //! Removes a successor from this node
-    virtual bool remove_successor( successor_type &r ) = 0;
+    __TBB_DEPRECATED virtual bool remove_successor( successor_type &r ) = 0;
 
     //! Request an item from the sender
     virtual bool try_get( T & ) { return false; }
@@ -495,13 +515,13 @@ public:
 
 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
     //! interface to record edges for traversal & deletion
-    typedef typename  internal::edge_container<successor_type> built_successors_type;
-    typedef typename  built_successors_type::edge_list_type successor_list_type;
-    virtual built_successors_type &built_successors()                   = 0;
-    virtual void    internal_add_built_successor( successor_type & )    = 0;
-    virtual void    internal_delete_built_successor( successor_type & ) = 0;
-    virtual void    copy_successors( successor_list_type &)             = 0;
-    virtual size_t  successor_count()                                   = 0;
+    __TBB_DEPRECATED typedef typename  internal::edge_container<successor_type> built_successors_type;
+    __TBB_DEPRECATED typedef typename  built_successors_type::edge_list_type successor_list_type;
+    __TBB_DEPRECATED virtual built_successors_type &built_successors()                   = 0;
+    __TBB_DEPRECATED virtual void    internal_add_built_successor( successor_type & )    = 0;
+    __TBB_DEPRECATED virtual void    internal_delete_built_successor( successor_type & ) = 0;
+    __TBB_DEPRECATED virtual void    copy_successors( successor_list_type &)             = 0;
+    __TBB_DEPRECATED virtual size_t  successor_count()                                   = 0;
 #endif /* TBB_DEPRECATED_FLOW_NODE_EXTRACTION */
 };  // class sender<T>
 
@@ -510,10 +530,10 @@ template< typename T >
 class receiver {
 public:
     //! The input type of this receiver
-    typedef T input_type;
+    __TBB_DEPRECATED typedef T input_type;
 
     //! The predecessor type for this node
-    typedef sender<T> predecessor_type;
+    __TBB_DEPRECATED typedef sender<T> predecessor_type;
 
     //! Destructor
     virtual ~receiver() {}
@@ -532,24 +552,24 @@ protected:
     template< typename X, typename Y > friend class internal::broadcast_cache;
     template< typename X, typename Y > friend class internal::round_robin_cache;
     virtual task *try_put_task(const T& t) = 0;
-    virtual graph& graph_reference() = 0;
+    virtual graph& graph_reference() const = 0;
 public:
     // NOTE: Following part of PUBLIC and PROTECTED sections is copy-pasted in receiver<T> under #if __TBB_PREVIEW_ASYNC_MSG
 
     //! Add a predecessor to the node
-    virtual bool register_predecessor( predecessor_type & ) { return false; }
+    __TBB_DEPRECATED virtual bool register_predecessor( predecessor_type & ) { return false; }
 
     //! Remove a predecessor from the node
-    virtual bool remove_predecessor( predecessor_type & ) { return false; }
+    __TBB_DEPRECATED virtual bool remove_predecessor( predecessor_type & ) { return false; }
 
 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
-    typedef typename internal::edge_container<predecessor_type> built_predecessors_type;
-    typedef typename built_predecessors_type::edge_list_type predecessor_list_type;
-    virtual built_predecessors_type &built_predecessors()                  = 0;
-    virtual void   internal_add_built_predecessor( predecessor_type & )    = 0;
-    virtual void   internal_delete_built_predecessor( predecessor_type & ) = 0;
-    virtual void   copy_predecessors( predecessor_list_type & )            = 0;
-    virtual size_t predecessor_count()                                     = 0;
+    __TBB_DEPRECATED typedef typename internal::edge_container<predecessor_type> built_predecessors_type;
+    __TBB_DEPRECATED typedef typename built_predecessors_type::edge_list_type predecessor_list_type;
+    __TBB_DEPRECATED virtual built_predecessors_type &built_predecessors()                  = 0;
+    __TBB_DEPRECATED virtual void   internal_add_built_predecessor( predecessor_type & )    = 0;
+    __TBB_DEPRECATED virtual void   internal_delete_built_predecessor( predecessor_type & ) = 0;
+    __TBB_DEPRECATED virtual void   copy_predecessors( predecessor_list_type & )            = 0;
+    __TBB_DEPRECATED virtual size_t predecessor_count()                                     = 0;
 #endif /* TBB_DEPRECATED_FLOW_NODE_EXTRACTION */
 
 protected:
@@ -572,13 +592,13 @@ class continue_receiver : public receiver< continue_msg > {
 public:
 
     //! The input type
-    typedef continue_msg input_type;
+    __TBB_DEPRECATED typedef continue_msg input_type;
 
     //! The predecessor type for this node
-    typedef receiver<input_type>::predecessor_type predecessor_type;
+    __TBB_DEPRECATED typedef receiver<input_type>::predecessor_type predecessor_type;
 
     //! Constructor
-    explicit continue_receiver(
+    __TBB_DEPRECATED explicit continue_receiver(
         __TBB_FLOW_GRAPH_PRIORITY_ARG1(int number_of_predecessors, node_priority_t priority)) {
         my_predecessor_count = my_initial_predecessor_count = number_of_predecessors;
         my_current_count = 0;
@@ -586,14 +606,14 @@ public:
     }
 
     //! Copy constructor
-    continue_receiver( const continue_receiver& src ) : receiver<continue_msg>() {
+    __TBB_DEPRECATED continue_receiver( const continue_receiver& src ) : receiver<continue_msg>() {
         my_predecessor_count = my_initial_predecessor_count = src.my_initial_predecessor_count;
         my_current_count = 0;
         __TBB_FLOW_GRAPH_PRIORITY_EXPR( my_priority = src.my_priority; )
     }
 
     //! Increments the trigger threshold
-    bool register_predecessor( predecessor_type & ) __TBB_override {
+    __TBB_DEPRECATED bool register_predecessor( predecessor_type & ) __TBB_override {
         spin_mutex::scoped_lock l(my_mutex);
         ++my_predecessor_count;
         return true;
@@ -603,33 +623,33 @@ public:
     /** Does not check to see if the removal of the predecessor now makes the current count
         exceed the new threshold.  So removing a predecessor while the graph is active can cause
         unexpected results. */
-    bool remove_predecessor( predecessor_type & ) __TBB_override {
+    __TBB_DEPRECATED bool remove_predecessor( predecessor_type & ) __TBB_override {
         spin_mutex::scoped_lock l(my_mutex);
         --my_predecessor_count;
         return true;
     }
 
 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
-    typedef internal::edge_container<predecessor_type> built_predecessors_type;
-    typedef built_predecessors_type::edge_list_type predecessor_list_type;
+    __TBB_DEPRECATED typedef internal::edge_container<predecessor_type> built_predecessors_type;
+    __TBB_DEPRECATED typedef built_predecessors_type::edge_list_type predecessor_list_type;
     built_predecessors_type &built_predecessors() __TBB_override { return my_built_predecessors; }
 
-    void internal_add_built_predecessor( predecessor_type &s) __TBB_override {
+    __TBB_DEPRECATED void internal_add_built_predecessor( predecessor_type &s) __TBB_override {
         spin_mutex::scoped_lock l(my_mutex);
         my_built_predecessors.add_edge( s );
     }
 
-    void internal_delete_built_predecessor( predecessor_type &s) __TBB_override {
+    __TBB_DEPRECATED void internal_delete_built_predecessor( predecessor_type &s) __TBB_override {
         spin_mutex::scoped_lock l(my_mutex);
         my_built_predecessors.delete_edge(s);
     }
 
-    void copy_predecessors( predecessor_list_type &v) __TBB_override {
+    __TBB_DEPRECATED void copy_predecessors( predecessor_list_type &v) __TBB_override {
         spin_mutex::scoped_lock l(my_mutex);
         my_built_predecessors.copy_edges(v);
     }
 
-    size_t predecessor_count() __TBB_override {
+    __TBB_DEPRECATED size_t predecessor_count() __TBB_override {
         spin_mutex::scoped_lock l(my_mutex);
         return my_built_predecessors.edge_count();
     }
@@ -695,9 +715,9 @@ protected:
     }
 #endif /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */
 
-    using interface10::sender;
-    using interface10::receiver;
-    using interface10::continue_receiver;
+    using interface11::sender;
+    using interface11::receiver;
+    using interface11::continue_receiver;
 }  // flow
 }  // tbb
 
@@ -706,7 +726,7 @@ protected:
 
 namespace tbb {
 namespace flow {
-namespace interface10 {
+namespace interface11 {
 
 #include "internal/_flow_graph_body_impl.h"
 #include "internal/_flow_graph_cache_impl.h"
@@ -739,6 +759,9 @@ void graph_iterator<C,N>::internal_forward() {
     if (current_node) current_node = current_node->next;
 }
 
+} // namespace interfaceX
+
+namespace interface10 {
 //! Constructs a graph with isolated task_group_context
 inline graph::graph() : my_nodes(NULL), my_nodes_last(NULL), my_task_arena(NULL) {
     prepare_task_arena();
@@ -784,7 +807,7 @@ inline void graph::release_wait() {
     }
 }
 
-inline void graph::register_node(graph_node *n) {
+inline void graph::register_node(tbb::flow::interface11::graph_node *n) {
     n->next = NULL;
     {
         spin_mutex::scoped_lock lock(nodelist_mutex);
@@ -795,7 +818,7 @@ inline void graph::register_node(graph_node *n) {
     }
 }
 
-inline void graph::remove_node(graph_node *n) {
+inline void graph::remove_node(tbb::flow::interface11::graph_node *n) {
     {
         spin_mutex::scoped_lock lock(nodelist_mutex);
         __TBB_ASSERT(my_nodes && my_nodes_last, "graph::remove_node: Error: no registered nodes");
@@ -807,25 +830,25 @@ inline void graph::remove_node(graph_node *n) {
     n->prev = n->next = NULL;
 }
 
-inline void graph::reset( reset_flags f ) {
+inline void graph::reset( tbb::flow::interface11::reset_flags f ) {
     // reset context
-    internal::deactivate_graph(*this);
+    tbb::flow::interface11::internal::deactivate_graph(*this);
 
     if(my_context) my_context->reset();
     cancelled = false;
     caught_exception = false;
     // reset all the nodes comprising the graph
     for(iterator ii = begin(); ii != end(); ++ii) {
-        graph_node *my_p = &(*ii);
+        tbb::flow::interface11::graph_node *my_p = &(*ii);
         my_p->reset_node(f);
     }
     // Reattach the arena. Might be useful to run the graph in a particular task_arena
     // while not limiting graph lifetime to a single task_arena::execute() call.
     prepare_task_arena( /*reinit=*/true );
-    internal::activate_graph(*this);
+    tbb::flow::interface11::internal::activate_graph(*this);
     // now spawn the tasks necessary to start the graph
     for(task_list_type::iterator rti = my_reset_task_list.begin(); rti != my_reset_task_list.end(); ++rti) {
-        internal::spawn_in_graph_arena(*this, *(*rti));
+        tbb::flow::interface11::internal::spawn_in_graph_arena(*this, *(*rti));
     }
     my_reset_task_list.clear();
 }
@@ -848,6 +871,10 @@ inline void graph::set_name(const char *name) {
 }
 #endif
 
+} // namespace interface10
+
+namespace interface11 {
+
 inline graph_node::graph_node(graph& g) : my_graph(g) {
     my_graph.register_node(this);
 }
@@ -858,6 +885,10 @@ inline graph_node::~graph_node() {
 
 #include "internal/_flow_graph_node_impl.h"
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+using internal::node_set;
+#endif
+
 //! An executable node that acts as a source, i.e. it has no predecessors
 template < typename Output >
 class source_node : public graph_node, public sender< Output > {
@@ -878,26 +909,34 @@ public:
 
     //! Constructor for a node with a successor
     template< typename Body >
-    source_node( graph &g, Body body, bool is_active = true )
+     __TBB_NOINLINE_SYM source_node( graph &g, Body body, bool is_active = true )
         : graph_node(g), my_active(is_active), init_my_active(is_active),
         my_body( new internal::source_body_leaf< output_type, Body>(body) ),
         my_init_body( new internal::source_body_leaf< output_type, Body>(body) ),
         my_reserved(false), my_has_cached_item(false)
     {
         my_successors.set_owner(this);
-        tbb::internal::fgt_node_with_body( tbb::internal::FLOW_SOURCE_NODE, &this->my_graph,
+       tbb::internal::fgt_node_with_body( CODEPTR(), tbb::internal::FLOW_SOURCE_NODE, &this->my_graph,
                                            static_cast<sender<output_type> *>(this), this->my_body );
     }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename Body, typename... Successors>
+    source_node( const node_set<internal::order::preceding, Successors...>& successors, Body body, bool is_active = true )
+        : source_node(successors.graph_reference(), body, is_active) {
+        make_edges(*this, successors);
+    }
+#endif
+
     //! Copy constructor
-    source_node( const source_node& src ) :
+    __TBB_NOINLINE_SYM source_node( const source_node& src ) :
         graph_node(src.my_graph), sender<Output>(),
         my_active(src.init_my_active),
         init_my_active(src.init_my_active), my_body( src.my_init_body->clone() ), my_init_body(src.my_init_body->clone() ),
         my_reserved(false), my_has_cached_item(false)
     {
         my_successors.set_owner(this);
-        tbb::internal::fgt_node_with_body( tbb::internal::FLOW_SOURCE_NODE, &this->my_graph,
+        tbb::internal::fgt_node_with_body(CODEPTR(), tbb::internal::FLOW_SOURCE_NODE, &this->my_graph,
                                            static_cast<sender<output_type> *>(this), this->my_body );
     }
 
@@ -1137,20 +1176,45 @@ public:
     // TODO: pass the graph_buffer_policy to the function_input_base so it can all
     // be done in one place.  This would be an interface-breaking change.
     template< typename Body >
-    function_node(
-        graph &g, size_t concurrency,
-        __TBB_FLOW_GRAPH_PRIORITY_ARG1( Body body, node_priority_t priority = tbb::flow::internal::no_priority )
-    ) : graph_node(g), input_impl_type(g, concurrency, __TBB_FLOW_GRAPH_PRIORITY_ARG1(body, priority)) {
-        tbb::internal::fgt_node_with_body( tbb::internal::FLOW_FUNCTION_NODE, &this->my_graph,
+     __TBB_NOINLINE_SYM function_node( graph &g, size_t concurrency,
+#if __TBB_CPP11_PRESENT
+                   Body body, __TBB_FLOW_GRAPH_PRIORITY_ARG1( Policy = Policy(), node_priority_t priority = tbb::flow::internal::no_priority ))
+#else
+                   __TBB_FLOW_GRAPH_PRIORITY_ARG1( Body body, node_priority_t priority = tbb::flow::internal::no_priority ))
+#endif
+        : graph_node(g), input_impl_type(g, concurrency, __TBB_FLOW_GRAPH_PRIORITY_ARG1(body, priority)),
+          fOutput_type(g) {
+        tbb::internal::fgt_node_with_body( CODEPTR(), tbb::internal::FLOW_FUNCTION_NODE, &this->my_graph,
                 static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this), this->my_body );
     }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES && __TBB_CPP11_PRESENT
+    template <typename Body>
+    function_node( graph& g, size_t concurrency, Body body, node_priority_t priority )
+        : function_node(g, concurrency, body, Policy(), priority) {}
+#endif // __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES && __TBB_CPP11_PRESENT
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename Body, typename... Args>
+    function_node( const node_set<Args...>& nodes, size_t concurrency, Body body,
+                   __TBB_FLOW_GRAPH_PRIORITY_ARG1( Policy p = Policy(), node_priority_t priority = tbb::flow::internal::no_priority ))
+        : function_node(nodes.graph_reference(), concurrency, body, __TBB_FLOW_GRAPH_PRIORITY_ARG1(p, priority)) {
+        make_edges_in_order(nodes, *this);
+    }
+
+#if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
+    template <typename Body, typename... Args>
+    function_node( const node_set<Args...>& nodes, size_t concurrency, Body body, node_priority_t priority )
+        : function_node(nodes, concurrency, body, Policy(), priority) {}
+#endif // __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
     //! Copy constructor
-    function_node( const function_node& src ) :
+    __TBB_NOINLINE_SYM function_node( const function_node& src ) :
         graph_node(src.my_graph),
         input_impl_type(src),
-        fOutput_type() {
-        tbb::internal::fgt_node_with_body( tbb::internal::FLOW_FUNCTION_NODE, &this->my_graph,
+        fOutput_type(src.my_graph) {
+        tbb::internal::fgt_node_with_body( CODEPTR(), tbb::internal::FLOW_FUNCTION_NODE, &this->my_graph,
                 static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this), this->my_body );
     }
 
@@ -1217,20 +1281,45 @@ private:
     using input_impl_type::my_predecessors;
 public:
     template<typename Body>
-    multifunction_node(
+    __TBB_NOINLINE_SYM multifunction_node( 
         graph &g, size_t concurrency,
-        __TBB_FLOW_GRAPH_PRIORITY_ARG1( Body body, node_priority_t priority = tbb::flow::internal::no_priority )
+#if __TBB_CPP11_PRESENT
+        Body body, __TBB_FLOW_GRAPH_PRIORITY_ARG1( Policy = Policy(), node_priority_t priority = tbb::flow::internal::no_priority )
+#else
+        __TBB_FLOW_GRAPH_PRIORITY_ARG1(Body body, node_priority_t priority = tbb::flow::internal::no_priority)
+#endif
     ) : graph_node(g), base_type(g, concurrency, __TBB_FLOW_GRAPH_PRIORITY_ARG1(body, priority)) {
         tbb::internal::fgt_multioutput_node_with_body<N>(
-            tbb::internal::FLOW_MULTIFUNCTION_NODE,
+            CODEPTR(), tbb::internal::FLOW_MULTIFUNCTION_NODE,
             &this->my_graph, static_cast<receiver<input_type> *>(this),
             this->output_ports(), this->my_body
         );
     }
 
-    multifunction_node( const multifunction_node &other) :
+#if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES && __TBB_CPP11_PRESENT
+    template <typename Body>
+    __TBB_NOINLINE_SYM multifunction_node(graph& g, size_t concurrency, Body body, node_priority_t priority)
+        : multifunction_node(g, concurrency, body, Policy(), priority) {}
+#endif // TBB_PREVIEW_FLOW_GRAPH_PRIORITIES && __TBB_CPP11_PRESENT
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename Body, typename... Args>
+    __TBB_NOINLINE_SYM multifunction_node(const node_set<Args...>& nodes, size_t concurrency, Body body,
+                       __TBB_FLOW_GRAPH_PRIORITY_ARG1(Policy p = Policy(), node_priority_t priority = tbb::flow::internal::no_priority))
+        : multifunction_node(nodes.graph_reference(), concurrency, body, __TBB_FLOW_GRAPH_PRIORITY_ARG1(p, priority)) {
+        make_edges_in_order(nodes, *this);
+    }
+
+#if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
+    template <typename Body, typename... Args>
+    __TBB_NOINLINE_SYM multifunction_node(const node_set<Args...>& nodes, size_t concurrency, Body body, node_priority_t priority)
+        : multifunction_node(nodes, concurrency, body, Policy(), priority) {}
+#endif // __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
+    __TBB_NOINLINE_SYM multifunction_node( const multifunction_node &other) :
         graph_node(other.my_graph), base_type(other) {
-        tbb::internal::fgt_multioutput_node_with_body<N>( tbb::internal::FLOW_MULTIFUNCTION_NODE,
+        tbb::internal::fgt_multioutput_node_with_body<N>( CODEPTR(), tbb::internal::FLOW_MULTIFUNCTION_NODE,
                 &this->my_graph, static_cast<receiver<input_type> *>(this),
                 this->output_ports(), this->my_body );
     }
@@ -1274,14 +1363,26 @@ public:
             TupleType // the tuple providing the types
         >::type  output_ports_type;
 
-    explicit split_node(graph &g) : graph_node(g)
+    __TBB_NOINLINE_SYM explicit split_node(graph &g)
+        : graph_node(g),
+          my_output_ports(internal::init_output_ports<output_ports_type>::call(g, my_output_ports))
     {
-        tbb::internal::fgt_multioutput_node<N>(tbb::internal::FLOW_SPLIT_NODE, &this->my_graph,
+        tbb::internal::fgt_multioutput_node<N>(CODEPTR(), tbb::internal::FLOW_SPLIT_NODE, &this->my_graph,
             static_cast<receiver<input_type> *>(this), this->output_ports());
     }
-    split_node( const split_node & other) : graph_node(other.my_graph), base_type(other)
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename... Args>
+    __TBB_NOINLINE_SYM split_node(const node_set<Args...>& nodes) : split_node(nodes.graph_reference()) {
+        make_edges_in_order(nodes, *this);
+    }
+#endif
+
+    __TBB_NOINLINE_SYM split_node(const split_node& other)
+        : graph_node(other.my_graph), base_type(other),
+          my_output_ports(internal::init_output_ports<output_ports_type>::call(other.my_graph, my_output_ports))
     {
-        tbb::internal::fgt_multioutput_node<N>(tbb::internal::FLOW_SPLIT_NODE, &this->my_graph,
+        tbb::internal::fgt_multioutput_node<N>(CODEPTR(), tbb::internal::FLOW_SPLIT_NODE, &this->my_graph,
             static_cast<receiver<input_type> *>(this), this->output_ports());
     }
 
@@ -1306,7 +1407,7 @@ protected:
         __TBB_ASSERT(!(f & rf_clear_edges) || internal::clear_element<N>::this_empty(my_output_ports), "split_node reset failed");
     }
     void reset_receiver(reset_flags /*f*/) __TBB_override {}
-    graph& graph_reference() __TBB_override {
+    graph& graph_reference() const __TBB_override {
         return my_graph;
     }
 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
@@ -1347,32 +1448,85 @@ public:
 
     //! Constructor for executable node with continue_msg -> Output
     template <typename Body >
-    continue_node(
+    __TBB_NOINLINE_SYM continue_node(
         graph &g,
+#if __TBB_CPP11_PRESENT
+        Body body, __TBB_FLOW_GRAPH_PRIORITY_ARG1( Policy = Policy(), node_priority_t priority = tbb::flow::internal::no_priority )
+#else
         __TBB_FLOW_GRAPH_PRIORITY_ARG1( Body body, node_priority_t priority = tbb::flow::internal::no_priority )
-    ) : graph_node(g), input_impl_type( g, __TBB_FLOW_GRAPH_PRIORITY_ARG1(body, priority) ) {
-        tbb::internal::fgt_node_with_body( tbb::internal::FLOW_CONTINUE_NODE, &this->my_graph,
+#endif
+    ) : graph_node(g), input_impl_type( g, __TBB_FLOW_GRAPH_PRIORITY_ARG1(body, priority) ),
+        fOutput_type(g) {
+        tbb::internal::fgt_node_with_body( CODEPTR(), tbb::internal::FLOW_CONTINUE_NODE, &this->my_graph,
+
                                            static_cast<receiver<input_type> *>(this),
                                            static_cast<sender<output_type> *>(this), this->my_body );
     }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES && __TBB_CPP11_PRESENT
+    template <typename Body>
+    continue_node( graph& g, Body body, node_priority_t priority )
+        : continue_node(g, body, Policy(), priority) {}
+#endif
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename Body, typename... Args>
+    continue_node( const node_set<Args...>& nodes, Body body,
+                   __TBB_FLOW_GRAPH_PRIORITY_ARG1( Policy p = Policy(), node_priority_t priority = tbb::flow::internal::no_priority))
+        : continue_node(nodes.graph_reference(), body, __TBB_FLOW_GRAPH_PRIORITY_ARG1(p, priority) ) {
+        make_edges_in_order(nodes, *this);
+    }
+#if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
+    template <typename Body, typename... Args>
+    continue_node( const node_set<Args...>& nodes, Body body, node_priority_t priority)
+        : continue_node(nodes, body, Policy(), priority) {}
+#endif // __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
     //! Constructor for executable node with continue_msg -> Output
     template <typename Body >
-    continue_node(
+    __TBB_NOINLINE_SYM continue_node(
         graph &g, int number_of_predecessors,
+#if __TBB_CPP11_PRESENT
+        Body body, __TBB_FLOW_GRAPH_PRIORITY_ARG1( Policy = Policy(), node_priority_t priority = tbb::flow::internal::no_priority )
+#else
         __TBB_FLOW_GRAPH_PRIORITY_ARG1( Body body, node_priority_t priority = tbb::flow::internal::no_priority )
+#endif
     ) : graph_node(g)
-      , input_impl_type(g, number_of_predecessors, __TBB_FLOW_GRAPH_PRIORITY_ARG1(body, priority)) {
-        tbb::internal::fgt_node_with_body( tbb::internal::FLOW_CONTINUE_NODE, &this->my_graph,
+      , input_impl_type(g, number_of_predecessors, __TBB_FLOW_GRAPH_PRIORITY_ARG1(body, priority)),
+        fOutput_type(g) {
+        tbb::internal::fgt_node_with_body( CODEPTR(), tbb::internal::FLOW_CONTINUE_NODE, &this->my_graph,
                                            static_cast<receiver<input_type> *>(this),
                                            static_cast<sender<output_type> *>(this), this->my_body );
     }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES && __TBB_CPP11_PRESENT
+    template <typename Body>
+    continue_node( graph& g, int number_of_predecessors, Body body, node_priority_t priority)
+        : continue_node(g, number_of_predecessors, body, Policy(), priority) {}
+#endif
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename Body, typename... Args>
+    continue_node( const node_set<Args...>& nodes, int number_of_predecessors,
+                   Body body, __TBB_FLOW_GRAPH_PRIORITY_ARG1( Policy p = Policy(), node_priority_t priority = tbb::flow::internal::no_priority ))
+        : continue_node(nodes.graph_reference(), number_of_predecessors, body, __TBB_FLOW_GRAPH_PRIORITY_ARG1(p, priority)) {
+        make_edges_in_order(nodes, *this);
+    }
+
+#if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
+    template <typename Body, typename... Args>
+    continue_node( const node_set<Args...>& nodes, int number_of_predecessors,
+                   Body body, node_priority_t priority )
+        : continue_node(nodes, number_of_predecessors, body, Policy(), priority) {}
+#endif
+#endif
+
     //! Copy constructor
-    continue_node( const continue_node& src ) :
+    __TBB_NOINLINE_SYM continue_node( const continue_node& src ) :
         graph_node(src.my_graph), input_impl_type(src),
-        internal::function_output<Output>() {
-        tbb::internal::fgt_node_with_body( tbb::internal::FLOW_CONTINUE_NODE, &this->my_graph,
+        internal::function_output<Output>(src.my_graph) {
+        tbb::internal::fgt_node_with_body( CODEPTR(), tbb::internal::FLOW_CONTINUE_NODE, &this->my_graph,
                                            static_cast<receiver<input_type> *>(this),
                                            static_cast<sender<output_type> *>(this), this->my_body );
     }
@@ -1424,18 +1578,25 @@ private:
 #endif
 public:
 
-    explicit broadcast_node(graph& g) : graph_node(g) {
+    __TBB_NOINLINE_SYM explicit broadcast_node(graph& g) : graph_node(g) {
         my_successors.set_owner( this );
-        tbb::internal::fgt_node( tbb::internal::FLOW_BROADCAST_NODE, &this->my_graph,
+        tbb::internal::fgt_node( CODEPTR(), tbb::internal::FLOW_BROADCAST_NODE, &this->my_graph,
                                  static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) );
     }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename... Args>
+    broadcast_node(const node_set<Args...>& nodes) : broadcast_node(nodes.graph_reference()) {
+        make_edges_in_order(nodes, *this);
+    }
+#endif
+
     // Copy constructor
-    broadcast_node( const broadcast_node& src ) :
+    __TBB_NOINLINE_SYM broadcast_node( const broadcast_node& src ) :
         graph_node(src.my_graph), receiver<T>(), sender<T>()
     {
         my_successors.set_owner( this );
-        tbb::internal::fgt_node( tbb::internal::FLOW_BROADCAST_NODE, &this->my_graph,
+        tbb::internal::fgt_node( CODEPTR(), tbb::internal::FLOW_BROADCAST_NODE, &this->my_graph,
                                  static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) );
     }
 
@@ -1519,7 +1680,7 @@ protected:
         return new_task;
     }
 
-    graph& graph_reference() __TBB_override {
+    graph& graph_reference() const __TBB_override {
         return my_graph;
     }
 
@@ -1834,21 +1995,28 @@ protected:
 
 public:
     //! Constructor
-    explicit buffer_node( graph &g ) : graph_node(g), internal::reservable_item_buffer<T>(),
+    __TBB_NOINLINE_SYM explicit buffer_node( graph &g ) : graph_node(g), internal::reservable_item_buffer<T>(),
         forwarder_busy(false) {
         my_successors.set_owner(this);
         my_aggregator.initialize_handler(handler_type(this));
-        tbb::internal::fgt_node( tbb::internal::FLOW_BUFFER_NODE, &this->my_graph,
+        tbb::internal::fgt_node( CODEPTR(), tbb::internal::FLOW_BUFFER_NODE, &this->my_graph,
                                  static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) );
     }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename... Args>
+    buffer_node(const node_set<Args...>& nodes) : buffer_node(nodes.graph_reference()) {
+        make_edges_in_order(nodes, *this);
+    }
+#endif
+
     //! Copy constructor
-    buffer_node( const buffer_node& src ) : graph_node(src.my_graph),
+    __TBB_NOINLINE_SYM buffer_node( const buffer_node& src ) : graph_node(src.my_graph),
         internal::reservable_item_buffer<T>(), receiver<T>(), sender<T>() {
         forwarder_busy = false;
         my_successors.set_owner(this);
         my_aggregator.initialize_handler(handler_type(this));
-        tbb::internal::fgt_node( tbb::internal::FLOW_BUFFER_NODE, &this->my_graph,
+        tbb::internal::fgt_node( CODEPTR(), tbb::internal::FLOW_BUFFER_NODE, &this->my_graph,
                                  static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) );
     }
 
@@ -2003,7 +2171,7 @@ protected:
         return ft;
     }
 
-    graph& graph_reference() __TBB_override {
+    graph& graph_reference() const __TBB_override {
         return my_graph;
     }
 
@@ -2092,15 +2260,22 @@ public:
     typedef typename sender<output_type>::successor_type successor_type;
 
     //! Constructor
-    explicit queue_node( graph &g ) : base_type(g) {
-        tbb::internal::fgt_node( tbb::internal::FLOW_QUEUE_NODE, &(this->my_graph),
+    __TBB_NOINLINE_SYM explicit queue_node( graph &g ) : base_type(g) {
+        tbb::internal::fgt_node( CODEPTR(), tbb::internal::FLOW_QUEUE_NODE, &(this->my_graph),
                                  static_cast<receiver<input_type> *>(this),
                                  static_cast<sender<output_type> *>(this) );
     }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename... Args>
+    queue_node( const node_set<Args...>& nodes) : queue_node(nodes.graph_reference()) {
+        make_edges_in_order(nodes, *this);
+    }
+#endif
+
     //! Copy constructor
-    queue_node( const queue_node& src) : base_type(src) {
-        tbb::internal::fgt_node( tbb::internal::FLOW_QUEUE_NODE, &(this->my_graph),
+    __TBB_NOINLINE_SYM queue_node( const queue_node& src) : base_type(src) {
+        tbb::internal::fgt_node( CODEPTR(), tbb::internal::FLOW_QUEUE_NODE, &(this->my_graph),
                                  static_cast<receiver<input_type> *>(this),
                                  static_cast<sender<output_type> *>(this) );
     }
@@ -2131,17 +2306,25 @@ public:
 
     //! Constructor
     template< typename Sequencer >
-    sequencer_node( graph &g, const Sequencer& s ) : queue_node<T, A>(g),
+    __TBB_NOINLINE_SYM sequencer_node( graph &g, const Sequencer& s ) : queue_node<T, A>(g),
         my_sequencer(new internal::function_body_leaf< T, size_t, Sequencer>(s) ) {
-        tbb::internal::fgt_node( tbb::internal::FLOW_SEQUENCER_NODE, &(this->my_graph),
+        tbb::internal::fgt_node( CODEPTR(), tbb::internal::FLOW_SEQUENCER_NODE, &(this->my_graph),
                                  static_cast<receiver<input_type> *>(this),
                                  static_cast<sender<output_type> *>(this) );
     }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename Sequencer, typename... Args>
+    sequencer_node( const node_set<Args...>& nodes, const Sequencer& s)
+        : sequencer_node(nodes.graph_reference(), s) {
+        make_edges_in_order(nodes, *this);
+    }
+#endif
+
     //! Copy constructor
-    sequencer_node( const sequencer_node& src ) : queue_node<T, A>(src),
+    __TBB_NOINLINE_SYM sequencer_node( const sequencer_node& src ) : queue_node<T, A>(src),
         my_sequencer( src.my_sequencer->clone() ) {
-        tbb::internal::fgt_node( tbb::internal::FLOW_SEQUENCER_NODE, &(this->my_graph),
+        tbb::internal::fgt_node( CODEPTR(), tbb::internal::FLOW_SEQUENCER_NODE, &(this->my_graph),
                                  static_cast<receiver<input_type> *>(this),
                                  static_cast<sender<output_type> *>(this) );
     }
@@ -2195,15 +2378,24 @@ public:
     typedef typename sender<output_type>::successor_type successor_type;
 
     //! Constructor
-    explicit priority_queue_node( graph &g ) : buffer_node<T, A>(g), mark(0) {
-        tbb::internal::fgt_node( tbb::internal::FLOW_PRIORITY_QUEUE_NODE, &(this->my_graph),
+    __TBB_NOINLINE_SYM explicit priority_queue_node( graph &g, const Compare& comp = Compare() )
+        : buffer_node<T, A>(g), compare(comp), mark(0) {
+        tbb::internal::fgt_node( CODEPTR(), tbb::internal::FLOW_PRIORITY_QUEUE_NODE, &(this->my_graph),
                                  static_cast<receiver<input_type> *>(this),
                                  static_cast<sender<output_type> *>(this) );
     }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename... Args>
+    priority_queue_node(const node_set<Args...>& nodes, const Compare& comp = Compare())
+        : priority_queue_node(nodes.graph_reference(), comp) {
+        make_edges_in_order(nodes, *this);
+    }
+#endif
+
     //! Copy constructor
-    priority_queue_node( const priority_queue_node &src ) : buffer_node<T, A>(src), mark(0) {
-        tbb::internal::fgt_node( tbb::internal::FLOW_PRIORITY_QUEUE_NODE, &(this->my_graph),
+    __TBB_NOINLINE_SYM priority_queue_node( const priority_queue_node &src ) : buffer_node<T, A>(src), mark(0) {
+        tbb::internal::fgt_node( CODEPTR(), tbb::internal::FLOW_PRIORITY_QUEUE_NODE, &(this->my_graph),
                                  static_cast<receiver<input_type> *>(this),
                                  static_cast<sender<output_type> *>(this) );
     }
@@ -2398,9 +2590,6 @@ private:
 
 namespace interface11 {
 
-using namespace interface10;
-namespace internal = interface10::internal;
-
 //! Forwards messages only if the threshold has not been reached
 /** This node forwards items until its threshold is reached.
     It contains no buffering.  If the downstream node rejects, the
@@ -2515,7 +2704,7 @@ private:
         my_successors.set_owner(this);
         decrement.set_owner(this);
         tbb::internal::fgt_node(
-            tbb::internal::FLOW_LIMITER_NODE, &this->my_graph,
+            CODEPTR(), tbb::internal::FLOW_LIMITER_NODE, &this->my_graph,
             static_cast<receiver<input_type> *>(this), static_cast<receiver<DecrementType> *>(&decrement),
             static_cast<sender<output_type> *>(this)
         );
@@ -2541,6 +2730,14 @@ public:
         initialize();
     }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename... Args>
+    limiter_node(const node_set<Args...>& nodes, size_t threshold)
+        : limiter_node(nodes.graph_reference(), threshold) {
+        make_edges_in_order(nodes, *this);
+    }
+#endif
+
     //! Copy constructor
     limiter_node( const limiter_node& src ) :
         graph_node(src.my_graph), receiver<T>(), sender<T>(),
@@ -2673,7 +2870,7 @@ protected:
         return rtask;
     }
 
-    graph& graph_reference() __TBB_override { return my_graph; }
+    graph& graph_reference() const __TBB_override { return my_graph; }
 
     void reset_receiver(reset_flags /*f*/) __TBB_override {
         __TBB_ASSERT(false,NULL);  // should never be called
@@ -2692,9 +2889,6 @@ protected:
         decrement.reset_receiver(f);
     }
 };  // limiter_node
-} // namespace interfaceX
-
-namespace interface10 {
 
 #include "internal/_flow_graph_join_impl.h"
 
@@ -2714,12 +2908,20 @@ private:
 public:
     typedef OutputTuple output_type;
     typedef typename unfolded_type::input_ports_type input_ports_type;
-    explicit join_node(graph &g) : unfolded_type(g) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_JOIN_NODE_RESERVING, &this->my_graph,
+     __TBB_NOINLINE_SYM explicit join_node(graph &g) : unfolded_type(g) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::FLOW_JOIN_NODE_RESERVING, &this->my_graph,
                                             this->input_ports(), static_cast< sender< output_type > *>(this) );
     }
-    join_node(const join_node &other) : unfolded_type(other) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_JOIN_NODE_RESERVING, &this->my_graph,
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename... Args>
+    __TBB_NOINLINE_SYM join_node(const node_set<Args...>& nodes, reserving = reserving()) : join_node(nodes.graph_reference()) {
+        make_edges_in_order(nodes, *this);
+    }
+#endif
+
+    __TBB_NOINLINE_SYM join_node(const join_node &other) : unfolded_type(other) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::FLOW_JOIN_NODE_RESERVING, &this->my_graph,
                                             this->input_ports(), static_cast< sender< output_type > *>(this) );
     }
 
@@ -2739,12 +2941,20 @@ private:
 public:
     typedef OutputTuple output_type;
     typedef typename unfolded_type::input_ports_type input_ports_type;
-    explicit join_node(graph &g) : unfolded_type(g) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_JOIN_NODE_QUEUEING, &this->my_graph,
+     __TBB_NOINLINE_SYM explicit join_node(graph &g) : unfolded_type(g) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::FLOW_JOIN_NODE_QUEUEING, &this->my_graph,
                                             this->input_ports(), static_cast< sender< output_type > *>(this) );
     }
-    join_node(const join_node &other) : unfolded_type(other) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_JOIN_NODE_QUEUEING, &this->my_graph,
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename... Args>
+    __TBB_NOINLINE_SYM join_node(const node_set<Args...>& nodes, queueing = queueing()) : join_node(nodes.graph_reference()) {
+        make_edges_in_order(nodes, *this);
+    }
+#endif
+
+    __TBB_NOINLINE_SYM join_node(const join_node &other) : unfolded_type(other) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::FLOW_JOIN_NODE_QUEUEING, &this->my_graph,
                                             this->input_ports(), static_cast< sender< output_type > *>(this) );
     }
 
@@ -2770,76 +2980,94 @@ public:
 
 #if __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING
     join_node(graph &g) : unfolded_type(g) {}
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename... Args>
+    join_node(const node_set<Args...>& nodes, key_matching<K, KHash> = key_matching<K, KHash>())
+        : join_node(nodes.graph_reference()) {
+        make_edges_in_order(nodes, *this);
+    }
+#endif
+
 #endif  /* __TBB_PREVIEW_MESSAGE_BASED_KEY_MATCHING */
 
     template<typename __TBB_B0, typename __TBB_B1>
-    join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1) : unfolded_type(g, b0, b1) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
+     __TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1) : unfolded_type(g, b0, b1) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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>
-    join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2) : unfolded_type(g, b0, b1, b2) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
+     __TBB_NOINLINE_SYM join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2) : unfolded_type(g, b0, b1, b2) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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>
-    join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3) : unfolded_type(g, b0, b1, b2, b3) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
+     __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) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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>
-    join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 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) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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>
-    join_node(graph &g, __TBB_B0 b0, __TBB_B1 b1, __TBB_B2 b2, __TBB_B3 b3, __TBB_B4 b4, __TBB_B5 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) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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>
-    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_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) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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>
-    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_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) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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>
-    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_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) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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>
-    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_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) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
                                                            this->input_ports(), static_cast< sender< output_type > *>(this) );
     }
 #endif
-    join_node(const join_node &other) : unfolded_type(other) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename... Args, typename... Bodies>
+    __TBB_NOINLINE_SYM join_node(const node_set<Args...>& nodes, Bodies... bodies)
+        : join_node(nodes.graph_reference(), bodies...) {
+        make_edges_in_order(nodes, *this);
+    }
+#endif
+
+    __TBB_NOINLINE_SYM join_node(const join_node &other) : unfolded_type(other) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::FLOW_JOIN_NODE_TAG_MATCHING, &this->my_graph,
                                                            this->input_ports(), static_cast< sender< output_type > *>(this) );
     }
 
@@ -2868,13 +3096,21 @@ public:
     typedef tuple<T0> InputTuple;
     typedef typename internal::tagged_msg<size_t, T0> output_type;
     typedef typename internal::unfolded_indexer_node<InputTuple> unfolded_type;
-    indexer_node(graph& g) : unfolded_type(g) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
                                            this->input_ports(), static_cast< sender< output_type > *>(this) );
     }
 
@@ -2893,13 +3129,21 @@ public:
     typedef tuple<T0, T1> InputTuple;
     typedef typename internal::tagged_msg<size_t, T0, T1> output_type;
     typedef typename internal::unfolded_indexer_node<InputTuple> unfolded_type;
-    indexer_node(graph& g) : unfolded_type(g) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
                                            this->input_ports(), static_cast< sender< output_type > *>(this) );
     }
 
@@ -2918,13 +3162,21 @@ public:
     typedef tuple<T0, T1, T2> InputTuple;
     typedef typename internal::tagged_msg<size_t, T0, T1, T2> output_type;
     typedef typename internal::unfolded_indexer_node<InputTuple> unfolded_type;
-    indexer_node(graph& g) : unfolded_type(g) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
                                            this->input_ports(), static_cast< sender< output_type > *>(this) );
     }
 
@@ -2943,13 +3195,21 @@ public:
     typedef tuple<T0, T1, T2, T3> InputTuple;
     typedef typename internal::tagged_msg<size_t, T0, T1, T2, T3> output_type;
     typedef typename internal::unfolded_indexer_node<InputTuple> unfolded_type;
-    indexer_node(graph& g) : unfolded_type(g) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
                                            this->input_ports(), static_cast< sender< output_type > *>(this) );
     }
 
@@ -2968,13 +3228,21 @@ public:
     typedef tuple<T0, T1, T2, T3, T4> InputTuple;
     typedef typename internal::tagged_msg<size_t, T0, T1, T2, T3, T4> output_type;
     typedef typename internal::unfolded_indexer_node<InputTuple> unfolded_type;
-    indexer_node(graph& g) : unfolded_type(g) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
                                            this->input_ports(), static_cast< sender< output_type > *>(this) );
     }
 
@@ -2994,13 +3262,21 @@ public:
     typedef tuple<T0, T1, T2, T3, T4, T5> InputTuple;
     typedef typename internal::tagged_msg<size_t, T0, T1, T2, T3, T4, T5> output_type;
     typedef typename internal::unfolded_indexer_node<InputTuple> unfolded_type;
-    indexer_node(graph& g) : unfolded_type(g) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
                                            this->input_ports(), static_cast< sender< output_type > *>(this) );
     }
 
@@ -3022,13 +3298,21 @@ public:
     typedef tuple<T0, T1, T2, T3, T4, T5, T6> InputTuple;
     typedef typename internal::tagged_msg<size_t, T0, T1, T2, T3, T4, T5, T6> output_type;
     typedef typename internal::unfolded_indexer_node<InputTuple> unfolded_type;
-    indexer_node(graph& g) : unfolded_type(g) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
                                            this->input_ports(), static_cast< sender< output_type > *>(this) );
     }
 
@@ -3051,12 +3335,20 @@ public:
     typedef typename internal::tagged_msg<size_t, T0, T1, T2, T3, T4, T5, T6, T7> output_type;
     typedef typename internal::unfolded_indexer_node<InputTuple> unfolded_type;
     indexer_node(graph& g) : unfolded_type(g) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
                                            this->input_ports(), static_cast< sender< output_type > *>(this) );
     }
 
@@ -3078,13 +3370,21 @@ public:
     typedef tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8> InputTuple;
     typedef typename internal::tagged_msg<size_t, T0, T1, T2, T3, T4, T5, T6, T7, T8> output_type;
     typedef typename internal::unfolded_indexer_node<InputTuple> unfolded_type;
-    indexer_node(graph& g) : unfolded_type(g) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
                                            this->input_ports(), static_cast< sender< output_type > *>(this) );
     }
 
@@ -3106,13 +3406,21 @@ public:
     typedef tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> InputTuple;
     typedef typename internal::tagged_msg<size_t, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> output_type;
     typedef typename internal::unfolded_indexer_node<InputTuple> unfolded_type;
-    indexer_node(graph& g) : unfolded_type(g) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node(graph& g) : unfolded_type(g) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::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) {
-        tbb::internal::fgt_multiinput_node<N>( tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
+    __TBB_NOINLINE_SYM indexer_node( const indexer_node& other ) : unfolded_type(other) {
+        tbb::internal::fgt_multiinput_node<N>( CODEPTR(), tbb::internal::FLOW_INDEXER_NODE, &this->my_graph,
                                            this->input_ports(), static_cast< sender< output_type > *>(this) );
     }
 
@@ -3300,12 +3608,12 @@ protected:
 public:
 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
     composite_node( graph &g, const char *type_name = "composite_node" ) : graph_node(g) {
-        tbb::internal::fgt_multiinput_multioutput_node( tbb::internal::FLOW_COMPOSITE_NODE, this, &this->my_graph );
+        tbb::internal::fgt_multiinput_multioutput_node( CODEPTR(), tbb::internal::FLOW_COMPOSITE_NODE, this, &this->my_graph );
         tbb::internal::fgt_multiinput_multioutput_node_desc( this, type_name );
     }
 #else
     composite_node( graph &g ) : graph_node(g) {
-        tbb::internal::fgt_multiinput_multioutput_node( tbb::internal::FLOW_COMPOSITE_NODE, this, &this->my_graph );
+        tbb::internal::fgt_multiinput_multioutput_node( CODEPTR(), tbb::internal::FLOW_COMPOSITE_NODE, this, &this->my_graph );
     }
 #endif
 
@@ -3365,12 +3673,12 @@ protected:
 public:
 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
     composite_node( graph &g, const char *type_name = "composite_node") : graph_node(g) {
-        tbb::internal::fgt_composite( this, &g );
+        tbb::internal::fgt_composite( CODEPTR(), this, &g );
         tbb::internal::fgt_multiinput_multioutput_node_desc( this, type_name );
     }
 #else
     composite_node( graph &g ) : graph_node(g) {
-        tbb::internal::fgt_composite( this, &g );
+        tbb::internal::fgt_composite( CODEPTR(), this, &g );
     }
 #endif
 
@@ -3423,13 +3731,13 @@ protected:
 
 public:
 #if TBB_PREVIEW_FLOW_GRAPH_TRACE
-    composite_node( graph &g, const char *type_name = "composite_node") : graph_node(g) {
-        tbb::internal::fgt_composite( this, &g );
+    __TBB_NOINLINE_SYM composite_node( graph &g, const char *type_name = "composite_node") : graph_node(g) {
+        tbb::internal::fgt_composite( CODEPTR(), this, &g );
         tbb::internal::fgt_multiinput_multioutput_node_desc( this, type_name );
     }
 #else
-    composite_node( graph &g ) : graph_node(g) {
-        tbb::internal::fgt_composite( this, &g );
+    __TBB_NOINLINE_SYM composite_node( graph &g ) : graph_node(g) {
+        tbb::internal::fgt_composite( CODEPTR(), this, &g );
     }
 #endif
 
@@ -3504,7 +3812,10 @@ private:
     Body my_body;
 };
 
-}
+} // namespace internal
+
+} // namespace interfaceX
+namespace interface11 {
 
 //! Implements async node
 template < typename Input, typename Output,
@@ -3581,25 +3892,51 @@ private:
 
 public:
     template<typename Body>
-    async_node(
+    __TBB_NOINLINE_SYM async_node(
         graph &g, size_t concurrency,
-        __TBB_FLOW_GRAPH_PRIORITY_ARG1( Body body, node_priority_t priority = tbb::flow::internal::no_priority )
+#if __TBB_CPP11_PRESENT
+        Body body, __TBB_FLOW_GRAPH_PRIORITY_ARG1(Policy = Policy(), node_priority_t priority = tbb::flow::internal::no_priority)
+#else
+        __TBB_FLOW_GRAPH_PRIORITY_ARG1(Body body, node_priority_t priority = tbb::flow::internal::no_priority)
+#endif
     ) : base_type(
         g, concurrency,
         internal::async_body<Input, typename base_type::output_ports_type, gateway_type, Body>
         (body, &my_gateway) __TBB_FLOW_GRAPH_PRIORITY_ARG0(priority) ), my_gateway(self()) {
         tbb::internal::fgt_multioutput_node_with_body<1>(
-            tbb::internal::FLOW_ASYNC_NODE,
+            CODEPTR(), tbb::internal::FLOW_ASYNC_NODE,
             &this->my_graph, static_cast<receiver<input_type> *>(this),
             this->output_ports(), this->my_body
         );
     }
 
-    async_node( const async_node &other ) : base_type(other), sender<Output>(), my_gateway(self()) {
+#if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES && __TBB_CPP11_PRESENT
+    template <typename Body, typename... Args>
+    __TBB_NOINLINE_SYM async_node(graph& g, size_t concurrency, Body body, node_priority_t priority)
+        : async_node(g, concurrency, body, Policy(), priority) {}
+#endif // __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename Body, typename... Args>
+    __TBB_NOINLINE_SYM async_node(
+        const node_set<Args...>& nodes, size_t concurrency, Body body,
+        __TBB_FLOW_GRAPH_PRIORITY_ARG1(Policy = Policy(), node_priority_t priority = tbb::flow::internal::no_priority)
+    ) : async_node(nodes.graph_reference(), concurrency, __TBB_FLOW_GRAPH_PRIORITY_ARG1(body, priority)) {
+        make_edges_in_order(nodes, *this);
+    }
+
+#if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
+    template <typename Body, typename... Args>
+    __TBB_NOINLINE_SYM async_node(const node_set<Args...>& nodes, size_t concurrency, Body body, node_priority_t priority)
+        : async_node(nodes, concurrency, body, Policy(), priority) {}
+#endif // __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
+    __TBB_NOINLINE_SYM async_node( const async_node &other ) : base_type(other), sender<Output>(), my_gateway(self()) {
         static_cast<async_body_base_type*>(this->my_body->get_body_ptr())->set_gateway(&my_gateway);
         static_cast<async_body_base_type*>(this->my_init_body->get_body_ptr())->set_gateway(&my_gateway);
 
-        tbb::internal::fgt_multioutput_node_with_body<1>( tbb::internal::FLOW_ASYNC_NODE,
+        tbb::internal::fgt_multioutput_node_with_body<1>( CODEPTR(), tbb::internal::FLOW_ASYNC_NODE,
                 &this->my_graph, static_cast<receiver<input_type> *>(this),
                 this->output_ports(), this->my_body );
     }
@@ -3671,13 +4008,7 @@ protected:
 #include "internal/_flow_graph_streaming_node.h"
 #endif // __TBB_PREVIEW_STREAMING_NODE
 
-} // interfaceX
-
-
-namespace interface10a {
-
-using namespace interface10;
-namespace internal = interface10::internal;
+#include "internal/_flow_graph_node_set_impl.h"
 
 template< typename T >
 class overwrite_node : public graph_node, public receiver<T>, public sender<T> {
@@ -3693,18 +4024,25 @@ public:
     typedef typename sender<output_type>::successor_list_type successor_list_type;
 #endif
 
-    explicit overwrite_node(graph &g) : graph_node(g), my_buffer_is_valid(false) {
+    __TBB_NOINLINE_SYM explicit overwrite_node(graph &g) : graph_node(g), my_buffer_is_valid(false) {
         my_successors.set_owner( this );
-        tbb::internal::fgt_node( tbb::internal::FLOW_OVERWRITE_NODE, &this->my_graph,
+        tbb::internal::fgt_node( CODEPTR(), tbb::internal::FLOW_OVERWRITE_NODE, &this->my_graph,
                                  static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) );
     }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename... Args>
+    overwrite_node(const node_set<Args...>& nodes) : overwrite_node(nodes.graph_reference()) {
+        make_edges_in_order(nodes, *this);
+    }
+#endif
+
     //! Copy constructor; doesn't take anything from src; default won't work
-    overwrite_node( const overwrite_node& src ) :
+    __TBB_NOINLINE_SYM overwrite_node( const overwrite_node& src ) :
         graph_node(src.my_graph), receiver<T>(), sender<T>(), my_buffer_is_valid(false)
     {
         my_successors.set_owner( this );
-        tbb::internal::fgt_node( tbb::internal::FLOW_OVERWRITE_NODE, &this->my_graph,
+        tbb::internal::fgt_node( CODEPTR(), tbb::internal::FLOW_OVERWRITE_NODE, &this->my_graph,
                                  static_cast<receiver<input_type> *>(this), static_cast<sender<output_type> *>(this) );
     }
 
@@ -3846,7 +4184,7 @@ protected:
         return rtask;
     }
 
-    graph& graph_reference() __TBB_override {
+    graph& graph_reference() const __TBB_override {
         return my_graph;
     }
 
@@ -3894,15 +4232,22 @@ public:
     typedef typename sender<output_type>::successor_type successor_type;
 
     //! Constructor
-    explicit write_once_node(graph& g) : base_type(g) {
-        tbb::internal::fgt_node( tbb::internal::FLOW_WRITE_ONCE_NODE, &(this->my_graph),
+    __TBB_NOINLINE_SYM explicit write_once_node(graph& g) : base_type(g) {
+        tbb::internal::fgt_node( CODEPTR(), tbb::internal::FLOW_WRITE_ONCE_NODE, &(this->my_graph),
                                  static_cast<receiver<input_type> *>(this),
                                  static_cast<sender<output_type> *>(this) );
     }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    template <typename... Args>
+    write_once_node(const node_set<Args...>& nodes) : write_once_node(nodes.graph_reference()) {
+        make_edges_in_order(nodes, *this);
+    }
+#endif
+
     //! Copy constructor: call base class copy constructor
-    write_once_node( const write_once_node& src ) : base_type(src) {
-        tbb::internal::fgt_node( tbb::internal::FLOW_WRITE_ONCE_NODE, &(this->my_graph),
+    __TBB_NOINLINE_SYM write_once_node( const write_once_node& src ) : base_type(src) {
+        tbb::internal::fgt_node( CODEPTR(), tbb::internal::FLOW_WRITE_ONCE_NODE, &(this->my_graph),
                                  static_cast<receiver<input_type> *>(this),
                                  static_cast<sender<output_type> *>(this) );
     }
@@ -3922,63 +4267,80 @@ protected:
         return this->my_buffer_is_valid ? NULL : this->try_put_task_impl(v);
     }
 };
+
 } // interfaceX
 
-    using interface10::reset_flags;
-    using interface10::rf_reset_protocol;
-    using interface10::rf_reset_bodies;
-    using interface10::rf_clear_edges;
-
-    using interface10::graph;
-    using interface10::graph_node;
-    using interface10::continue_msg;
-
-    using interface10::source_node;
-    using interface10::function_node;
-    using interface10::multifunction_node;
-    using interface10::split_node;
-    using interface10::internal::output_port;
-    using interface10::indexer_node;
-    using interface10::internal::tagged_msg;
-    using interface10::internal::cast_to;
-    using interface10::internal::is_a;
-    using interface10::continue_node;
-    using interface10a::overwrite_node;
-    using interface10a::write_once_node;
-    using interface10::broadcast_node;
-    using interface10::buffer_node;
-    using interface10::queue_node;
-    using interface10::sequencer_node;
-    using interface10::priority_queue_node;
+    using interface11::reset_flags;
+    using interface11::rf_reset_protocol;
+    using interface11::rf_reset_bodies;
+    using interface11::rf_clear_edges;
+
+    using interface11::graph;
+    using interface11::graph_node;
+    using interface11::continue_msg;
+
+    using interface11::source_node;
+    using interface11::function_node;
+    using interface11::multifunction_node;
+    using interface11::split_node;
+    using interface11::internal::output_port;
+    using interface11::indexer_node;
+    using interface11::internal::tagged_msg;
+    using interface11::internal::cast_to;
+    using interface11::internal::is_a;
+    using interface11::continue_node;
+    using interface11::overwrite_node;
+    using interface11::write_once_node;
+    using interface11::broadcast_node;
+    using interface11::buffer_node;
+    using interface11::queue_node;
+    using interface11::sequencer_node;
+    using interface11::priority_queue_node;
     using interface11::limiter_node;
-    using namespace interface10::internal::graph_policy_namespace;
-    using interface10::join_node;
-    using interface10::input_port;
-    using interface10::copy_body;
-    using interface10::make_edge;
-    using interface10::remove_edge;
-    using interface10::internal::tag_value;
+    using namespace interface11::internal::graph_policy_namespace;
+    using interface11::join_node;
+    using interface11::input_port;
+    using interface11::copy_body;
+    using interface11::make_edge;
+    using interface11::remove_edge;
+    using interface11::internal::tag_value;
 #if __TBB_FLOW_GRAPH_CPP11_FEATURES
-    using interface10::composite_node;
+    using interface11::composite_node;
 #endif
-    using interface10::async_node;
+    using interface11::async_node;
 #if __TBB_PREVIEW_ASYNC_MSG
-    using interface10::async_msg;
+    using interface11::async_msg;
 #endif
 #if __TBB_PREVIEW_STREAMING_NODE
-    using interface10::port_ref;
-    using interface10::streaming_node;
+    using interface11::port_ref;
+    using interface11::streaming_node;
 #endif // __TBB_PREVIEW_STREAMING_NODE
 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
     using internal::node_priority_t;
     using internal::no_priority;
 #endif
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    using interface11::internal::follows;
+    using interface11::internal::precedes;
+    using interface11::internal::make_node_set;
+    using interface11::internal::make_edges;
+#endif
 
 } // flow
 } // tbb
 
+// Include deduction guides for node classes
+#include "internal/_flow_graph_nodes_deduction.h"
+
 #undef __TBB_PFG_RESET_ARG
 #undef __TBB_COMMA
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_flow_graph_H_include_area
+
+#if TBB_USE_THREADING_TOOLS && TBB_PREVIEW_FLOW_GRAPH_TRACE && ( __linux__ || __APPLE__ )
+   #undef __TBB_NOINLINE_SYM
+#endif
+
 #endif // __TBB_flow_graph_H
index e690f0d..0306763 100644 (file)
@@ -19,7 +19,7 @@
 
 namespace tbb {
 namespace flow {
-namespace interface10 {
+namespace interface11 {
 
 //! Pure virtual template classes that define interfaces for async communication
 class graph_proxy {
@@ -45,8 +45,8 @@ public:
 
 } //interfaceX
 
-using interface10::graph_proxy;
-using interface10::receiver_gateway;
+using interface11::graph_proxy;
+using interface11::receiver_gateway;
 
 } //flow
 } //tbb
index 2c99fb3..c9baf7b 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_flow_graph_opencl_node_H
 #define __TBB_flow_graph_opencl_node_H
 
+#define __TBB_flow_graph_opencl_node_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "tbb/tbb_config.h"
 #if __TBB_PREVIEW_OPENCL_NODE
 
@@ -39,7 +42,7 @@
 namespace tbb {
 namespace flow {
 
-namespace interface10 {
+namespace interface11 {
 
 template <typename DeviceFilter>
 class opencl_factory;
@@ -1410,20 +1413,20 @@ public:
     opencl_node( graph &g, const kernel_type& kernel )
         : base_type( g, kernel, opencl_info::default_device_selector< opencl_info::default_opencl_factory >(), opencl_info::default_factory() )
     {
-        tbb::internal::fgt_multiinput_multioutput_node( tbb::internal::FLOW_OPENCL_NODE, this, &this->my_graph );
+        tbb::internal::fgt_multiinput_multioutput_node( CODEPTR(), tbb::internal::FLOW_OPENCL_NODE, this, &this->my_graph );
     }
 
     opencl_node( graph &g, const kernel_type& kernel, Factory &f )
         : base_type( g, kernel, opencl_info::default_device_selector <Factory >(), f )
     {
-        tbb::internal::fgt_multiinput_multioutput_node( tbb::internal::FLOW_OPENCL_NODE, this, &this->my_graph );
+        tbb::internal::fgt_multiinput_multioutput_node( CODEPTR(), tbb::internal::FLOW_OPENCL_NODE, this, &this->my_graph );
     }
 
     template <typename DeviceSelector>
     opencl_node( graph &g, const kernel_type& kernel, DeviceSelector d, Factory &f)
         : base_type( g, kernel, d, f)
     {
-        tbb::internal::fgt_multiinput_multioutput_node( tbb::internal::FLOW_OPENCL_NODE, this, &this->my_graph );
+        tbb::internal::fgt_multiinput_multioutput_node( CODEPTR(), tbb::internal::FLOW_OPENCL_NODE, this, &this->my_graph );
     }
 };
 
@@ -1459,24 +1462,27 @@ public:
     {}
 };
 
-} // namespace interface10
-
-using interface10::opencl_node;
-using interface10::read_only;
-using interface10::read_write;
-using interface10::write_only;
-using interface10::opencl_buffer;
-using interface10::opencl_subbuffer;
-using interface10::opencl_device;
-using interface10::opencl_device_list;
-using interface10::opencl_program;
-using interface10::opencl_program_type;
-using interface10::opencl_async_msg;
-using interface10::opencl_factory;
-using interface10::opencl_range;
+} // namespace interfaceX
+
+using interface11::opencl_node;
+using interface11::read_only;
+using interface11::read_write;
+using interface11::write_only;
+using interface11::opencl_buffer;
+using interface11::opencl_subbuffer;
+using interface11::opencl_device;
+using interface11::opencl_device_list;
+using interface11::opencl_program;
+using interface11::opencl_program_type;
+using interface11::opencl_async_msg;
+using interface11::opencl_factory;
+using interface11::opencl_range;
 
 } // namespace flow
 } // namespace tbb
 #endif /* __TBB_PREVIEW_OPENCL_NODE */
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_flow_graph_opencl_node_H_include_area
+
 #endif // __TBB_flow_graph_opencl_node_H
index c1aafc9..594f952 100644 (file)
@@ -643,7 +643,7 @@ bool concurrent_queue_iterator_rep<T>::get_item( T*& item, size_t k ) {
 //! Constness-independent portion of concurrent_queue_iterator.
 /** @ingroup containers */
 template<typename Value>
-class concurrent_queue_iterator_base_v3 : no_assign {
+class concurrent_queue_iterator_base_v3 {
     //! Represents concurrent_queue over which we are iterating.
     /** NULL if one past last element in queue. */
     concurrent_queue_iterator_rep<Value>* my_rep;
@@ -666,10 +666,15 @@ protected:
 
     //! Copy constructor
     concurrent_queue_iterator_base_v3( const concurrent_queue_iterator_base_v3& i )
-    : no_assign(), my_rep(NULL), my_item(NULL) {
+    : my_rep(NULL), my_item(NULL) {
         assign(i);
     }
 
+    concurrent_queue_iterator_base_v3& operator=( const concurrent_queue_iterator_base_v3& i ) {
+        assign(i);
+        return *this;
+    }
+
     //! Construct iterator pointing to head of queue.
     concurrent_queue_iterator_base_v3( const concurrent_queue_base_v3<Value>& queue ) ;
 
@@ -764,8 +769,8 @@ public:
     {}
 
     //! Iterator assignment
-    concurrent_queue_iterator& operator=( const concurrent_queue_iterator& other ) {
-        this->assign(other);
+    concurrent_queue_iterator& operator=( const concurrent_queue_iterator<Container,typename Container::value_type>& other ) {
+        concurrent_queue_iterator_base_v3<typename tbb_remove_cv<Value>::type>::operator=(other);
         return *this;
     }
 
@@ -976,6 +981,11 @@ protected:
         assign(i);
     }
 
+    concurrent_queue_iterator_base_v3& operator=( const concurrent_queue_iterator_base_v3& i ) {
+        assign(i);
+        return *this;
+    }
+
     //! Obsolete entry point for constructing iterator pointing to head of queue.
     /** Does not work correctly for SSE types. */
     __TBB_EXPORTED_METHOD concurrent_queue_iterator_base_v3( const concurrent_queue_base_v3& queue );
@@ -1025,8 +1035,8 @@ public:
     {}
 
     //! Iterator assignment
-    concurrent_queue_iterator& operator=( const concurrent_queue_iterator& other ) {
-        assign(other);
+    concurrent_queue_iterator& operator=( const concurrent_queue_iterator<Container,typename Container::value_type>& other ) {
+        concurrent_queue_iterator_base_v3::operator=(other);
         return *this;
     }
 
index 685c45a..ed9abc5 100644 (file)
@@ -163,6 +163,11 @@ public:
 
     skip_list_iterator(const skip_list_iterator<node_type, false>& other) : my_node_ptr(other.my_node_ptr) {}
 
+    skip_list_iterator& operator=(const skip_list_iterator<node_type, false>& other) {
+         my_node_ptr = other.my_node_ptr;
+         return *this;
+    }
+
     template <typename T = void, typename = typename std::enable_if<is_const, T>::type>
     skip_list_iterator(const skip_list_iterator<node_type, true>& other) : my_node_ptr(other.my_node_ptr) {}
 
@@ -404,11 +409,25 @@ public:
         std::pair<node_ptr, node_ptr> extract_result = internal_extract(pos);
         if(extract_result.first) { // node was extracted
             delete_node(extract_result.first);
-            return extract_result.second;
+            return iterator(extract_result.second);
         }
         return end();
     }
 
+    iterator unsafe_erase(const_iterator pos) {
+        return unsafe_erase(get_iterator(pos));
+    }
+
+    template <typename K, typename = tbb::internal::is_transparent<key_compare, K>,
+                          typename = typename std::enable_if<!std::is_convertible<K, iterator>::value &&
+                                                             !std::is_convertible<K, const_iterator>::value>::type>
+    size_type unsafe_erase(const K& key) {
+        std::pair<iterator, iterator> range = equal_range(key);
+        size_type sz = std::distance(range.first, range.second);
+        unsafe_erase(range.first, range.second);
+        return sz;
+    }
+
     iterator unsafe_erase(const_iterator first, const_iterator last) {
         while(first != last) {
             first = unsafe_erase(get_iterator(first));
@@ -440,12 +459,12 @@ public:
         return internal_get_bound(key, my_compare);
     }
 
-    template<typename K, typename = typename std::enable_if<tbb::internal::has_is_transparent<key_compare>::value, K>::type>
+    template <typename K, typename = typename tbb::internal::is_transparent<key_compare, K> >
     iterator lower_bound(const K& key) {
         return internal_get_bound(key, my_compare);
     }
 
-    template<typename K, typename = typename std::enable_if<tbb::internal::has_is_transparent<key_compare>::value, K>::type>
+    template <typename K, typename = typename tbb::internal::is_transparent<key_compare, K> >
     const_iterator lower_bound(const K& key) const {
         return internal_get_bound(key, my_compare);
     }
@@ -458,12 +477,12 @@ public:
         return internal_get_bound(key, not_greater_compare(my_compare));
     }
 
-    template<typename K, typename = typename std::enable_if<tbb::internal::has_is_transparent<key_compare>::value, K>::type>
+    template <typename K, typename = typename tbb::internal::is_transparent<key_compare, K> >
     iterator upper_bound(const K& key) {
         return internal_get_bound(key, not_greater_compare(my_compare));
     }
 
-    template<typename K, typename = typename std::enable_if<tbb::internal::has_is_transparent<key_compare>::value, K>::type>
+    template <typename K, typename = typename tbb::internal::is_transparent<key_compare, K> >
     const_iterator upper_bound(const K& key) const {
         return internal_get_bound(key, not_greater_compare(my_compare));
     }
@@ -476,12 +495,12 @@ public:
         return internal_find(key);
     }
 
-    template<typename K, typename = typename std::enable_if<tbb::internal::has_is_transparent<key_compare>::value, K>::type>
+    template <typename K, typename = typename tbb::internal::is_transparent<key_compare, K> >
     iterator find(const K& key) {
         return internal_find(key);
     }
 
-    template<typename K, typename = typename std::enable_if<tbb::internal::has_is_transparent<key_compare>::value, K>::type>
+    template <typename K, typename = typename tbb::internal::is_transparent<key_compare, K> >
     const_iterator find(const K& key) const {
         return internal_find(key);
     }
@@ -490,7 +509,7 @@ public:
         return internal_count(key);
     }
 
-    template<typename K, typename = typename std::enable_if<tbb::internal::has_is_transparent<key_compare>::value, K>::type>
+    template <typename K, typename = typename tbb::internal::is_transparent<key_compare, K> >
     size_type count(const K& key) const {
         return internal_count(key);
     }
@@ -499,7 +518,7 @@ public:
         return find(key) != end();
     }
 
-    template<typename K, typename = typename std::enable_if<tbb::internal::has_is_transparent<key_compare>::value, K>::type>
+    template <typename K, typename = typename tbb::internal::is_transparent<key_compare, K> >
     bool contains(const K& key) const {
         return find(key) != end();
     }
@@ -582,12 +601,12 @@ public:
         return std::pair<const_iterator, const_iterator>(lower_bound(key), upper_bound(key));
     }
 
-    template<typename K, typename = typename std::enable_if<tbb::internal::has_is_transparent<key_compare>::value, K>::type>
+    template <typename K, typename = typename tbb::internal::is_transparent<key_compare, K> >
     std::pair<iterator, iterator> equal_range(const K& key) {
         return std::pair<iterator, iterator>(lower_bound(key), upper_bound(key));
     }
 
-    template<typename K, typename = typename std::enable_if<tbb::internal::has_is_transparent<key_compare>::value, K>::type>
+    template <typename K, typename = typename tbb::internal::is_transparent<key_compare, K> >
     std::pair<const_iterator, const_iterator> equal_range(const K& key) const {
         return std::pair<const_iterator, const_iterator>(lower_bound(key), upper_bound(key));
     }
@@ -727,6 +746,29 @@ private:
         }
     }
 
+    template <typename comparator>
+    void fill_prev_next_by_ptr(array_type& prev_nodes, array_type& next_nodes, const_iterator it, const key_type& key,
+                               const comparator& cmp) {
+        node_ptr prev = dummy_head;
+        node_ptr erase_node = it.my_node_ptr;
+        size_type node_height = erase_node->height();
+
+        for (size_type h = prev->height(); h >= node_height; --h) {
+            internal_find_position(h - 1, prev, key, cmp);
+        }
+
+        for (size_type h = node_height; h > 0; --h) {
+            node_ptr curr = prev->next(h - 1);
+            while (const_iterator(curr) != it) {
+                prev = curr;
+                curr = prev->next(h - 1);
+            }
+            prev_nodes[h - 1] = prev;
+        }
+
+        std::fill(next_nodes.begin(), next_nodes.begin() + node_height, erase_node);
+    }
+
     template<typename... Args>
     std::pair<iterator, bool> internal_insert(Args&&... args) {
         node_ptr new_node = create_node(std::forward<Args>(args)...);
@@ -838,18 +880,18 @@ private:
     std::pair<node_ptr, node_ptr> internal_extract(const_iterator it) {
         if ( it != end() ) {
             key_type key = traits_type::get_key(*it);
-            node_ptr prev = dummy_head;
             __TBB_ASSERT(dummy_head->height() > 0, NULL);
 
             array_type prev_nodes;
             array_type next_nodes;
 
-            fill_prev_next_arrays(prev_nodes, next_nodes, prev, key, my_compare);
+            fill_prev_next_by_ptr(prev_nodes, next_nodes, it, key, my_compare);
 
             node_ptr erase_node = next_nodes[0];
+            __TBB_ASSERT(erase_node != nullptr, NULL);
             node_ptr next_node = erase_node->next(0);
 
-            if (erase_node && !my_compare(key, get_key(erase_node))) {
+            if (!my_compare(key, get_key(erase_node))) {
                 for(size_type level = 0; level < erase_node->height(); ++level) {
                     __TBB_ASSERT(prev_nodes[level]->height() > level, NULL);
                     __TBB_ASSERT(next_nodes[level] == erase_node, NULL);
index 3998c3f..21b35da 100644 (file)
@@ -84,6 +84,11 @@ public:
     flist_iterator( const flist_iterator<Solist, typename Solist::value_type> &other )
         : my_node_ptr(other.my_node_ptr) {}
 
+    flist_iterator& operator=( const flist_iterator<Solist, typename Solist::value_type> &other ) {
+        my_node_ptr = other.my_node_ptr;
+        return *this;
+    }
+
     reference operator*() const { return my_node_ptr->my_element; }
     pointer operator->() const { return &**this; }
 
@@ -147,9 +152,15 @@ public:
     typedef typename Solist::reference reference;
 
     solist_iterator() {}
-    solist_iterator(const solist_iterator<Solist, typename Solist::value_type> &other )
+    solist_iterator( const solist_iterator<Solist, typename Solist::value_type> &other )
         : base_type(other), my_list_ptr(other.my_list_ptr) {}
 
+    solist_iterator& operator=( const solist_iterator<Solist, typename Solist::value_type> &other ) {
+        base_type::my_node_ptr = other.get_node_ptr();
+        my_list_ptr = other.my_list_ptr;
+        return *this;
+    }
+
     reference operator*() const {
         return this->base_type::operator*();
     }
@@ -889,12 +900,18 @@ protected:
             if (allow_multimapping || find(get_key(*where)) == end()) {
                 std::pair<node_type, raw_iterator> extract_result = source.internal_extract(where);
 
+                // Remember the old order key
+                sokey_t old_order_key = extract_result.first.my_node->get_order_key();
+
                 // If the insertion fails, it returns ownership of the node to extract_result.first
                 // extract_result.first remains valid node handle
                 if (!insert(std::move(extract_result.first)).second) {
                     raw_iterator next = extract_result.second;
                     raw_iterator current = next++;
 
+                    // Revert order key to old value
+                    extract_result.first.my_node->init(old_order_key);
+
                     __TBB_ASSERT(extract_result.first.my_node->get_order_key() >= current.get_node_ptr()->get_order_key(),
                                 "Wrong nodes order in source container");
                     __TBB_ASSERT(next==source.my_solist.raw_end() ||
@@ -1394,6 +1411,11 @@ private:
         raw_iterator last = my_solist.raw_end();
         __TBB_ASSERT(previous != last, "Invalid head node");
 
+        if (pnode) {
+            // Set new order_key to node
+            pnode->init(order_key);
+        }
+
         // First node is a dummy node
         for (raw_iterator where = previous;;)
         {
@@ -1408,11 +1430,6 @@ private:
                     // If the value was moved, the known reference to key might be invalid
                     pkey = &get_key(pnode->my_element);
                 }
-                else
-                {
-                    // Set new order_key to node
-                    pnode->init(order_key);
-                }
 
                 // Try to insert 'pnode' between 'previous' and 'where'
                 std::pair<iterator, bool> result = my_solist.try_insert(previous, where, pnode, &new_count);
diff --git a/include/tbb/internal/_deprecated_header_message_guard.h b/include/tbb/internal/_deprecated_header_message_guard.h
new file mode 100644 (file)
index 0000000..a929820
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+    Copyright (c) 2005-2019 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.
+*/
+
+#include "tbb/tbb_config.h"
+
+#if (!defined(TBB_SUPPRESS_DEPRECATED_MESSAGES) || (TBB_SUPPRESS_DEPRECATED_MESSAGES == 0)) && !defined(__TBB_INTERNAL_INCLUDES_DEPRECATION_MESSAGE) && \
+!defined(__TBB_condition_variable_H_include_area) && \
+!defined(__TBB_ppl_H_include_area) && \
+!defined(__TBB_thread_H_include_area) && \
+!defined(__TBB_tuple_H_include_area) && \
+!defined(__TBB_aggregator_H_include_area) && \
+!defined(__TBB_aligned_space_H_include_area) && \
+!defined(__TBB_atomic_H_include_area) && \
+!defined(__TBB_combinable_H_include_area) && \
+!defined(__TBB_concurrent_hash_map_H_include_area) && \
+!defined(__TBB_concurrent_lru_cache_H_include_area) && \
+!defined(__TBB_concurrent_map_H_include_area) && \
+!defined(__TBB_concurrent_priority_queue_H_include_area) && \
+!defined(__TBB_concurrent_queue_H_include_area) && \
+!defined(__TBB_concurrent_set_H_include_area) && \
+!defined(__TBB_concurrent_unordered_map_H_include_area) && \
+!defined(__TBB_concurrent_unordered_set_H_include_area) && \
+!defined(__TBB_concurrent_vector_H_include_area) && \
+!defined(__TBB_critical_section_H_include_area) && \
+!defined(__TBB_enumerable_thread_specific_H_include_area) && \
+!defined(__TBB_flow_graph_opencl_node_H_include_area) && \
+!defined(__TBB_flow_graph_H_include_area) && \
+!defined(__TBB_mutex_H_include_area) && \
+!defined(__TBB_parallel_do_H_include_area) && \
+!defined(__TBB_parallel_for_H_include_area) && \
+!defined(__TBB_parallel_invoke_H_include_area) && \
+!defined(__TBB_parallel_reduce_H_include_area) && \
+!defined(__TBB_parallel_scan_H_include_area) && \
+!defined(__TBB_parallel_sort_H_include_area) && \
+!defined(__TBB_parallel_while_H_include_area) && \
+!defined(__TBB_partitioner_H_include_area) && \
+!defined(__TBB_pipeline_H_include_area) && \
+!defined(__TBB_queuing_mutex_H_include_area) && \
+!defined(__TBB_queuing_rw_mutex_H_include_area) && \
+!defined(__TBB_reader_writer_lock_H_include_area) && \
+!defined(__TBB_recursive_mutex_H_include_area) && \
+!defined(__TBB_runtime_loader_H_include_area) && \
+!defined(__TBB_task_scheduler_init_H_include_area) && \
+!defined(__TBB_spin_mutex_H_include_area) && \
+!defined(__TBB_task_arena_H_include_area) && \
+!defined(__TBB_task_group_H_include_area) && \
+!defined(__TBB_task_scheduler_observer_H_include_area) && \
+!defined(__TBB_task_H_include_area) && \
+!defined(__TBB_tbb_exception_H_include_area) && \
+!defined(__TBB_tbb_profiling_H_include_area) && \
+!defined(__TBB_tbb_thread_H_include_area) && \
+!defined(__TBB_tbb_H_include_area)
+
+#define __TBB_show_deprecated_header_message
+
+#endif
index 57264fd..15c3b92 100644 (file)
@@ -84,8 +84,8 @@ namespace graph_policy_namespace {
     typedef key_matching<tag_value> tag_matching;
 
     // Aliases for Policy combinations
-    typedef interface10::internal::Policy<queueing, lightweight> queueing_lightweight;
-    typedef interface10::internal::Policy<rejecting, lightweight>  rejecting_lightweight;
+    typedef interface11::internal::Policy<queueing, lightweight> queueing_lightweight;
+    typedef interface11::internal::Policy<rejecting, lightweight>  rejecting_lightweight;
 
 } // namespace graph_policy_namespace
 
@@ -358,7 +358,7 @@ protected:
         return result;
     }
 
-    graph& graph_reference() __TBB_override {
+    graph& graph_reference() const __TBB_override {
         return my_node->my_graph;
     }
 
@@ -423,7 +423,7 @@ class decrementer<T, continue_msg, void> : public continue_receiver, tbb::intern
 
 protected:
 
-    graph& graph_reference() __TBB_override {
+    graph& graph_reference() const __TBB_override {
         return my_node->my_graph;
     }
 
index f3081b6..6529771 100644 (file)
@@ -361,11 +361,11 @@ public:
  };  // successor_cache<T>
 
 //! An abstract cache of successors, specialized to continue_msg
-template<>
-class successor_cache< continue_msg > : tbb::internal::no_copy {
+template<typename M>
+class successor_cache< continue_msg, M > : tbb::internal::no_copy {
 protected:
 
-    typedef spin_rw_mutex mutex_type;
+    typedef M mutex_type;
     mutex_type my_mutex;
 
 #if __TBB_PREVIEW_ASYNC_MSG
@@ -391,22 +391,22 @@ public:
     edge_container<successor_type> &built_successors() { return my_built_successors; }
 
     void internal_add_built_successor( successor_type &r) {
-        mutex_type::scoped_lock l(my_mutex, true);
+        typename mutex_type::scoped_lock l(my_mutex, true);
         my_built_successors.add_edge( r );
     }
 
     void internal_delete_built_successor( successor_type &r) {
-        mutex_type::scoped_lock l(my_mutex, true);
+        typename mutex_type::scoped_lock l(my_mutex, true);
         my_built_successors.delete_edge(r);
     }
 
     void copy_successors( successor_list_type &v) {
-        mutex_type::scoped_lock l(my_mutex, false);
+        typename mutex_type::scoped_lock l(my_mutex, false);
         my_built_successors.copy_edges(v);
     }
 
     size_t successor_count() {
-        mutex_type::scoped_lock l(my_mutex,false);
+        typename mutex_type::scoped_lock l(my_mutex,false);
         return my_built_successors.edge_count();
     }
 
@@ -419,7 +419,7 @@ public:
     virtual ~successor_cache() {}
 
     void register_successor( successor_type &r ) {
-        mutex_type::scoped_lock l(my_mutex, true);
+        typename mutex_type::scoped_lock l(my_mutex, true);
         my_successors.push_back( &r );
         if ( my_owner && r.is_continue_receiver() ) {
             r.register_predecessor( *my_owner );
@@ -427,7 +427,7 @@ public:
     }
 
     void remove_successor( successor_type &r ) {
-        mutex_type::scoped_lock l(my_mutex, true);
+        typename mutex_type::scoped_lock l(my_mutex, true);
         for ( successors_type::iterator i = my_successors.begin();
               i != my_successors.end(); ++i ) {
             if ( *i == & r ) {
@@ -442,7 +442,7 @@ public:
     }
 
     bool empty() {
-        mutex_type::scoped_lock l(my_mutex, false);
+        typename mutex_type::scoped_lock l(my_mutex, false);
         return my_successors.empty();
     }
 
index a4b96d1..e2356e2 100644 (file)
@@ -66,6 +66,10 @@ static const node_priority_t no_priority = node_priority_t(0);
 }
 
 namespace interface10 {
+class graph;
+}
+
+namespace interface11 {
 
 using tbb::flow::internal::SUCCESSFULLY_ENQUEUED;
 
@@ -81,13 +85,11 @@ struct graph_task : public task {
 typedef task graph_task;
 #endif /* __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES */
 
-
-class graph;
 class graph_node;
 
 template <typename GraphContainerType, typename GraphNodeType>
 class graph_iterator {
-    friend class graph;
+    friend class tbb::flow::interface10::graph;
     friend class graph_node;
 public:
     typedef size_t size_type;
@@ -161,13 +163,13 @@ enum reset_flags {
 
 namespace internal {
 
-void activate_graph(graph& g);
-void deactivate_graph(graph& g);
-bool is_graph_active(graph& g);
-tbb::task& prioritize_task(graph& g, tbb::task& arena_task);
-void spawn_in_graph_arena(graph& g, tbb::task& arena_task);
-void enqueue_in_graph_arena(graph &g, tbb::task& arena_task);
-void add_task_to_graph_reset_list(graph& g, tbb::task *tp);
+void activate_graph(tbb::flow::interface10::graph& g);
+void deactivate_graph(tbb::flow::interface10::graph& g);
+bool is_graph_active(tbb::flow::interface10::graph& g);
+tbb::task& prioritize_task(tbb::flow::interface10::graph& g, tbb::task& arena_task);
+void spawn_in_graph_arena(tbb::flow::interface10::graph& g, tbb::task& arena_task);
+void enqueue_in_graph_arena(tbb::flow::interface10::graph &g, tbb::task& arena_task);
+void add_task_to_graph_reset_list(tbb::flow::interface10::graph& g, tbb::task *tp);
 
 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
 struct graph_task_comparator {
@@ -202,18 +204,20 @@ private:
 
 }
 
+} // namespace interfaceX
+namespace interface10 {
 //! The graph class
 /** This class serves as a handle to the graph */
 class graph : tbb::internal::no_copy, public tbb::flow::graph_proxy {
-    friend class graph_node;
+    friend class tbb::flow::interface11::graph_node;
 
     template< typename Body >
-    class run_task : public graph_task {
+    class run_task : public tbb::flow::interface11::graph_task {
     public:
         run_task(Body& body
 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
-                 , node_priority_t node_priority = no_priority
-        ) : graph_task(node_priority),
+                 , tbb::flow::interface11::node_priority_t node_priority = tbb::flow::interface11::no_priority
+        ) : tbb::flow::interface11::graph_task(node_priority),
 #else
         ) :
 #endif
@@ -227,12 +231,12 @@ class graph : tbb::internal::no_copy, public tbb::flow::graph_proxy {
     };
 
     template< typename Receiver, typename Body >
-    class run_and_put_task : public graph_task {
+    class run_and_put_task : public tbb::flow::interface11::graph_task {
     public:
         run_and_put_task(Receiver &r, Body& body) : my_receiver(r), my_body(body) {}
         tbb::task *execute() __TBB_override {
             tbb::task *res = my_receiver.try_put_task(my_body());
-            if (res == SUCCESSFULLY_ENQUEUED) res = NULL;
+            if (res == tbb::flow::interface11::SUCCESSFULLY_ENQUEUED) res = NULL;
             return res;
         }
     private:
@@ -311,7 +315,7 @@ public:
     that need to block a wait_for_all() on the graph.  For example a one-off source. */
     template< typename Receiver, typename Body >
     void run(Receiver &r, Body body) {
-        if (internal::is_graph_active(*this)) {
+        if (tbb::flow::interface11::internal::is_graph_active(*this)) {
             task* rtask = new (task::allocate_additional_child_of(*root_task()))
                 run_and_put_task< Receiver, Body >(r, body);
             my_task_arena->execute(spawn_functor(*rtask));
@@ -323,7 +327,7 @@ public:
     that need to block a wait_for_all() on the graph. For example a one-off source. */
     template< typename Body >
     void run(Body body) {
-        if (internal::is_graph_active(*this)) {
+        if (tbb::flow::interface11::internal::is_graph_active(*this)) {
             task* rtask = new (task::allocate_additional_child_of(*root_task())) run_task< Body >(body);
             my_task_arena->execute(spawn_functor(*rtask));
         }
@@ -339,7 +343,9 @@ public:
             try {
 #endif
                 my_task_arena->execute(wait_functor(my_root_task));
+#if __TBB_TASK_GROUP_CONTEXT
                 cancelled = my_context->is_group_execution_cancelled();
+#endif
 #if TBB_USE_EXCEPTIONS
             }
             catch (...) {
@@ -350,13 +356,17 @@ public:
                 throw;
             }
 #endif
+#if __TBB_TASK_GROUP_CONTEXT
             // TODO: the "if" condition below is just a work-around to support the concurrent wait
             // mode. The cancellation and exception mechanisms are still broken in this mode.
             // Consider using task group not to re-implement the same functionality.
             if (!(my_context->traits() & tbb::task_group_context::concurrent_wait)) {
                 my_context->reset();  // consistent with behavior in catch()
+#endif
                 my_root_task->set_ref_count(1);
+#if __TBB_TASK_GROUP_CONTEXT
             }
+#endif
         }
     }
 
@@ -367,11 +377,11 @@ public:
 
     // ITERATORS
     template<typename C, typename N>
-    friend class graph_iterator;
+    friend class tbb::flow::interface11::graph_iterator;
 
     // Graph iterator typedefs
-    typedef graph_iterator<graph, graph_node> iterator;
-    typedef graph_iterator<const graph, const graph_node> const_iterator;
+    typedef tbb::flow::interface11::graph_iterator<graph, tbb::flow::interface11::graph_node> iterator;
+    typedef tbb::flow::interface11::graph_iterator<const graph, const tbb::flow::interface11::graph_node> const_iterator;
 
     // Graph iterator constructors
     //! start iterator
@@ -392,46 +402,64 @@ public:
     bool exception_thrown() { return caught_exception; }
 
     // thread-unsafe state reset.
-    void reset(reset_flags f = rf_reset_protocol);
+    void reset(tbb::flow::interface11::reset_flags f = tbb::flow::interface11::rf_reset_protocol);
 
 private:
     tbb::task *my_root_task;
+#if __TBB_TASK_GROUP_CONTEXT
     tbb::task_group_context *my_context;
+#endif
     bool own_context;
     bool cancelled;
     bool caught_exception;
     bool my_is_active;
     task_list_type my_reset_task_list;
 
-    graph_node *my_nodes, *my_nodes_last;
+    tbb::flow::interface11::graph_node *my_nodes, *my_nodes_last;
 
     tbb::spin_mutex nodelist_mutex;
-    void register_node(graph_node *n);
-    void remove_node(graph_node *n);
+    void register_node(tbb::flow::interface11::graph_node *n);
+    void remove_node(tbb::flow::interface11::graph_node *n);
 
     tbb::task_arena* my_task_arena;
 
 #if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
-    internal::graph_task_priority_queue_t my_priority_queue;
+    tbb::flow::interface11::internal::graph_task_priority_queue_t my_priority_queue;
 #endif
 
-    friend void internal::activate_graph(graph& g);
-    friend void internal::deactivate_graph(graph& g);
-    friend bool internal::is_graph_active(graph& g);
-    friend tbb::task& internal::prioritize_task(graph& g, tbb::task& arena_task);
-    friend void internal::spawn_in_graph_arena(graph& g, tbb::task& arena_task);
-    friend void internal::enqueue_in_graph_arena(graph &g, tbb::task& arena_task);
-    friend void internal::add_task_to_graph_reset_list(graph& g, tbb::task *tp);
+    friend void tbb::flow::interface11::internal::activate_graph(graph& g);
+    friend void tbb::flow::interface11::internal::deactivate_graph(graph& g);
+    friend bool tbb::flow::interface11::internal::is_graph_active(graph& g);
+    friend tbb::task& tbb::flow::interface11::internal::prioritize_task(graph& g, tbb::task& arena_task);
+    friend void tbb::flow::interface11::internal::spawn_in_graph_arena(graph& g, tbb::task& arena_task);
+    friend void tbb::flow::interface11::internal::enqueue_in_graph_arena(graph &g, tbb::task& arena_task);
+    friend void tbb::flow::interface11::internal::add_task_to_graph_reset_list(graph& g, tbb::task *tp);
 
     friend class tbb::interface7::internal::task_arena_base;
 
 };  // class graph
+} // namespace interface10
+
+namespace interface11 {
+
+using tbb::flow::interface10::graph;
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+namespace internal{
+class get_graph_helper;
+}
+#endif
 
 //! The base of all graph nodes.
 class graph_node : tbb::internal::no_copy {
     friend class graph;
     template<typename C, typename N>
     friend class graph_iterator;
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    friend class internal::get_graph_helper;
+#endif
+
 protected:
     graph& my_graph;
     graph_node *next, *prev;
@@ -512,7 +540,7 @@ inline void add_task_to_graph_reset_list(graph& g, tbb::task *tp) {
 
 } // namespace internal
 
-} // namespace interface10
+} // namespace interfaceX
 } // namespace flow
 } // namespace tbb
 
index 332467d..dc674f6 100644 (file)
@@ -133,7 +133,7 @@ namespace internal {
             return my_try_put_task(v, my_indexer_ptr);
         }
 
-        graph& graph_reference() __TBB_override {
+        graph& graph_reference() const __TBB_override {
             return *my_graph;
         }
 
index 4ccaef9..b879b85 100644 (file)
@@ -319,7 +319,7 @@ namespace internal {
             return NULL;
         }
 
-        graph& graph_reference() __TBB_override {
+        graph& graph_reference() const __TBB_override {
             return my_join->graph_ref;
         }
 
@@ -416,6 +416,10 @@ namespace internal {
         }
 
     private:
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+        friend class get_graph_helper;
+#endif
+
         forwarding_base *my_join;
         reservable_predecessor_cache< T, null_mutex > my_predecessors;
         bool reserved;
@@ -542,7 +546,7 @@ namespace internal {
             return op_data.bypass_t;
         }
 
-        graph& graph_reference() __TBB_override {
+        graph& graph_reference() const __TBB_override {
             return my_join->graph_ref;
         }
 
@@ -622,6 +626,10 @@ namespace internal {
         }
 
     private:
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+        friend class get_graph_helper;
+#endif
+
         forwarding_base *my_join;
 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
         edge_container<predecessor_type> my_built_predecessors;
@@ -760,7 +768,7 @@ namespace internal {
             return rtask;
         }
 
-        graph& graph_reference() __TBB_override {
+        graph& graph_reference() const __TBB_override {
             return my_join->graph_ref;
         }
 
index 215777f..e6277b2 100644 (file)
@@ -191,7 +191,7 @@ namespace internal {
             __TBB_ASSERT(!(f & rf_clear_edges) || my_predecessors.empty(), "function_input_base reset failed");
         }
 
-        graph& graph_reference() __TBB_override {
+        graph& graph_reference() const __TBB_override {
             return my_graph_ref;
         }
 
@@ -559,6 +559,79 @@ namespace internal {
     };
 #endif
 
+    template <typename OutputTuple>
+    struct init_output_ports {
+#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
+        template <typename... Args>
+        static OutputTuple call(graph& g, const tbb::flow::tuple<Args...>&) {
+            return OutputTuple(Args(g)...);
+        }
+#else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
+        template <typename T1>
+        static OutputTuple call(graph& g, const tbb::flow::tuple<T1>&) {
+            return OutputTuple(T1(g));
+        }
+
+        template <typename T1, typename T2>
+        static OutputTuple call(graph& g, const tbb::flow::tuple<T1, T2>&) {
+            return OutputTuple(T1(g), T2(g));
+        }
+
+        template <typename T1, typename T2, typename T3>
+        static OutputTuple call(graph& g, const tbb::flow::tuple<T1, T2, T3>&) {
+            return OutputTuple(T1(g), T2(g), T3(g));
+        }
+
+        template <typename T1, typename T2, typename T3, typename T4>
+        static OutputTuple call(graph& g, const tbb::flow::tuple<T1, T2, T3, T4>&) {
+            return OutputTuple(T1(g), T2(g), T3(g), T4(g));
+        }
+
+        template <typename T1, typename T2, typename T3, typename T4, typename T5>
+        static OutputTuple call(graph& g, const tbb::flow::tuple<T1, T2, T3, T4, T5>&) {
+            return OutputTuple(T1(g), T2(g), T3(g), T4(g), T5(g));
+        }
+#if __TBB_VARIADIC_MAX >= 6
+        template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+        static OutputTuple call(graph& g, const tbb::flow::tuple<T1, T2, T3, T4, T5, T6>&) {
+            return OutputTuple(T1(g), T2(g), T3(g), T4(g), T5(g), T6(g));
+        }
+#endif
+#if __TBB_VARIADIC_MAX >= 7
+        template <typename T1, typename T2, typename T3, typename T4,
+                  typename T5, typename T6, typename T7>
+        static OutputTuple call(graph& g,
+                                const tbb::flow::tuple<T1, T2, T3, T4, T5, T6, T7>&) {
+            return OutputTuple(T1(g), T2(g), T3(g), T4(g), T5(g), T6(g), T7(g));
+        }
+#endif
+#if __TBB_VARIADIC_MAX >= 8
+        template <typename T1, typename T2, typename T3, typename T4,
+                  typename T5, typename T6, typename T7, typename T8>
+        static OutputTuple call(graph& g,
+                                const tbb::flow::tuple<T1, T2, T3, T4, T5, T6, T7, T8>&) {
+            return OutputTuple(T1(g), T2(g), T3(g), T4(g), T5(g), T6(g), T7(g), T8(g));
+        }
+#endif
+#if __TBB_VARIADIC_MAX >= 9
+        template <typename T1, typename T2, typename T3, typename T4,
+                  typename T5, typename T6, typename T7, typename T8, typename T9>
+        static OutputTuple call(graph& g,
+                                const tbb::flow::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>&) {
+            return OutputTuple(T1(g), T2(g), T3(g), T4(g), T5(g), T6(g), T7(g), T8(g), T9(g));
+        }
+#endif
+#if __TBB_VARIADIC_MAX >= 9
+        template <typename T1, typename T2, typename T3, typename T4, typename T5,
+                  typename T6, typename T7, typename T8, typename T9, typename T10>
+        static OutputTuple call(graph& g,
+                                const tbb::flow::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>&) {
+            return OutputTuple(T1(g), T2(g), T3(g), T4(g), T5(g), T6(g), T7(g), T8(g), T9(g), T10(g));
+        }
+#endif
+#endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
+    }; // struct init_output_ports
+
     //! Implements methods for a function node that takes a type Input as input
     //  and has a tuple of output ports specified.
     template< typename Input, typename OutputPortSet, typename Policy, typename A>
@@ -578,14 +651,16 @@ namespace internal {
                             __TBB_FLOW_GRAPH_PRIORITY_ARG1(Body& body, node_priority_t priority)
         ) : base_type(g, __TBB_FLOW_GRAPH_PRIORITY_ARG1(max_concurrency, priority))
           , my_body( new internal::multifunction_body_leaf<input_type, output_ports_type, Body>(body) )
-          , my_init_body( new internal::multifunction_body_leaf<input_type, output_ports_type, Body>(body) ) {
+          , my_init_body( new internal::multifunction_body_leaf<input_type, output_ports_type, Body>(body) )
+          , my_output_ports(init_output_ports<output_ports_type>::call(g, my_output_ports)){
         }
 
         //! Copy constructor
         multifunction_input( const multifunction_input& src ) :
                 base_type(src),
                 my_body( src.my_init_body->clone() ),
-                my_init_body(src.my_init_body->clone() ) {
+                my_init_body(src.my_init_body->clone() ),
+                my_output_ports( init_output_ports<output_ports_type>::call(src.my_graph_ref, my_output_ports) ) {
         }
 
         ~multifunction_input() {
@@ -769,7 +844,7 @@ namespace internal {
             }
         }
 
-        graph& graph_reference() __TBB_override {
+        graph& graph_reference() const __TBB_override {
             return my_graph_ref;
         }
     };  // continue_input
@@ -788,8 +863,8 @@ namespace internal {
         typedef typename sender<output_type>::successor_list_type successor_list_type;
 #endif
 
-        function_output() { my_successors.set_owner(this); }
-        function_output(const function_output & /*other*/) : sender<output_type>() {
+        function_output( graph& g) : my_graph_ref(g) { my_successors.set_owner(this); }
+        function_output(const function_output & other) : sender<output_type>(), my_graph_ref(other.my_graph_ref) {
             my_successors.set_owner(this);
         }
 
@@ -839,9 +914,11 @@ namespace internal {
         }
 
         broadcast_cache_type &successors() { return my_successors; }
+
+        graph& graph_reference() const { return my_graph_ref; }
     protected:
         broadcast_cache_type my_successors;
-
+        graph& my_graph_ref;
     };  // function_output
 
     template< typename Output >
@@ -851,8 +928,8 @@ namespace internal {
         typedef function_output<output_type> base_type;
         using base_type::my_successors;
 
-        multifunction_output() : base_type() {my_successors.set_owner(this);}
-        multifunction_output( const multifunction_output &/*other*/) : base_type() { my_successors.set_owner(this); }
+        multifunction_output(graph& g) : base_type(g) {my_successors.set_owner(this);}
+        multifunction_output( const multifunction_output& other) : base_type(other.my_graph_ref) { my_successors.set_owner(this); }
 
         bool try_put(const output_type &i) {
             task *res = try_put_task(i);
@@ -863,6 +940,8 @@ namespace internal {
             return true;
         }
 
+        using base_type::graph_reference;
+
     protected:
 
         task* try_put_task(const output_type &i) {
diff --git a/include/tbb/internal/_flow_graph_node_set_impl.h b/include/tbb/internal/_flow_graph_node_set_impl.h
new file mode 100644 (file)
index 0000000..6ca4544
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+    Copyright (c) 2019 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.
+*/
+
+#ifndef __TBB_flow_graph_node_set_impl_H
+#define __TBB_flow_graph_node_set_impl_H
+
+#ifndef __TBB_flow_graph_H
+#error Do not #include this internal file directly; use public TBB headers instead.
+#endif
+
+// Included in namespace tbb::flow::interfaceX (in flow_graph.h)
+
+namespace internal {
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+// Visual Studio 2019 reports an error while calling predecessor_selector::get and successor_selector::get
+// Seems like the well-formed expression in trailing decltype is treated as ill-formed
+// TODO: investigate problems with decltype in trailing return types or find the cross-platform solution
+#define __TBB_MSVC_DISABLE_TRAILING_DECLTYPE (_MSC_VER >= 1900)
+
+namespace order {
+struct undefined {};
+struct following {};
+struct preceding {};
+}
+
+class get_graph_helper {
+public:
+    // TODO: consider making graph_reference() public and consistent interface to get a reference to the graph
+    // and remove get_graph_helper
+    template <typename T>
+    static graph& get(const T& object) {
+        return get_impl(object, std::is_base_of<graph_node, T>());
+    }
+
+private:
+    // Get graph from the object of type derived from graph_node
+    template <typename T>
+    static graph& get_impl(const T& object, std::true_type) {
+        return static_cast<const graph_node*>(&object)->my_graph;
+    }
+
+    template <typename T>
+    static graph& get_impl(const T& object, std::false_type) {
+        return object.graph_reference();
+    }
+};
+
+template<typename Order, typename... Nodes>
+struct node_set {
+    typedef Order order_type;
+
+    tbb::flow::tuple<Nodes&...> nodes;
+    node_set(Nodes&... ns) : nodes(ns...) {}
+
+    template <typename... Nodes2>
+    node_set(const node_set<order::undefined, Nodes2...>& set) : nodes(set.nodes) {}
+
+    graph& graph_reference() const {
+        return get_graph_helper::get(std::get<0>(nodes));
+    }
+};
+
+namespace alias_helpers {
+template <typename T> using output_type = typename T::output_type;
+template <typename T> using output_ports_type = typename T::output_ports_type;
+template <typename T> using input_type = typename T::input_type;
+template <typename T> using input_ports_type = typename T::input_ports_type;
+} // namespace alias_helpers
+
+template <typename T>
+using has_output_type = tbb::internal::supports<T, alias_helpers::output_type>;
+
+template <typename T>
+using has_input_type = tbb::internal::supports<T, alias_helpers::input_type>;
+
+template <typename T>
+using has_input_ports_type = tbb::internal::supports<T, alias_helpers::input_ports_type>;
+
+template <typename T>
+using has_output_ports_type = tbb::internal::supports<T, alias_helpers::output_ports_type>;
+
+template<typename T>
+struct is_sender : std::is_base_of<sender<typename T::output_type>, T> {};
+
+template<typename T>
+struct is_receiver : std::is_base_of<receiver<typename T::input_type>, T> {};
+
+template <typename Node>
+struct is_async_node : std::false_type {};
+
+template <typename... Args>
+struct is_async_node<tbb::flow::interface11::async_node<Args...>> : std::true_type {};
+
+template<typename FirstPredecessor, typename... Predecessors>
+node_set<order::following, FirstPredecessor, Predecessors...>
+follows(FirstPredecessor& first_predecessor, Predecessors&... predecessors) {
+    __TBB_STATIC_ASSERT((tbb::internal::conjunction<has_output_type<FirstPredecessor>,
+                                                   has_output_type<Predecessors>...>::value),
+                        "Not all node's predecessors has output_type typedef");
+    __TBB_STATIC_ASSERT((tbb::internal::conjunction<is_sender<FirstPredecessor>, is_sender<Predecessors>...>::value),
+                        "Not all node's predecessors are senders");
+    return node_set<order::following, FirstPredecessor, Predecessors...>(first_predecessor, predecessors...);
+}
+
+template<typename... Predecessors>
+node_set<order::following, Predecessors...>
+follows(node_set<order::undefined, Predecessors...>& predecessors_set) {
+    __TBB_STATIC_ASSERT((tbb::internal::conjunction<has_output_type<Predecessors>...>::value),
+                        "Not all nodes in the set has output_type typedef");
+    __TBB_STATIC_ASSERT((tbb::internal::conjunction<is_sender<Predecessors>...>::value),
+                        "Not all nodes in the set are senders");
+    return node_set<order::following, Predecessors...>(predecessors_set);
+}
+
+template<typename FirstSuccessor, typename... Successors>
+node_set<order::preceding, FirstSuccessor, Successors...>
+precedes(FirstSuccessor& first_successor, Successors&... successors) {
+    __TBB_STATIC_ASSERT((tbb::internal::conjunction<has_input_type<FirstSuccessor>,
+                                                    has_input_type<Successors>...>::value),
+                        "Not all node's successors has input_type typedef");
+    __TBB_STATIC_ASSERT((tbb::internal::conjunction<is_receiver<FirstSuccessor>, is_receiver<Successors>...>::value),
+                        "Not all node's successors are receivers");
+    return node_set<order::preceding, FirstSuccessor, Successors...>(first_successor, successors...);
+}
+
+template<typename... Successors>
+node_set<order::preceding, Successors...>
+precedes(node_set<order::undefined, Successors...>& successors_set) {
+    __TBB_STATIC_ASSERT((tbb::internal::conjunction<has_input_type<Successors>...>::value),
+                        "Not all nodes in the set has input_type typedef");
+    __TBB_STATIC_ASSERT((tbb::internal::conjunction<is_receiver<Successors>...>::value),
+                        "Not all nodes in the set are receivers");
+    return node_set<order::preceding, Successors...>(successors_set);
+}
+
+template <typename Node, typename... Nodes>
+node_set<order::undefined, Node, Nodes...>
+make_node_set(Node& first_node, Nodes&... nodes) {
+    return node_set<order::undefined, Node, Nodes...>(first_node, nodes...);
+}
+
+template<size_t I>
+class successor_selector {
+    template <typename NodeType>
+    static auto get_impl(NodeType& node, std::true_type) -> decltype(input_port<I>(node)) {
+        return input_port<I>(node);
+    }
+
+    template <typename NodeType>
+    static NodeType& get_impl(NodeType& node, std::false_type) { return node; }
+
+public:
+    template <typename NodeType>
+#if __TBB_MSVC_DISABLE_TRAILING_DECLTYPE
+    static auto& get(NodeType& node)
+#else
+    static auto get(NodeType& node) -> decltype(get_impl(node, has_input_ports_type<NodeType>()))
+#endif
+       {
+        return get_impl(node, has_input_ports_type<NodeType>());
+    }
+};
+
+template<size_t I>
+class predecessor_selector {
+    template <typename NodeType>
+    static auto internal_get(NodeType& node, std::true_type) -> decltype(output_port<I>(node)) {
+        return output_port<I>(node);
+    }
+
+    template <typename NodeType>
+    static NodeType& internal_get(NodeType& node, std::false_type) { return node;}
+
+    template <typename NodeType>
+#if __TBB_MSVC_DISABLE_TRAILING_DECLTYPE
+    static auto& get_impl(NodeType& node, std::false_type)
+#else
+    static auto get_impl(NodeType& node, std::false_type) -> decltype(internal_get(node, has_output_ports_type<NodeType>()))
+#endif
+       {
+        return internal_get(node, has_output_ports_type<NodeType>());
+    }
+
+    template <typename AsyncNode>
+    static AsyncNode& get_impl(AsyncNode& node, std::true_type) { return node; }
+
+public:
+    template <typename NodeType>
+#if __TBB_MSVC_DISABLE_TRAILING_DECLTYPE
+    static auto& get(NodeType& node)
+#else
+    static auto get(NodeType& node) -> decltype(get_impl(node, is_async_node<NodeType>()))
+#endif
+       {
+        return get_impl(node, is_async_node<NodeType>());
+    }
+};
+
+template<size_t I>
+class make_edges_helper {
+public:
+    template<typename PredecessorsTuple, typename NodeType>
+    static void connect_predecessors(PredecessorsTuple& predecessors, NodeType& node) {
+        make_edge(std::get<I>(predecessors), successor_selector<I>::get(node));
+        make_edges_helper<I - 1>::connect_predecessors(predecessors, node);
+    }
+
+    template<typename SuccessorsTuple, typename NodeType>
+    static void connect_successors(NodeType& node, SuccessorsTuple& successors) {
+        make_edge(predecessor_selector<I>::get(node), std::get<I>(successors));
+        make_edges_helper<I - 1>::connect_successors(node, successors);
+    }
+};
+
+template<>
+struct make_edges_helper<0> {
+    template<typename PredecessorsTuple, typename NodeType>
+    static void connect_predecessors(PredecessorsTuple& predecessors, NodeType& node) {
+        make_edge(std::get<0>(predecessors), successor_selector<0>::get(node));
+    }
+
+    template<typename SuccessorsTuple, typename NodeType>
+    static void connect_successors(NodeType& node, SuccessorsTuple& successors) {
+        make_edge(predecessor_selector<0>::get(node), std::get<0>(successors));
+    }
+};
+
+// TODO: consider adding an overload for making edges between node sets
+template<typename NodeType, typename OrderFlagType, typename... Args>
+void make_edges(const node_set<OrderFlagType, Args...>& s, NodeType& node) {
+    const std::size_t SetSize = tbb::flow::tuple_size<decltype(s.nodes)>::value;
+    make_edges_helper<SetSize - 1>::connect_predecessors(s.nodes, node);
+}
+
+template <typename NodeType, typename OrderFlagType, typename... Args>
+void make_edges(NodeType& node, const node_set<OrderFlagType, Args...>& s) {
+    const std::size_t SetSize = tbb::flow::tuple_size<decltype(s.nodes)>::value;
+    make_edges_helper<SetSize - 1>::connect_successors(node, s.nodes);
+}
+
+template <typename NodeType, typename... Nodes>
+void make_edges_in_order(const node_set<order::following, Nodes...>& ns, NodeType& node) {
+    make_edges(ns, node);
+}
+
+template <typename NodeType, typename... Nodes>
+void make_edges_in_order(const node_set<order::preceding, Nodes...>& ns, NodeType& node) {
+    make_edges(node, ns);
+}
+
+#endif // __TBB_CPP11_PRESENT
+
+} // namespace internal
+
+#endif // __TBB_flow_graph_node_set_impl_H
diff --git a/include/tbb/internal/_flow_graph_nodes_deduction.h b/include/tbb/internal/_flow_graph_nodes_deduction.h
new file mode 100644 (file)
index 0000000..c12553f
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+    Copyright (c) 2005-2019 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.
+*/
+
+#ifndef __TBB_flow_graph_nodes_deduction_H
+#define __TBB_flow_graph_nodes_deduction_H
+
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+
+namespace tbb {
+namespace flow {
+namespace interface11 {
+
+template <typename Input, typename Output>
+struct declare_body_types {
+    using input_type = Input;
+    using output_type = Output;
+};
+
+template <typename T> struct body_types;
+
+template <typename T, typename Input, typename Output>
+struct body_types<Output (T::*)(const Input&) const> : declare_body_types<Input, Output> {};
+
+template <typename T, typename Input, typename Output>
+struct body_types<Output (T::*)(const Input&)> : declare_body_types<Input, Output> {};
+
+template <typename T, typename Input, typename Output>
+struct body_types<Output (T::*)(Input&) const> : declare_body_types<Input, Output> {};
+
+template <typename T, typename Input, typename Output>
+struct body_types<Output (T::*)(Input&)> : declare_body_types<Input, Output> {};
+
+template <typename Input, typename Output>
+struct body_types<Output (*)(Input&)> : declare_body_types<Input, Output> {};
+
+template <typename Input, typename Output>
+struct body_types<Output (*)(const Input&)> : declare_body_types<Input, Output> {};
+
+template <typename Body>
+using input_t = typename body_types<Body>::input_type;
+
+template <typename Body>
+using output_t = typename body_types<Body>::output_type;
+
+template <typename T, typename Input, typename Output>
+auto decide_on_operator_overload(Output (T::*name)(const Input&) const)->decltype(name);
+
+template <typename T, typename Input, typename Output>
+auto decide_on_operator_overload(Output (T::*name)(const Input&))->decltype(name);
+
+template <typename T, typename Input, typename Output>
+auto decide_on_operator_overload(Output (T::*name)(Input&) const)->decltype(name);
+
+template <typename T, typename Input, typename Output>
+auto decide_on_operator_overload(Output (T::*name)(Input&))->decltype(name);
+
+template <typename Input, typename Output>
+auto decide_on_operator_overload(Output (*name)(const Input&))->decltype(name);
+
+template <typename Input, typename Output>
+auto decide_on_operator_overload(Output (*name)(Input&))->decltype(name);
+
+template <typename Body>
+decltype(decide_on_operator_overload(&Body::operator())) decide_on_callable_type(int);
+
+template <typename Body>
+decltype(decide_on_operator_overload(std::declval<Body>())) decide_on_callable_type(...);
+
+// Deduction guides for Flow Graph nodes
+template <typename GraphOrSet, typename Body>
+source_node(GraphOrSet&&, Body, bool = true)
+->source_node<input_t<decltype(decide_on_callable_type<Body>(0))>>;
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
+template <typename NodeSet>
+struct decide_on_set;
+
+template <typename Node, typename... Nodes>
+struct decide_on_set<node_set<internal::order::following, Node, Nodes...>> {
+    using type = typename Node::output_type;
+};
+
+template <typename Node, typename... Nodes>
+struct decide_on_set<node_set<internal::order::preceding, Node, Nodes...>> {
+    using type = typename Node::input_type;
+};
+
+template <typename NodeSet>
+using decide_on_set_t = typename decide_on_set<std::decay_t<NodeSet>>::type;
+
+template <typename NodeSet>
+broadcast_node(const NodeSet&)
+->broadcast_node<decide_on_set_t<NodeSet>>;
+
+template <typename NodeSet>
+buffer_node(const NodeSet&)
+->buffer_node<decide_on_set_t<NodeSet>>;
+
+template <typename NodeSet>
+queue_node(const NodeSet&)
+->queue_node<decide_on_set_t<NodeSet>>;
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
+template <typename GraphOrProxy, typename Sequencer>
+sequencer_node(GraphOrProxy&&, Sequencer)
+->sequencer_node<input_t<decltype(decide_on_callable_type<Sequencer>(0))>>;
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+template <typename NodeSet, typename Compare>
+priority_queue_node(const NodeSet&, const Compare&)
+->priority_queue_node<decide_on_set_t<NodeSet>, Compare>;
+
+template <typename NodeSet>
+priority_queue_node(const NodeSet&)
+->priority_queue_node<decide_on_set_t<NodeSet>, std::less<decide_on_set_t<NodeSet>>>;
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
+template <typename Key>
+struct join_key {
+    using type = Key;
+};
+
+template <typename T>
+struct join_key<const T&> {
+    using type = T&;
+};
+
+template <typename Key>
+using join_key_t = typename join_key<Key>::type;
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+template <typename Policy, typename... Predecessors>
+join_node(const node_set<internal::order::following, Predecessors...>&, Policy)
+->join_node<std::tuple<typename Predecessors::output_type...>,
+            Policy>;
+
+template <typename Policy, typename Successor, typename... Successors>
+join_node(const node_set<internal::order::preceding, Successor, Successors...>&, Policy)
+->join_node<typename Successor::input_type, Policy>;
+
+template <typename... Predecessors>
+join_node(const node_set<internal::order::following, Predecessors...>)
+->join_node<std::tuple<typename Predecessors::output_type...>,
+            queueing>;
+
+template <typename Successor, typename... Successors>
+join_node(const node_set<internal::order::preceding, Successor, Successors...>)
+->join_node<typename Successor::input_type, queueing>;
+#endif
+
+template <typename GraphOrProxy, typename Body, typename... Bodies>
+join_node(GraphOrProxy&&, Body, Bodies...)
+->join_node<std::tuple<input_t<decltype(decide_on_callable_type<Body>(0))>,
+                       input_t<decltype(decide_on_callable_type<Bodies>(0))>...>,
+            key_matching<join_key_t<output_t<decltype(decide_on_callable_type<Body>(0))>>>>;
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+template <typename... Predecessors>
+indexer_node(const node_set<internal::order::following, Predecessors...>&)
+->indexer_node<typename Predecessors::output_type...>;
+#endif
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+template <typename NodeSet>
+limiter_node(const NodeSet&, size_t)
+->limiter_node<decide_on_set_t<NodeSet>>;
+
+template <typename Predecessor, typename... Predecessors>
+split_node(const node_set<internal::order::following, Predecessor, Predecessors...>&)
+->split_node<typename Predecessor::output_type>;
+
+template <typename... Successors>
+split_node(const node_set<internal::order::preceding, Successors...>&)
+->split_node<std::tuple<typename Successors::input_type...>>;
+
+#endif
+
+template <typename GraphOrSet, typename Body, typename Policy>
+function_node(GraphOrSet&&,
+              size_t, Body,
+            __TBB_FLOW_GRAPH_PRIORITY_ARG1(Policy, node_priority_t = tbb::flow::internal::no_priority))
+->function_node<input_t<decltype(decide_on_callable_type<Body>(0))>,
+                output_t<decltype(decide_on_callable_type<Body>(0))>,
+                Policy>;
+
+template <typename GraphOrSet, typename Body>
+function_node(GraphOrSet&&, size_t,
+              __TBB_FLOW_GRAPH_PRIORITY_ARG1(Body, node_priority_t = tbb::flow::internal::no_priority))
+->function_node<input_t<decltype(decide_on_callable_type<Body>(0))>,
+                output_t<decltype(decide_on_callable_type<Body>(0))>,
+                queueing>;
+
+template <typename Output>
+struct continue_output {
+    using type = Output;
+};
+
+template <>
+struct continue_output<void> {
+    using type = continue_msg;
+};
+
+template <typename T>
+using continue_output_t = typename continue_output<T>::type;
+
+template <typename GraphOrSet, typename Body, typename Policy>
+continue_node(GraphOrSet&&, Body,
+              __TBB_FLOW_GRAPH_PRIORITY_ARG1(Policy, node_priority_t = tbb::flow::internal::no_priority))
+->continue_node<continue_output_t<std::invoke_result_t<Body, continue_msg>>,
+                Policy>;
+
+template <typename GraphOrSet, typename Body, typename Policy>
+continue_node(GraphOrSet&&,
+              int, Body,
+              __TBB_FLOW_GRAPH_PRIORITY_ARG1(Policy, node_priority_t = tbb::flow::internal::no_priority))
+->continue_node<continue_output_t<std::invoke_result_t<Body, continue_msg>>,
+                Policy>;
+
+template <typename GraphOrSet, typename Body>
+continue_node(GraphOrSet&&,
+              __TBB_FLOW_GRAPH_PRIORITY_ARG1(Body, node_priority_t = tbb::flow::internal::no_priority))
+->continue_node<continue_output_t<std::invoke_result_t<Body, continue_msg>>,
+                internal::Policy<void>>;
+
+template <typename GraphOrSet, typename Body>
+continue_node(GraphOrSet&&, int,
+              __TBB_FLOW_GRAPH_PRIORITY_ARG1(Body, node_priority_t = tbb::flow::internal::no_priority))
+->continue_node<continue_output_t<std::invoke_result_t<Body, continue_msg>>,
+                internal::Policy<void>>;
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
+template <typename NodeSet>
+overwrite_node(const NodeSet&)
+->overwrite_node<decide_on_set_t<NodeSet>>;
+
+template <typename NodeSet>
+write_once_node(const NodeSet&)
+->write_once_node<decide_on_set_t<NodeSet>>;
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+} // namespace interfaceX
+} // namespace flow
+} // namespace tbb
+
+#endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+#endif // __TBB_flow_graph_nodes_deduction_H
index 2a1d43e..4fb19c7 100644 (file)
@@ -462,6 +462,7 @@ private:
         device_selector_base *my_device_selector;
     };
 
+    // TODO: investigate why copy-construction is disallowed
     class args_storage_base : tbb::internal::no_copy {
     public:
         typedef typename kernel_multifunction_node::output_ports_type output_ports_type;
@@ -477,7 +478,7 @@ private:
         {}
 
         args_storage_base( const args_storage_base &k )
-            : my_kernel( k.my_kernel ), my_factory( k.my_factory )
+            : tbb::internal::no_copy(), my_kernel( k.my_kernel ), my_factory( k.my_factory )
         {}
 
         const kernel_type my_kernel;
index aee4076..6299cde 100644 (file)
 #define _FGT_GRAPH_TRACE_IMPL_H
 
 #include "../tbb_profiling.h"
+#if (_MSC_VER >= 1900)
+    #include <intrin.h>
+#endif
 
 namespace tbb {
     namespace internal {
 
 #if TBB_USE_THREADING_TOOLS
+    #if TBB_PREVIEW_FLOW_GRAPH_TRACE
+        #if (_MSC_VER >= 1900)
+            #define CODEPTR() (_ReturnAddress())
+        #elif __TBB_GCC_VERSION >= 40800
+            #define CODEPTR() ( __builtin_return_address(0))
+        #else
+            #define CODEPTR() NULL
+        #endif
+    #else
+        #define CODEPTR() NULL
+    #endif /* TBB_PREVIEW_FLOW_GRAPH_TRACE */
 
 static inline void fgt_alias_port(void *node, void *p, bool visible) {
     if(visible)
@@ -31,8 +45,14 @@ static inline void fgt_alias_port(void *node, void *p, bool visible) {
         itt_relation_add( ITT_DOMAIN_FLOW, p, FLOW_NODE, __itt_relation_is_child_of, node, FLOW_NODE );
 }
 
-static inline void fgt_composite ( void *node, void *graph ) {
+static inline void fgt_composite ( void* codeptr, void *node, void *graph ) {
     itt_make_task_group( ITT_DOMAIN_FLOW, node, FLOW_NODE, graph, FLOW_GRAPH, FLOW_COMPOSITE_NODE );
+    suppress_unused_warning( codeptr );
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+    if (codeptr != NULL) {
+        register_node_addr(ITT_DOMAIN_FLOW, node, FLOW_NODE, CODE_ADDRESS, &codeptr);
+    }
+#endif
 }
 
 static inline void fgt_internal_alias_input_port( void *node, void *p, string_index name_index ) {
@@ -88,8 +108,14 @@ static inline void fgt_internal_create_input_port( void *node, void *p, string_i
     itt_make_task_group( ITT_DOMAIN_FLOW, p, FLOW_INPUT_PORT, node, FLOW_NODE, name_index );
 }
 
-static inline void fgt_internal_create_output_port( void *node, void *p, string_index name_index ) {
-    itt_make_task_group( ITT_DOMAIN_FLOW, p, FLOW_OUTPUT_PORT, node, FLOW_NODE, name_index );
+static inline void fgt_internal_create_output_port( void* codeptr, void *node, void *p, string_index name_index ) {
+    itt_make_task_group(ITT_DOMAIN_FLOW, p, FLOW_OUTPUT_PORT, node, FLOW_NODE, name_index);
+    suppress_unused_warning( codeptr );
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+    if (codeptr != NULL) {
+        register_node_addr(ITT_DOMAIN_FLOW, node, FLOW_NODE, CODE_ADDRESS, &codeptr);
+    }
+#endif
 }
 
 template<typename InputType>
@@ -117,23 +143,23 @@ struct fgt_internal_input_helper<PortsTuple, 1> {
 };
 
 template<typename OutputType>
-void register_output_port(void *node, tbb::flow::sender<OutputType>* port, string_index name_index) {
+void register_output_port(void* codeptr, void *node, tbb::flow::sender<OutputType>* port, string_index name_index) {
     // TODO: Make fgt_internal_create_output_port a function template?
-    fgt_internal_create_output_port( node, static_cast<void *>(port), name_index);
+    fgt_internal_create_output_port( codeptr, node, static_cast<void *>(port), name_index);
 }
 
 template < typename PortsTuple, int N >
 struct fgt_internal_output_helper {
-    static void register_port( void *node, PortsTuple &ports ) {
-        register_output_port( node, &(tbb::flow::get<N-1>(ports)), static_cast<tbb::internal::string_index>(FLOW_OUTPUT_PORT_0 + N - 1) );
-        fgt_internal_output_helper<PortsTuple, N-1>::register_port( node, ports );
+    static void register_port( void* codeptr, void *node, PortsTuple &ports ) {
+        register_output_port( codeptr, node, &(tbb::flow::get<N-1>(ports)), static_cast<tbb::internal::string_index>(FLOW_OUTPUT_PORT_0 + N - 1) );
+        fgt_internal_output_helper<PortsTuple, N-1>::register_port( codeptr, node, ports );
     }
 };
 
 template < typename PortsTuple >
 struct fgt_internal_output_helper<PortsTuple,1> {
-    static void register_port( void *node, PortsTuple &ports ) {
-        register_output_port( node, &(tbb::flow::get<0>(ports)), FLOW_OUTPUT_PORT_0 );
+    static void register_port( void* codeptr, void *node, PortsTuple &ports ) {
+        register_output_port( codeptr, node, &(tbb::flow::get<0>(ports)), FLOW_OUTPUT_PORT_0 );
     }
 };
 
@@ -164,56 +190,61 @@ static inline void fgt_body( void *node, void *body ) {
 }
 
 template< int N, typename PortsTuple >
-static inline void fgt_multioutput_node( string_index t, void *g, void *input_port, PortsTuple &ports ) {
+static inline void fgt_multioutput_node(void* codeptr, string_index t, void *g, void *input_port, PortsTuple &ports ) {
     itt_make_task_group( ITT_DOMAIN_FLOW, input_port, FLOW_NODE, g, FLOW_GRAPH, t );
     fgt_internal_create_input_port( input_port, input_port, FLOW_INPUT_PORT_0 );
-    fgt_internal_output_helper<PortsTuple, N>::register_port( input_port, ports );
+    fgt_internal_output_helper<PortsTuple, N>::register_port(codeptr, input_port, ports );
 }
 
 template< int N, typename PortsTuple >
-static inline void fgt_multioutput_node_with_body( string_index t, void *g, void *input_port, PortsTuple &ports, void *body ) {
+static inline void fgt_multioutput_node_with_body( void* codeptr, string_index t, void *g, void *input_port, PortsTuple &ports, void *body ) {
     itt_make_task_group( ITT_DOMAIN_FLOW, input_port, FLOW_NODE, g, FLOW_GRAPH, t );
     fgt_internal_create_input_port( input_port, input_port, FLOW_INPUT_PORT_0 );
-    fgt_internal_output_helper<PortsTuple, N>::register_port( input_port, ports );
+    fgt_internal_output_helper<PortsTuple, N>::register_port( codeptr, input_port, ports );
     fgt_body( input_port, body );
 }
 
 template< int N, typename PortsTuple >
-static inline void fgt_multiinput_node( string_index t, void *g, PortsTuple &ports, void *output_port) {
+static inline void fgt_multiinput_node( void* codeptr, string_index t, void *g, PortsTuple &ports, void *output_port) {
     itt_make_task_group( ITT_DOMAIN_FLOW, output_port, FLOW_NODE, g, FLOW_GRAPH, t );
-    fgt_internal_create_output_port( output_port, output_port, FLOW_OUTPUT_PORT_0 );
+    fgt_internal_create_output_port( codeptr, output_port, output_port, FLOW_OUTPUT_PORT_0 );
     fgt_internal_input_helper<PortsTuple, N>::register_port( output_port, ports );
 }
 
-static inline void fgt_multiinput_multioutput_node( string_index t, void *n, void *g ) {
+static inline void fgt_multiinput_multioutput_node( void* codeptr, string_index t, void *n, void *g ) {
     itt_make_task_group( ITT_DOMAIN_FLOW, n, FLOW_NODE, g, FLOW_GRAPH, t );
+    suppress_unused_warning( codeptr );
+#if TBB_PREVIEW_FLOW_GRAPH_TRACE
+    if (codeptr != NULL) {
+        register_node_addr(ITT_DOMAIN_FLOW, n, FLOW_NODE, CODE_ADDRESS, &codeptr);
+    }
+#endif
 }
 
-static inline void fgt_node( string_index t, void *g, void *output_port ) {
+static inline void fgt_node( void* codeptr, string_index t, void *g, void *output_port ) {
     itt_make_task_group( ITT_DOMAIN_FLOW, output_port, FLOW_NODE, g, FLOW_GRAPH, t );
-    fgt_internal_create_output_port( output_port, output_port, FLOW_OUTPUT_PORT_0 );
+    fgt_internal_create_output_port( codeptr, output_port, output_port, FLOW_OUTPUT_PORT_0 );
 }
 
-static inline void fgt_node_with_body( string_index t, void *g, void *output_port, void *body ) {
+static void fgt_node_with_body( void* codeptr, string_index t, void *g, void *output_port, void *body ) {
     itt_make_task_group( ITT_DOMAIN_FLOW, output_port, FLOW_NODE, g, FLOW_GRAPH, t );
-    fgt_internal_create_output_port( output_port, output_port, FLOW_OUTPUT_PORT_0 );
+    fgt_internal_create_output_port(codeptr, output_port, output_port, FLOW_OUTPUT_PORT_0 );
     fgt_body( output_port, body );
 }
 
-
-static inline void fgt_node( string_index t, void *g, void *input_port, void *output_port ) {
-    fgt_node( t, g, output_port );
+static inline void fgt_node( void* codeptr, string_index t, void *g, void *input_port, void *output_port ) {
+    fgt_node( codeptr, t, g, output_port );
     fgt_internal_create_input_port( output_port, input_port, FLOW_INPUT_PORT_0 );
 }
 
-static inline void fgt_node_with_body( string_index t, void *g, void *input_port, void *output_port, void *body ) {
-    fgt_node_with_body( t, g, output_port, body );
+static inline void  fgt_node_with_body( void* codeptr, string_index t, void *g, void *input_port, void *output_port, void *body ) {
+    fgt_node_with_body( codeptr, t, g, output_port, body );
     fgt_internal_create_input_port( output_port, input_port, FLOW_INPUT_PORT_0 );
 }
 
 
-static inline void  fgt_node( string_index t, void *g, void *input_port, void *decrement_port, void *output_port ) {
-    fgt_node( t, g, input_port, output_port );
+static inline void  fgt_node( void* codeptr, string_index t, void *g, void *input_port, void *decrement_port, void *output_port ) {
+    fgt_node( codeptr, t, g, input_port, output_port );
     fgt_internal_create_input_port( output_port, decrement_port, FLOW_INPUT_PORT_1 );
 }
 
@@ -263,9 +294,11 @@ static inline void fgt_release_wait( void *graph ) {
 
 #else // TBB_USE_THREADING_TOOLS
 
+#define CODEPTR() NULL
+
 static inline void fgt_alias_port(void * /*node*/, void * /*p*/, bool /*visible*/ ) { }
 
-static inline void fgt_composite ( void * /*node*/, void * /*graph*/ ) { }
+static inline void fgt_composite ( void* /*codeptr*/, void * /*node*/, void * /*graph*/ ) { }
 
 static inline void fgt_graph( void * /*g*/ ) { }
 
@@ -280,22 +313,22 @@ static inline void fgt_graph_desc( void * /*g*/, const char * /*desc*/ ) { }
 static inline void fgt_body( void * /*node*/, void * /*body*/ ) { }
 
 template< int N, typename PortsTuple >
-static inline void fgt_multioutput_node( string_index /*t*/, void * /*g*/, void * /*input_port*/, PortsTuple & /*ports*/ ) { }
+static inline void fgt_multioutput_node( void* /*codeptr*/, string_index /*t*/, void * /*g*/, void * /*input_port*/, PortsTuple & /*ports*/ ) { }
 
 template< int N, typename PortsTuple >
-static inline void fgt_multioutput_node_with_body( string_index /*t*/, void * /*g*/, void * /*input_port*/, PortsTuple & /*ports*/, void * /*body*/ ) { }
+static inline void fgt_multioutput_node_with_body( void* /*codeptr*/, string_index /*t*/, void * /*g*/, void * /*input_port*/, PortsTuple & /*ports*/, void * /*body*/ ) { }
 
 template< int N, typename PortsTuple >
-static inline void fgt_multiinput_node( string_index /*t*/, void * /*g*/, PortsTuple & /*ports*/, void * /*output_port*/ ) { }
+static inline void fgt_multiinput_node( void* /*codeptr*/, string_index /*t*/, void * /*g*/, PortsTuple & /*ports*/, void * /*output_port*/ ) { }
 
-static inline void fgt_multiinput_multioutput_node( string_index /*t*/, void * /*node*/, void * /*graph*/ ) { }
+static inline void fgt_multiinput_multioutput_node( void* /*codeptr*/, string_index /*t*/, void * /*node*/, void * /*graph*/ ) { }
 
-static inline void fgt_node( string_index /*t*/, void * /*g*/, void * /*output_port*/ ) { }
-static inline void fgt_node( string_index /*t*/, void * /*g*/, void * /*input_port*/, void * /*output_port*/ ) { }
-static inline void  fgt_node( string_index /*t*/, void * /*g*/, void * /*input_port*/, void * /*decrement_port*/, void * /*output_port*/ ) { }
+static inline void fgt_node( void* /*codeptr*/, string_index /*t*/, void * /*g*/, void * /*output_port*/ ) { }
+static inline void fgt_node( void* /*codeptr*/, string_index /*t*/, void * /*g*/, void * /*input_port*/, void * /*output_port*/ ) { }
+static inline void  fgt_node( void* /*codeptr*/, string_index /*t*/, void * /*g*/, void * /*input_port*/, void * /*decrement_port*/, void * /*output_port*/ ) { }
 
-static inline void fgt_node_with_body( string_index /*t*/, void * /*g*/, void * /*output_port*/, void * /*body*/ ) { }
-static inline void fgt_node_with_body( string_index /*t*/, void * /*g*/, void * /*input_port*/, void * /*output_port*/, void * /*body*/ ) { }
+static inline void fgt_node_with_body( void* /*codeptr*/, string_index /*t*/, void * /*g*/, void * /*output_port*/, void * /*body*/ ) { }
+static inline void fgt_node_with_body( void* /*codeptr*/, string_index /*t*/, void * /*g*/, void * /*input_port*/, void * /*output_port*/, void * /*body*/ ) { }
 
 static inline void fgt_make_edge( void * /*output_port*/, void * /*input_port*/ ) { }
 static inline void fgt_remove_edge( void * /*output_port*/, void * /*input_port*/ ) { }
index 510bde3..f3e5de2 100644 (file)
@@ -58,23 +58,23 @@ static const size_t hash_multiplier = tbb::internal::select_size_t_constant<2654
 
 //! Hasher functions
 template<typename T>
-inline size_t tbb_hasher( const T& t ) {
+__TBB_DEPRECATED_MSG("tbb::tbb_hasher is deprecated, use std::hash") inline size_t tbb_hasher( const T& t ) {
     return static_cast<size_t>( t ) * internal::hash_multiplier;
 }
 template<typename P>
-inline size_t tbb_hasher( P* ptr ) {
+__TBB_DEPRECATED_MSG("tbb::tbb_hasher is deprecated, use std::hash") inline size_t tbb_hasher( P* ptr ) {
     size_t const h = reinterpret_cast<size_t>( ptr );
     return (h >> 3) ^ h;
 }
 template<typename E, typename S, typename A>
-inline size_t tbb_hasher( const std::basic_string<E,S,A>& s ) {
+__TBB_DEPRECATED_MSG("tbb::tbb_hasher is deprecated, use std::hash") inline size_t tbb_hasher( const std::basic_string<E,S,A>& s ) {
     size_t h = 0;
     for( const E* c = s.c_str(); *c; ++c )
         h = static_cast<size_t>(*c) ^ (h * internal::hash_multiplier);
     return h;
 }
 template<typename F, typename S>
-inline size_t tbb_hasher( const std::pair<F,S>& p ) {
+__TBB_DEPRECATED_MSG("tbb::tbb_hasher is deprecated, use std::hash") inline size_t tbb_hasher( const std::pair<F,S>& p ) {
     return tbb_hasher(p.first) ^ tbb_hasher(p.second);
 }
 
@@ -83,7 +83,7 @@ using interface5::tbb_hasher;
 
 // Template class for hash compare
 template<typename Key>
-class tbb_hash
+class __TBB_DEPRECATED_MSG("tbb::tbb_hash is deprecated, use std::hash") tbb_hash
 {
 public:
     tbb_hash() {}
index a5fd3ce..ee00525 100644 (file)
@@ -74,3 +74,6 @@ TBB_STRING_RESOURCE(FLOW_TASKS, "tbb_flow_graph")
 TBB_STRING_RESOURCE(PARALLEL_FOR_TASK, "tbb_parallel_for_task")
 // TODO: Drop following string prefix "fgt_" here and in FGA's collector
 TBB_STRING_RESOURCE(USER_EVENT, "fgt_user_event")
+#if __TBB_CPF_BUILD || (TBB_PREVIEW_FLOW_GRAPH_TRACE && TBB_USE_THREADING_TOOLS)
+TBB_STRING_RESOURCE(CODE_ADDRESS, "code_address")
+#endif
index 87c3efb..d31a3da 100644 (file)
@@ -210,6 +210,22 @@ using make_index_sequence = typename tbb::internal::make_index_sequence_impl<N>:
 
 #endif /* __TBB_CPP14_INTEGER_SEQUENCE_PRESENT */
 
+#if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT
+template<typename... Args>
+struct conjunction;
+
+template<typename First, typename... Args>
+struct conjunction<First, Args...>
+    : std::conditional<bool(First::value), conjunction<Args...>, First>::type {};
+
+template<typename T>
+struct conjunction<T> : T {};
+
+template<>
+struct conjunction<> : std::true_type {};
+
+#endif
+
 #if __TBB_CPP11_PRESENT
 
 template< typename Iter >
@@ -255,10 +271,11 @@ struct pack_element<0, T, Args...> {
 template< std::size_t N, typename... Args >
 using pack_element_t = typename pack_element<N, Args...>::type;
 
-template <typename Comp> using is_transparent = typename Comp::is_transparent;
-
-template <typename Comp>
-using has_is_transparent = supports<Comp, is_transparent>;
+// Helper alias for heterogeneous lookup functions in containers
+// template parameter K and std::conditional are needed to provide immediate context
+// and postpone getting is_trasparent from the compare functor until method instantiation.
+template <typename Comp, typename K>
+using is_transparent = typename std::conditional<true, Comp, K>::type::is_transparent;
 
 #endif /* __TBB_CPP11_PRESENT */
 
diff --git a/include/tbb/internal/_warning_suppress_disable_notice.h b/include/tbb/internal/_warning_suppress_disable_notice.h
new file mode 100644 (file)
index 0000000..fed04a1
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+    Copyright (c) 2005-2019 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.
+*/
+
+#if __TBB_SUPPRESS_INTERNAL_DEPRECATED_MESSAGES
+
+#if __INTEL_COMPILER || _MSC_VER
+#pragma warning( pop )
+#elif __GNUC__
+#pragma GCC diagnostic pop
+#elif __clang__
+#pragma clang diagnostic pop
+#endif
+
+#endif  // __TBB_SUPPRESS_INTERNAL_DEPRECATED_MESSAGES
diff --git a/include/tbb/internal/_warning_suppress_enable_notice.h b/include/tbb/internal/_warning_suppress_enable_notice.h
new file mode 100644 (file)
index 0000000..cd2bc8a
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+    Copyright (c) 2005-2019 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.
+*/
+
+#include "../tbb_config.h"
+
+#if __TBB_SUPPRESS_INTERNAL_DEPRECATED_MESSAGES
+
+#if _MSC_VER || __INTEL_COMPILER
+#pragma warning( push )
+#pragma warning( disable: 4996 )
+#elif __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#elif __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+#endif  // __TBB_SUPPRESS_INTERNAL_DEPRECATED_MESSAGES
index 7a3c927..39f21ac 100644 (file)
@@ -156,7 +156,7 @@ struct tuplewrapper : public std::tuple<typename std::enable_if<std::is_referenc
 
 template <typename... Types>
 class zip_iterator {
-    __TBB_STATIC_ASSERT(sizeof...(Types), "Cannot instantiate zip_iterator with empty template parameter pack");
+    __TBB_STATIC_ASSERT(sizeof...(Types)>0, "Cannot instantiate zip_iterator with empty template parameter pack");
     static const std::size_t num_types = sizeof...(Types);
     typedef std::tuple<Types...> it_types;
 public:
index 5f461f3..ca46ec8 100644 (file)
     limitations under the License.
 */
 
+#include "internal/_deprecated_header_message_guard.h"
+
+#if !defined(__TBB_show_deprecation_message_mutex_H) && defined(__TBB_show_deprecated_header_message)
+#define  __TBB_show_deprecation_message_mutex_H
+#pragma message("TBB Warning: tbb/mutex.h is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.")
+#endif
+
+#if defined(__TBB_show_deprecated_header_message)
+#undef __TBB_show_deprecated_header_message
+#endif
+
 #ifndef __TBB_mutex_H
 #define __TBB_mutex_H
 
+#define __TBB_mutex_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #if _WIN32||_WIN64
 #include "machine/windows_api.h"
 #else
@@ -32,7 +46,7 @@ namespace tbb {
 
 //! Wrapper around the platform's native lock.
 /** @ingroup synchronization */
-class mutex : internal::mutex_copy_deprecated_and_disabled {
+class __TBB_DEPRECATED_VERBOSE_MSG("tbb::critical_section is deprecated, use std::mutex") mutex : internal::mutex_copy_deprecated_and_disabled {
 public:
     //! Construct unacquired mutex.
     mutex() {
@@ -226,4 +240,7 @@ __TBB_DEFINE_PROFILING_SET_NAME(mutex)
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_mutex_H_include_area
+
 #endif /* __TBB_mutex_H */
index d3f2075..ab0f151 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_parallel_do_H
 #define __TBB_parallel_do_H
 
+#define __TBB_parallel_do_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "internal/_range_iterator.h"
 #include "internal/_template_helpers.h"
 #include "task.h"
@@ -544,4 +547,7 @@ using interface9::parallel_do_feeder;
 
 } // namespace
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_parallel_do_H_include_area
+
 #endif /* __TBB_parallel_do_H */
index a682067..bcdcaad 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_parallel_for_H
 #define __TBB_parallel_for_H
 
+#define __TBB_parallel_for_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include <new>
 #include "task.h"
 #include "partitioner.h"
@@ -107,9 +110,9 @@ namespace internal {
         }
 #endif /* __TBB_TASK_GROUP_CONTEXT */
         //! Run body for range, serves as callback for partitioner
-        void run_body( Range &r ) { 
+        void run_body( Range &r ) {
             fgt_alg_begin_body( tbb::internal::PARALLEL_FOR_TASK, (void *)const_cast<Body*>(&(this->my_body)), (void*)this );
-            my_body( r ); 
+            my_body( r );
             fgt_alg_end_body( (void *)const_cast<Body*>(&(this->my_body)) );
         }
 
@@ -416,4 +419,7 @@ using strict_ppl::parallel_for;
 #undef __TBB_NORMAL_EXECUTION
 #endif
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_parallel_for_H_include_area
+
 #endif /* __TBB_parallel_for_H */
index 026b445..0dffc81 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_parallel_invoke_H
 #define __TBB_parallel_invoke_H
 
+#define __TBB_parallel_invoke_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "task.h"
 #include "tbb_profiling.h"
 
@@ -451,4 +454,7 @@ void parallel_invoke(const F0& f0, const F1& f1, const F2& f2, const F3& f3, con
 
 } // namespace
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_parallel_invoke_H_include_area
+
 #endif /* __TBB_parallel_invoke_H */
index 9908de9..24e36cb 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_parallel_reduce_H
 #define __TBB_parallel_reduce_H
 
+#define __TBB_parallel_reduce_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include <new>
 #include "task.h"
 #include "aligned_space.h"
@@ -648,4 +651,7 @@ Value parallel_deterministic_reduce( const Range& range, const Value& identity,
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_parallel_reduce_H_include_area
+
 #endif /* __TBB_parallel_reduce_H */
index 7f6478d..302965e 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_parallel_scan_H
 #define __TBB_parallel_scan_H
 
+#define __TBB_parallel_scan_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "task.h"
 #include "aligned_space.h"
 #include <new>
@@ -406,5 +409,8 @@ Value parallel_scan( const Range& range, const Value& identity, const Scan& scan
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_parallel_scan_H_include_area
+
 #endif /* __TBB_parallel_scan_H */
 
index a543a6a..b5f015e 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_parallel_sort_H
 #define __TBB_parallel_sort_H
 
+#define __TBB_parallel_sort_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "parallel_for.h"
 #include "blocked_range.h"
 #include "internal/_range_iterator.h"
@@ -247,5 +250,8 @@ inline void parallel_sort( T * begin, T * end ) {
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_parallel_sort_H_include_area
+
 #endif
 
index 0717700..b32c781 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_parallel_while
 #define __TBB_parallel_while
 
+#define __TBB_parallel_while_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "task.h"
 #include <new>
 
@@ -179,4 +182,7 @@ void parallel_while<Body>::add( const value_type& item ) {
 
 } // namespace
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_parallel_while_H_include_area
+
 #endif /* __TBB_parallel_while */
index 285ada7..b17c263 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_partitioner_H
 #define __TBB_partitioner_H
 
+#define __TBB_partitioner_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #ifndef __TBB_INITIAL_CHUNKS
 // initial task divisions per thread
 #define __TBB_INITIAL_CHUNKS 2
@@ -671,4 +674,8 @@ private:
 #undef __TBB_INITIAL_CHUNKS
 #undef __TBB_RANGE_POOL_CAPACITY
 #undef __TBB_INIT_DEPTH
+
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_partitioner_H_include_area
+
 #endif /* __TBB_partitioner_H */
index c713864..fad817b 100644 (file)
 #ifndef __TBB_pipeline_H
 #define __TBB_pipeline_H
 
+#define __TBB_pipeline_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "atomic.h"
 #include "task.h"
 #include "tbb_allocator.h"
 #include <cstddef>
 
-#if __TBB_CPP11_TYPE_PROPERTIES_PRESENT || __TBB_TR1_TYPE_PROPERTIES_IN_STD_PRESENT
+#if __TBB_CPP11_TYPE_PROPERTIES_PRESENT
 #include <type_traits>
 #endif
 
@@ -61,7 +64,7 @@ namespace interface6 {
 class filter: internal::no_copy {
 private:
     //! Value used to mark "not in pipeline"
-    static filter* not_in_pipeline() {return reinterpret_cast<filter*>(intptr_t(-1));}
+    static filter* not_in_pipeline() { return reinterpret_cast<filter*>(intptr_t(-1)); }
 protected:
     //! The lowest bit 0 is for parallel vs. serial
     static const unsigned char filter_is_serial = 0x1;
@@ -153,7 +156,7 @@ public:
     //! Destroys item if pipeline was cancelled.
     /** Required to prevent memory leaks.
         Note it can be called concurrently even for serial filters.*/
-    virtual void finalize( void* /*item*/ ) {};
+    virtual void finalize( void* /*item*/ ) {}
 #endif
 
 private:
@@ -229,7 +232,7 @@ private:
 
 //! A processing pipeline that applies filters to items.
 /** @ingroup algorithms */
-class pipeline {
+class __TBB_DEPRECATED_MSG("tbb::pipeline is deprecated, use tbb::parallel_pipeline") pipeline {
 public:
     //! Construct empty pipeline.
     __TBB_EXPORTED_METHOD pipeline();
@@ -315,43 +318,58 @@ public:
 //! @cond INTERNAL
 namespace internal {
 
-template<typename T> struct tbb_large_object {enum { value = sizeof(T) > sizeof(void *) }; };
-
-// Obtain type properties in one or another way
+// Emulate std::is_trivially_copyable (false positives not allowed, false negatives suboptimal but safe).
 #if   __TBB_CPP11_TYPE_PROPERTIES_PRESENT
 template<typename T> struct tbb_trivially_copyable { enum { value = std::is_trivially_copyable<T>::value }; };
-#elif __TBB_TR1_TYPE_PROPERTIES_IN_STD_PRESENT
-template<typename T> struct tbb_trivially_copyable { enum { value = std::has_trivial_copy_constructor<T>::value }; };
 #else
-// Explicitly list the types we wish to be placed as-is in the pipeline input_buffers.
-template<typename T> struct tbb_trivially_copyable { enum { value = false }; };
-template<typename T> struct tbb_trivially_copyable <T*> { enum { value = true }; };
-template<> struct tbb_trivially_copyable <short> { enum { value = true }; };
-template<> struct tbb_trivially_copyable <unsigned short> { enum { value = true }; };
-template<> struct tbb_trivially_copyable <int> { enum { value = !tbb_large_object<int>::value }; };
-template<> struct tbb_trivially_copyable <unsigned int> { enum { value = !tbb_large_object<int>::value }; };
-template<> struct tbb_trivially_copyable <long> { enum { value = !tbb_large_object<long>::value }; };
-template<> struct tbb_trivially_copyable <unsigned long> { enum { value = !tbb_large_object<long>::value }; };
-template<> struct tbb_trivially_copyable <float> { enum { value = !tbb_large_object<float>::value }; };
-template<> struct tbb_trivially_copyable <double> { enum { value = !tbb_large_object<double>::value }; };
-#endif // Obtaining type properties
-
-template<typename T> struct is_large_object {enum { value = tbb_large_object<T>::value || !tbb_trivially_copyable<T>::value }; };
-
-template<typename T, bool> class token_helper;
-
-// large object helper (uses tbb_allocator)
+template<typename T> struct tbb_trivially_copyable                      { enum { value = false }; };
+template<typename T> struct tbb_trivially_copyable <         T*       > { enum { value = true  }; };
+template<>           struct tbb_trivially_copyable <         bool     > { enum { value = true  }; };
+template<>           struct tbb_trivially_copyable <         char     > { enum { value = true  }; };
+template<>           struct tbb_trivially_copyable <  signed char     > { enum { value = true  }; };
+template<>           struct tbb_trivially_copyable <unsigned char     > { enum { value = true  }; };
+template<>           struct tbb_trivially_copyable <         short    > { enum { value = true  }; };
+template<>           struct tbb_trivially_copyable <unsigned short    > { enum { value = true  }; };
+template<>           struct tbb_trivially_copyable <         int      > { enum { value = true  }; };
+template<>           struct tbb_trivially_copyable <unsigned int      > { enum { value = true  }; };
+template<>           struct tbb_trivially_copyable <         long     > { enum { value = true  }; };
+template<>           struct tbb_trivially_copyable <unsigned long     > { enum { value = true  }; };
+template<>           struct tbb_trivially_copyable <         long long> { enum { value = true  }; };
+template<>           struct tbb_trivially_copyable <unsigned long long> { enum { value = true  }; };
+template<>           struct tbb_trivially_copyable <         float    > { enum { value = true  }; };
+template<>           struct tbb_trivially_copyable <         double   > { enum { value = true  }; };
+template<>           struct tbb_trivially_copyable <    long double   > { enum { value = true  }; };
+#if !_MSC_VER || defined(_NATIVE_WCHAR_T_DEFINED)
+template<>           struct tbb_trivially_copyable <         wchar_t  > { enum { value = true  }; };
+#endif /* _MSC_VER||!defined(_NATIVE_WCHAR_T_DEFINED) */
+#endif // tbb_trivially_copyable
+
+template<typename T>
+struct use_allocator {
+    enum { value = sizeof(T) > sizeof(void *) || !tbb_trivially_copyable<T>::value };
+};
+
+// A helper class to customize how a type is passed between filters.
+// Usage: token_helper<T, use_allocator<T>::value>
+template<typename T, bool Allocate> class token_helper;
+
+// using tbb_allocator
 template<typename T>
 class token_helper<T, true> {
-    public:
+public:
     typedef typename tbb::tbb_allocator<T> allocator;
     typedef T* pointer;
     typedef T value_type;
-    static pointer create_token(const value_type & source) {
+#if __TBB_CPP11_RVALUE_REF_PRESENT
+    static pointer create_token(value_type && source)
+#else
+    static pointer create_token(const value_type & source)
+#endif
+    {
         pointer output_t = allocator().allocate(1);
-        return new (output_t) T(source);
+        return new (output_t) T(tbb::internal::move(source));
     }
-    static value_type & token(pointer & t) { return *t;}
+    static value_type & token(pointer & t) { return *t; }
     static void * cast_to_void_ptr(pointer ref) { return (void *) ref; }
     static pointer cast_from_void_ptr(void * ref) { return (pointer)ref; }
     static void destroy_token(pointer token) {
@@ -362,30 +380,29 @@ class token_helper<T, true> {
 
 // pointer specialization
 template<typename T>
-class token_helper<T*, false > {
-    public:
+class token_helper<T*, false> {
+public:
     typedef T* pointer;
     typedef T* value_type;
     static pointer create_token(const value_type & source) { return source; }
-    static value_type & token(pointer & t) { return t;}
+    static value_type & token(pointer & t) { return t; }
     static void * cast_to_void_ptr(pointer ref) { return (void *)ref; }
     static pointer cast_from_void_ptr(void * ref) { return (pointer)ref; }
     static void destroy_token( pointer /*token*/) {}
 };
 
-// small object specialization (converts void* to the correct type, passes objects directly.)
+// converting type to and from void*, passing objects directly
 template<typename T>
 class token_helper<T, false> {
     typedef union {
         T actual_value;
         void * void_overlay;
     } type_to_void_ptr_map;
-    public:
+public:
     typedef T pointer;  // not really a pointer in this case.
     typedef T value_type;
-    static pointer create_token(const value_type & source) {
-        return source; }
-    static value_type & token(pointer & t) { return t;}
+    static pointer create_token(const value_type & source) { return source; }
+    static value_type & token(pointer & t) { return t; }
     static void * cast_to_void_ptr(pointer ref) {
         type_to_void_ptr_map mymap;
         mymap.void_overlay = NULL;
@@ -400,17 +417,18 @@ class token_helper<T, false> {
     static void destroy_token( pointer /*token*/) {}
 };
 
+// intermediate
 template<typename T, typename U, typename Body>
 class concrete_filter: public tbb::filter {
     const Body& my_body;
-    typedef token_helper<T,is_large_object<T>::value > t_helper;
+    typedef token_helper<T,use_allocator<T>::value> t_helper;
     typedef typename t_helper::pointer t_pointer;
-    typedef token_helper<U,is_large_object<U>::value > u_helper;
+    typedef token_helper<U,use_allocator<U>::value> u_helper;
     typedef typename u_helper::pointer u_pointer;
 
     void* operator()(void* input) __TBB_override {
         t_pointer temp_input = t_helper::cast_from_void_ptr(input);
-        u_pointer output_u = u_helper::create_token(my_body(t_helper::token(temp_input)));
+        u_pointer output_u = u_helper::create_token(my_body(tbb::internal::move(t_helper::token(temp_input))));
         t_helper::destroy_token(temp_input);
         return u_helper::cast_to_void_ptr(output_u);
     }
@@ -428,7 +446,7 @@ public:
 template<typename U, typename Body>
 class concrete_filter<void,U,Body>: public filter {
     const Body& my_body;
-    typedef token_helper<U, is_large_object<U>::value > u_helper;
+    typedef token_helper<U, use_allocator<U>::value> u_helper;
     typedef typename u_helper::pointer u_pointer;
 
     void* operator()(void*) __TBB_override {
@@ -449,15 +467,16 @@ public:
     {}
 };
 
+// output
 template<typename T, typename Body>
 class concrete_filter<T,void,Body>: public filter {
     const Body& my_body;
-    typedef token_helper<T, is_large_object<T>::value > t_helper;
+    typedef token_helper<T, use_allocator<T>::value> t_helper;
     typedef typename t_helper::pointer t_pointer;
 
     void* operator()(void* input) __TBB_override {
         t_pointer temp_input = t_helper::cast_from_void_ptr(input);
-        my_body(t_helper::token(temp_input));
+        my_body(tbb::internal::move(t_helper::token(temp_input)));
         t_helper::destroy_token(temp_input);
         return NULL;
     }
@@ -474,7 +493,6 @@ template<typename Body>
 class concrete_filter<void,void,Body>: public filter {
     const Body& my_body;
 
-    /** Override privately because it is always called virtually */
     void* operator()(void*) __TBB_override {
         flow_control control;
         my_body(control);
@@ -514,7 +532,7 @@ public:
     //! Add concrete_filter to pipeline
     virtual void add_to( pipeline& ) = 0;
     //! Increment reference count
-    void add_ref() {++ref_count;}
+    void add_ref() { ++ref_count; }
     //! Decrement reference count and delete if it becomes zero.
     void remove_ref() {
         __TBB_ASSERT(ref_count>0,"ref_count underflow");
@@ -530,7 +548,7 @@ public:
 
 //! Node in parse tree representing result of make_filter.
 template<typename T, typename U, typename Body>
-class filter_node_leaf: public filter_node  {
+class filter_node_leaf: public filter_node {
     const tbb::filter::mode mode;
     const Body body;
     void add_to( pipeline& p ) __TBB_override {
@@ -658,4 +676,7 @@ using interface6::parallel_pipeline;
 
 } // tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_pipeline_H_include_area
+
 #endif /* __TBB_pipeline_H */
index 15f9477..17a858f 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_queuing_mutex_H
 #define __TBB_queuing_mutex_H
 
+#define __TBB_queuing_mutex_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include <cstring>
 #include "atomic.h"
 #include "tbb_profiling.h"
@@ -104,4 +107,7 @@ __TBB_DEFINE_PROFILING_SET_NAME(queuing_mutex)
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_queuing_mutex_H_include_area
+
 #endif /* __TBB_queuing_mutex_H */
index 6d5d313..86f1b8f 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_queuing_rw_mutex_H
 #define __TBB_queuing_rw_mutex_H
 
+#define __TBB_queuing_rw_mutex_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include <cstring>
 #include "atomic.h"
 #include "tbb_profiling.h"
@@ -145,4 +148,7 @@ __TBB_DEFINE_PROFILING_SET_NAME(queuing_rw_mutex)
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_queuing_rw_mutex_H_include_area
+
 #endif /* __TBB_queuing_rw_mutex_H */
index 2275abc..0783c79 100644 (file)
     limitations under the License.
 */
 
+#include "internal/_deprecated_header_message_guard.h"
+
+#if !defined(__TBB_show_deprecation_message_reader_writer_lock_H) && defined(__TBB_show_deprecated_header_message)
+#define  __TBB_show_deprecation_message_reader_writer_lock_H
+#pragma message("TBB Warning: tbb/reader_writer_lock.h is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.")
+#endif
+
+#if defined(__TBB_show_deprecated_header_message)
+#undef __TBB_show_deprecated_header_message
+#endif
+
 #ifndef __TBB_reader_writer_lock_H
 #define __TBB_reader_writer_lock_H
 
+#define __TBB_reader_writer_lock_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "tbb_thread.h"
 #include "tbb_allocator.h"
 #include "atomic.h"
@@ -27,7 +41,8 @@ namespace interface5 {
 /** Loosely adapted from Mellor-Crummey and Scott pseudocode at
     http://www.cs.rochester.edu/research/synchronization/pseudocode/rw.html#s_wp
     @ingroup synchronization */
-    class reader_writer_lock : tbb::internal::no_copy {
+    class __TBB_DEPRECATED_VERBOSE_MSG("tbb::reader_writer_lock is deprecated, use std::shared_mutex")
+    reader_writer_lock : tbb::internal::no_copy {
  public:
     friend class scoped_lock;
     friend class scoped_lock_read;
@@ -225,4 +240,7 @@ using interface5::reader_writer_lock;
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_reader_writer_lock_H_include_area
+
 #endif /* __TBB_reader_writer_lock_H */
index 576bd99..3a3f979 100644 (file)
     limitations under the License.
 */
 
+#include "internal/_deprecated_header_message_guard.h"
+
+#if !defined(__TBB_show_deprecation_message_recursive_mutex_H) && defined(__TBB_show_deprecated_header_message)
+#define  __TBB_show_deprecation_message_recursive_mutex_H
+#pragma message("TBB Warning: tbb/recursive_mutex.h is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.")
+#endif
+
+#if defined(__TBB_show_deprecated_header_message)
+#undef __TBB_show_deprecated_header_message
+#endif
+
 #ifndef __TBB_recursive_mutex_H
 #define __TBB_recursive_mutex_H
 
+#define __TBB_recursive_mutex_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #if _WIN32||_WIN64
 #include "machine/windows_api.h"
 #else
@@ -32,7 +46,8 @@ namespace tbb {
 //! Mutex that allows recursive mutex acquisition.
 /** Mutex that allows recursive mutex acquisition.
     @ingroup synchronization */
-class recursive_mutex : internal::mutex_copy_deprecated_and_disabled {
+class __TBB_DEPRECATED_VERBOSE_MSG("tbb::recursive_mutex is deprecated, use std::recursive_mutex")
+recursive_mutex : internal::mutex_copy_deprecated_and_disabled {
 public:
     //! Construct unacquired recursive_mutex.
     recursive_mutex() {
@@ -227,4 +242,7 @@ __TBB_DEFINE_PROFILING_SET_NAME(recursive_mutex)
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_recursive_mutex_H_include_area
+
 #endif /* __TBB_recursive_mutex_H */
index a6d695b..2c82b70 100644 (file)
     limitations under the License.
 */
 
+#include "internal/_deprecated_header_message_guard.h"
+
+#if !defined(__TBB_show_deprecation_message_runtime_loader_H) && defined(__TBB_show_deprecated_header_message)
+#define  __TBB_show_deprecation_message_runtime_loader_H
+#pragma message("TBB Warning: tbb/runtime_loader.h is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.")
+#endif
+
+#if defined(__TBB_show_deprecated_header_message)
+#undef __TBB_show_deprecated_header_message
+#endif
+
 #ifndef __TBB_runtime_loader_H
 #define __TBB_runtime_loader_H
 
+#define __TBB_runtime_loader_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #if ! TBB_PREVIEW_RUNTIME_LOADER
     #error Set TBB_PREVIEW_RUNTIME_LOADER to include runtime_loader.h
 #endif
@@ -78,7 +92,7 @@ There are some implications:
 
 */
 
-class runtime_loader : tbb::internal::no_copy {
+class __TBB_DEPRECATED_VERBOSE runtime_loader : tbb::internal::no_copy {
 
     public:
 
@@ -172,5 +186,8 @@ using interface6::runtime_loader;
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_runtime_loader_H_include_area
+
 #endif /* __TBB_runtime_loader_H */
 
index e29cf35..1258490 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_spin_mutex_H
 #define __TBB_spin_mutex_H
 
+#define __TBB_spin_mutex_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include <cstddef>
 #include <new>
 #include "aligned_space.h"
@@ -205,4 +208,7 @@ __TBB_DEFINE_PROFILING_SET_NAME(speculative_spin_mutex)
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_spin_mutex_H_include_area
+
 #endif /* __TBB_spin_mutex_H */
index 6eff290..15cb88c 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_task_H
 #define __TBB_task_H
 
+#define __TBB_task_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "tbb_stddef.h"
 #include "tbb_machine.h"
 #include "tbb_profiling.h"
@@ -116,6 +119,11 @@ namespace internal {
     /** Should always be non-negative.  A signed type is used so that underflow can be detected. */
     typedef intptr_t reference_count;
 
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    //! The flag to indicate that the wait task has been abandoned.
+    static const reference_count abandon_flag = reference_count(1) << (sizeof(reference_count)*CHAR_BIT - 2);
+#endif
+
     //! An id as used for specifying affinity.
     typedef unsigned short affinity_id;
 
@@ -219,7 +227,7 @@ namespace internal {
             thread-specific pools. */
         scheduler* origin;
 
-#if __TBB_TASK_PRIORITY
+#if __TBB_TASK_PRIORITY || __TBB_PREVIEW_RESUMABLE_TASKS
         union {
 #endif /* __TBB_TASK_PRIORITY */
         //! Obsolete. The scheduler that owns the task.
@@ -231,8 +239,15 @@ namespace internal {
         //! Pointer to the next offloaded lower priority task.
         /** Used to maintain a list of offloaded tasks inside the scheduler. **/
         task* next_offloaded;
+#endif
+
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+        //! Pointer to the abandoned scheduler where the current task is waited for.
+        scheduler* abandoned_scheduler;
+#endif
+#if __TBB_TASK_PRIORITY || __TBB_PREVIEW_RESUMABLE_TASKS
         };
-#endif /* __TBB_TASK_PRIORITY */
+#endif /* __TBB_TASK_PRIORITY || __TBB_PREVIEW_RESUMABLE_TASKS */
 
         //! The task whose reference count includes me.
         /** In the "blocking style" of programming, this field points to the parent task.
@@ -542,10 +557,10 @@ public:
 
 #if __TBB_TASK_PRIORITY
     //! Changes priority of the task group
-    void set_priority ( priority_t );
+    __TBB_DEPRECATED void set_priority ( priority_t );
 
     //! Retrieves current priority of the current task group
-    priority_t priority () const;
+    __TBB_DEPRECATED priority_t priority () const;
 #endif /* __TBB_TASK_PRIORITY */
 
     //! Returns the context's trait
@@ -623,6 +638,10 @@ public:
         //! task to be scheduled for starvation-resistant execution
         ,to_enqueue
 #endif
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+        //! a special task used to resume a scheduler.
+        ,to_resume
+#endif
     };
 
     //------------------------------------------------------------------------
@@ -809,7 +828,7 @@ public:
 
 #if __TBB_TASK_PRIORITY
     //! Enqueue task for starvation-resistant execution on the specified priority level.
-    static void enqueue( task& t, priority_t p ) {
+    __TBB_DEPRECATED static void enqueue( task& t, priority_t p ) {
 #if __TBB_PREVIEW_CRITICAL_TASKS
         __TBB_ASSERT(p == priority_low || p == priority_normal || p == priority_high
                      || p == internal::priority_critical, "Invalid priority level value");
@@ -822,11 +841,11 @@ public:
 
     //! Enqueue task in task_arena
     //! The implementation is in task_arena.h
-    inline static void enqueue( task& t, task_arena& arena
 #if __TBB_TASK_PRIORITY
-        , priority_t p = priority_t(0)
+    __TBB_DEPRECATED inline static void enqueue( task& t, task_arena& arena, priority_t p = priority_t(0) );
+#else
+    inline static void enqueue( task& t, task_arena& arena);
 #endif
-    );
 
     //! The innermost task being executed or destroyed by the current thread at the moment.
     static task& __TBB_EXPORTED_FUNC self();
@@ -856,6 +875,24 @@ public:
         return (prefix().extra_state & 0x80)!=0;
     }
 
+    //! True if the task was enqueued
+    bool is_enqueued_task() const {
+        // es_task_enqueued = 0x10
+        return (prefix().extra_state & 0x10)!=0;
+    }
+
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    //! Type that defines suspension point
+    typedef void* suspend_point;
+
+    //! Suspend current task execution
+    template <typename F>
+    static void suspend(F f);
+
+    //! Resume specific suspend point
+    static void resume(suspend_point tag);
+#endif
+
     //------------------------------------------------------------------------
     // Debugging
     //------------------------------------------------------------------------
@@ -866,10 +903,18 @@ public:
     //! The internal reference count.
     int ref_count() const {
 #if TBB_USE_ASSERT
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+        internal::reference_count ref_count_ = prefix().ref_count & ~internal::abandon_flag;
+#else
         internal::reference_count ref_count_ = prefix().ref_count;
+#endif
         __TBB_ASSERT( ref_count_==int(ref_count_), "integer overflow error");
 #endif
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+        return int(prefix().ref_count & ~internal::abandon_flag);
+#else
         return int(prefix().ref_count);
+#endif
     }
 
     //! Obsolete, and only retained for the sake of backward compatibility. Always returns true.
@@ -922,10 +967,10 @@ public:
 
 #if __TBB_TASK_PRIORITY
     //! Changes priority of the task group this task belongs to.
-    void set_group_priority ( priority_t p ) {  prefix().context->set_priority(p); }
+    __TBB_DEPRECATED void set_group_priority ( priority_t p ) {  prefix().context->set_priority(p); }
 
     //! Retrieves current priority of the task group this task belongs to.
-    priority_t group_priority () const { return prefix().context->priority(); }
+    __TBB_DEPRECATED priority_t group_priority () const { return prefix().context->priority(); }
 
 #endif /* __TBB_TASK_PRIORITY */
 
@@ -959,6 +1004,28 @@ inline bool is_critical( task& t ) { return bool((t.prefix().extra_state & 0x8)
 } // namespace internal
 #endif /* __TBB_PREVIEW_CRITICAL_TASKS */
 
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+namespace internal {
+    template <typename F>
+    static void suspend_callback(void* user_callback, task::suspend_point tag) {
+        // Copy user function to a new stack to avoid a race when the previous scheduler is resumed.
+        F user_callback_copy = *static_cast<F*>(user_callback);
+        user_callback_copy(tag);
+    }
+    void __TBB_EXPORTED_FUNC internal_suspend(void* suspend_callback, void* user_callback);
+    void __TBB_EXPORTED_FUNC internal_resume(task::suspend_point);
+    task::suspend_point __TBB_EXPORTED_FUNC internal_current_suspend_point();
+}
+
+template <typename F>
+inline void task::suspend(F f) {
+    internal::internal_suspend((void*)internal::suspend_callback<F>, &f);
+}
+inline void task::resume(suspend_point tag) {
+    internal::internal_resume(tag);
+}
+#endif
+
 //! task that does nothing.  Useful for synchronization.
 /** @ingroup task_scheduling */
 class empty_task: public task {
@@ -972,6 +1039,7 @@ namespace internal {
     template<typename F>
     class function_task : public task {
 #if __TBB_ALLOW_MUTABLE_FUNCTORS
+        // TODO: deprecated behavior, remove
         F my_func;
 #else
         const F my_func;
@@ -1104,4 +1172,7 @@ inline void operator delete( void* task, const tbb::internal::allocate_additiona
     p.free( *static_cast<tbb::task*>(task) );
 }
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_task_H_include_area
+
 #endif /* __TBB_task_H */
index f1fef56..0127c45 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_task_arena_H
 #define __TBB_task_arena_H
 
+#define __TBB_task_arena_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "task.h"
 #include "tbb_exception.h"
 #include "internal/_template_helpers.h"
@@ -149,7 +152,7 @@ public:
 };
 
 #if __TBB_TASK_ISOLATION
-void __TBB_EXPORTED_FUNC isolate_within_arena( delegate_base& d, intptr_t reserved = 0 );
+void __TBB_EXPORTED_FUNC isolate_within_arena( delegate_base& d, intptr_t isolation = 0 );
 
 template<typename R, typename F>
 R isolate_impl(F& f) {
@@ -313,7 +316,7 @@ public:
     //! Does not require the calling thread to join the arena
     template<typename F>
 #if __TBB_CPP11_RVALUE_REF_PRESENT
-    void enqueue( F&& f, priority_t p ) {
+    __TBB_DEPRECATED void enqueue( F&& f, priority_t p ) {
 #if __TBB_PREVIEW_CRITICAL_TASKS
         __TBB_ASSERT(p == priority_low || p == priority_normal || p == priority_high
                      || p == internal::priority_critical, "Invalid priority level value");
@@ -323,7 +326,7 @@ public:
         enqueue_impl(std::forward<F>(f), p);
     }
 #else
-    void enqueue( const F& f, priority_t p ) {
+    __TBB_DEPRECATED void enqueue( const F& f, priority_t p ) {
 #if __TBB_PREVIEW_CRITICAL_TASKS
         __TBB_ASSERT(p == priority_low || p == priority_normal || p == priority_high
                      || p == internal::priority_critical, "Invalid priority level value");
@@ -376,8 +379,8 @@ public:
     }
 };
 
-#if __TBB_TASK_ISOLATION
 namespace this_task_arena {
+#if __TBB_TASK_ISOLATION
     //! Executes a mutable functor in isolation within the current task arena.
     //! Since C++11, the method returns the value returned by functor (prior to C++11 it returns void).
     template<typename F>
@@ -391,18 +394,15 @@ namespace this_task_arena {
     typename internal::return_type_or_void<F>::type isolate(const F& f) {
         return internal::isolate_impl<typename internal::return_type_or_void<F>::type>(f);
     }
-}
 #endif /* __TBB_TASK_ISOLATION */
+} // namespace this_task_arena
 } // namespace interfaceX
 
 using interface7::task_arena;
-#if __TBB_TASK_ISOLATION
+
 namespace this_task_arena {
     using namespace interface7::this_task_arena;
-}
-#endif /* __TBB_TASK_ISOLATION */
 
-namespace this_task_arena {
     //! Returns the index, aka slot number, of the calling thread in its current arena
     inline int current_thread_index() {
         int idx = tbb::task_arena::current_thread_index();
@@ -416,12 +416,10 @@ namespace this_task_arena {
 } // namespace this_task_arena
 
 //! Enqueue task in task_arena
-void task::enqueue( task& t, task_arena& arena
 #if __TBB_TASK_PRIORITY
-        , priority_t p
-#endif
-    ) {
-#if !__TBB_TASK_PRIORITY
+void task::enqueue( task& t, task_arena& arena, priority_t p ) {
+#else
+void task::enqueue( task& t, task_arena& arena ) {
     intptr_t p = 0;
 #endif
     arena.initialize();
@@ -430,4 +428,7 @@ void task::enqueue( task& t, task_arena& arena
 }
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_task_arena_H_include_area
+
 #endif /* __TBB_task_arena_H */
index cafde9f..cb16500 100644 (file)
 #ifndef __TBB_task_group_H
 #define __TBB_task_group_H
 
+#define __TBB_task_group_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "task.h"
 #include "tbb_exception.h"
 #include "internal/_template_helpers.h"
+#if TBB_PREVIEW_ISOLATED_TASK_GROUP && __TBB_TASK_ISOLATION
+#include "task_arena.h"
+#endif
 
 #if __TBB_TASK_GROUP_CONTEXT
 
@@ -31,12 +37,18 @@ namespace internal {
 
 class task_group;
 class structured_task_group;
+#if TBB_PREVIEW_ISOLATED_TASK_GROUP && __TBB_TASK_ISOLATION
+class isolated_task_group;
+#endif
 
 template<typename F>
 class task_handle : internal::no_assign {
     template<typename _F> friend class internal::task_handle_task;
     friend class task_group;
     friend class structured_task_group;
+#if TBB_PREVIEW_ISOLATED_TASK_GROUP && __TBB_TASK_ISOLATION
+    friend class isolated_task_group;
+#endif
 
     static const intptr_t scheduled = 0x1;
 
@@ -92,8 +104,6 @@ protected:
     empty_task* my_root;
     task_group_context my_context;
 
-    task& owner () { return *my_root; }
-
     template<typename F>
     task_group_status internal_run_and_wait( F& f ) {
         __TBB_TRY {
@@ -110,8 +120,8 @@ protected:
     }
 
     template<typename Task, typename F>
-    void internal_run( __TBB_FORWARDING_REF(F) f ) {
-        owner().spawn( *new( owner().allocate_additional_child_of(*my_root) ) Task( internal::forward<F>(f) ));
+    task* prepare_task( __TBB_FORWARDING_REF(F) f ) {
+        return new( task::allocate_additional_child_of(*my_root) ) Task( internal::forward<F>(f) );
     }
 
 public:
@@ -150,7 +160,7 @@ public:
 
     template<typename F>
     void run( task_handle<F>& h ) {
-        internal_run< internal::task_handle_task<F> >( h );
+        task::spawn( *prepare_task< internal::task_handle_task<F> >(h) );
     }
 
     task_group_status wait() {
@@ -195,12 +205,12 @@ public:
 #if __TBB_CPP11_RVALUE_REF_PRESENT
     template<typename F>
     void run( F&& f ) {
-        internal_run< internal::function_task< typename internal::strip<F>::type > >( std::forward< F >(f) );
+        task::spawn( *prepare_task< internal::function_task< typename internal::strip<F>::type > >(std::forward<F>(f)) );
     }
 #else
     template<typename F>
     void run(const F& f) {
-        internal_run<internal::function_task<F> >(f);
+        task::spawn( *prepare_task< internal::function_task<F> >(f) );
     }
 #endif
 
@@ -212,12 +222,12 @@ public:
     // TODO: add task_handle rvalues support
     template<typename F>
     task_group_status run_and_wait( task_handle<F>& h ) {
-      h.mark_scheduled();
-      return internal_run_and_wait< task_handle<F> >( h );
+        h.mark_scheduled();
+        return internal_run_and_wait< task_handle<F> >( h );
     }
 }; // class task_group
 
-class structured_task_group : public internal::task_group_base {
+class __TBB_DEPRECATED structured_task_group : public internal::task_group_base {
 public:
     // TODO: add task_handle rvalues support
     template<typename F>
@@ -233,6 +243,102 @@ public:
     }
 }; // class structured_task_group
 
+#if TBB_PREVIEW_ISOLATED_TASK_GROUP && __TBB_TASK_ISOLATION
+namespace internal {
+    using interface7::internal::delegate_base;
+    using interface7::internal::isolate_within_arena;
+
+    class spawn_delegate : public delegate_base {
+        task* task_to_spawn;
+        void operator()() const __TBB_override {
+            task::spawn(*task_to_spawn);
+        }
+    public:
+        spawn_delegate(task* a_task) : task_to_spawn(a_task) {}
+    };
+
+    class wait_delegate : public delegate_base {
+        void operator()() const __TBB_override {
+            status = tg.wait();
+        }
+    protected:
+        task_group& tg;
+        task_group_status& status;
+    public:
+        wait_delegate(task_group& a_group, task_group_status& tgs)
+            : tg(a_group), status(tgs) {}
+    };
+
+    template<typename F>
+    class run_wait_delegate : public wait_delegate {
+        F& func;
+        void operator()() const __TBB_override {
+            status = tg.run_and_wait( func );
+        }
+    public:
+        run_wait_delegate(task_group& a_group, F& a_func, task_group_status& tgs)
+            : wait_delegate(a_group, tgs), func(a_func) {}
+    };
+} // namespace internal
+
+class isolated_task_group : public task_group {
+    intptr_t this_isolation() {
+        return reinterpret_cast<intptr_t>(this);
+    }
+public:
+    isolated_task_group () : task_group() {}
+
+#if __TBB_CPP11_RVALUE_REF_PRESENT
+    template<typename F>
+    void run( F&& f ) {
+        internal::spawn_delegate sd(
+            prepare_task< internal::function_task< typename internal::strip<F>::type > >(std::forward<F>(f))
+        );
+        internal::isolate_within_arena( sd, this_isolation() );
+    }
+#else
+    template<typename F>
+    void run(const F& f) {
+        internal::spawn_delegate sd( prepare_task< internal::function_task<F> >(f) );
+        internal::isolate_within_arena( sd, this_isolation() );
+    }
+#endif
+
+    template<typename F>
+    task_group_status run_and_wait( const F& f ) {
+        task_group_status result = not_complete;
+        internal::run_wait_delegate< const F > rwd( *this, f, result );
+        internal::isolate_within_arena( rwd, this_isolation() );
+        __TBB_ASSERT( result!=not_complete, "premature exit from wait?" );
+        return result;
+    }
+
+    // TODO: add task_handle rvalues support
+    template<typename F>
+    void run( task_handle<F>& h ) {
+        internal::spawn_delegate sd( prepare_task< internal::task_handle_task<F> >(h) );
+        internal::isolate_within_arena( sd, this_isolation() );
+    }
+
+    template<typename F>
+    task_group_status run_and_wait ( task_handle<F>& h ) {
+        task_group_status result = not_complete;
+        internal::run_wait_delegate< task_handle<F> > rwd( *this, h, result );
+        internal::isolate_within_arena( rwd, this_isolation() );
+        __TBB_ASSERT( result!=not_complete, "premature exit from wait?" );
+        return result;
+    }
+
+    task_group_status wait() {
+        task_group_status result = not_complete;
+        internal::wait_delegate wd( *this, result );
+        internal::isolate_within_arena( wd, this_isolation() );
+        __TBB_ASSERT( result!=not_complete, "premature exit from wait?" );
+        return result;
+    }
+}; // class isolated_task_group
+#endif // TBB_PREVIEW_ISOLATED_TASK_GROUP && __TBB_TASK_ISOLATION
+
 inline
 bool is_current_task_group_canceling() {
     return task::self().is_cancelled();
@@ -254,4 +360,7 @@ task_handle<F> make_task( const F& f ) {
 
 #endif /* __TBB_TASK_GROUP_CONTEXT */
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_task_group_H_include_area
+
 #endif /* __TBB_task_group_H */
index 66a2408..3f9f7b4 100644 (file)
     limitations under the License.
 */
 
+#include "internal/_deprecated_header_message_guard.h"
+
+#if !defined(__TBB_show_deprecation_message_task_scheduler_init_H) && defined(__TBB_show_deprecated_header_message)
+#define  __TBB_show_deprecation_message_task_scheduler_init_H
+#pragma message("TBB Warning: tbb/task_scheduler_init.h is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.")
+#endif
+
+#if defined(__TBB_show_deprecated_header_message)
+#undef __TBB_show_deprecated_header_message
+#endif
+
 #ifndef __TBB_task_scheduler_init_H
 #define __TBB_task_scheduler_init_H
 
+#define __TBB_task_scheduler_init_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "tbb_stddef.h"
 #include "limits.h"
 #if __TBB_SUPPORTS_WORKERS_WAITING_IN_TERMINATE
@@ -49,7 +63,7 @@ namespace internal {
     and will persist until this thread exits. Default concurrency level is defined
     as described in task_scheduler_init::initialize().
     @ingroup task_scheduling */
-class task_scheduler_init: internal::no_copy {
+class __TBB_DEPRECATED_VERBOSE task_scheduler_init: internal::no_copy {
     enum ExceptionPropagationMode {
         propagation_mode_exact = 1u,
         propagation_mode_captured = 2u,
@@ -154,4 +168,7 @@ public:
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_task_scheduler_init_H_include_area
+
 #endif /* __TBB_task_scheduler_init_H */
index 72694af..76a4529 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_task_scheduler_observer_H
 #define __TBB_task_scheduler_observer_H
 
+#define __TBB_task_scheduler_observer_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "atomic.h"
 #if __TBB_ARENA_OBSERVER
 #include "task_arena.h"
@@ -157,4 +160,7 @@ typedef tbb::internal::task_scheduler_observer_v3 task_scheduler_observer;
 
 #endif /* __TBB_SCHEDULER_OBSERVER */
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_task_scheduler_observer_H_include_area
+
 #endif /* __TBB_task_scheduler_observer_H */
index ba4b112..d6c2d7d 100644 (file)
 #ifndef __TBB_tbb_H
 #define __TBB_tbb_H
 
+#if (!defined(TBB_SUPPRESS_DEPRECATED_MESSAGES) || (TBB_SUPPRESS_DEPRECATED_MESSAGES == 0)) && !defined(__TBB_INTERNAL_INCLUDES_DEPRECATION_MESSAGE)
+#pragma message("TBB Warning: tbb.h contains deprecated functionality. For details, please see Deprecated Features appendix in the TBB reference manual.")
+#endif
+
+#define __TBB_tbb_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 /**
     This header bulk-includes declarations or definitions of all the functionality
     provided by TBB (save for tbbmalloc and 3rd party dependent headers).
@@ -84,4 +91,7 @@
 #include "tbb_thread.h"
 #include "tick_count.h"
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_tbb_H_include_area
+
 #endif /* __TBB_tbb_H */
index dbfc9ff..c2f7e6e 100644 (file)
 #define __TBB_CPP11_VARIADIC_TUPLE_PRESENT                  (!_MSC_VER || _MSC_VER >= 1800)
 
 #define __TBB_CPP11_TYPE_PROPERTIES_PRESENT                 (_LIBCPP_VERSION || _MSC_VER >= 1700 || (__TBB_GLIBCXX_VERSION >= 50000 && __GXX_EXPERIMENTAL_CXX0X__))
-#define __TBB_TR1_TYPE_PROPERTIES_IN_STD_PRESENT            (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_GLIBCXX_VERSION >= 40300 || _MSC_VER >= 1600)
 // GCC supported some of type properties since 4.7
 #define __TBB_CPP11_IS_COPY_CONSTRUCTIBLE_PRESENT           (__GXX_EXPERIMENTAL_CXX0X__ && __TBB_GLIBCXX_VERSION >= 40700 || __TBB_CPP11_TYPE_PROPERTIES_PRESENT)
 
@@ -615,6 +614,46 @@ There are four cases that are supported:
     #endif
 #endif
 
+// Intel C++ Compiler starts analyzing usages of the deprecated content at the template
+// instantiation site, which is too late for suppression of the corresponding messages for internal
+// stuff.
+#ifndef TBB_SUPPRESS_DEPRECATED_MESSAGES
+#define TBB_SUPPRESS_DEPRECATED_MESSAGES 1
+#endif
+
+#if !defined(__INTEL_COMPILER) && (!defined(TBB_SUPPRESS_DEPRECATED_MESSAGES) || (TBB_SUPPRESS_DEPRECATED_MESSAGES == 0))
+    #if (__cplusplus >= 201402L)
+        #define __TBB_DEPRECATED [[deprecated]]
+        #define __TBB_DEPRECATED_MSG(msg) [[deprecated(msg)]]
+    #elif _MSC_VER
+        #define __TBB_DEPRECATED __declspec(deprecated)
+        #define __TBB_DEPRECATED_MSG(msg) __declspec(deprecated(msg))
+    #elif (__GNUC__ && __TBB_GCC_VERSION >= 40805) || __clang__
+        #define __TBB_DEPRECATED __attribute__((deprecated))
+        #define __TBB_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
+    #endif
+#endif  // !defined(TBB_SUPPRESS_DEPRECATED_MESSAGES) || (TBB_SUPPRESS_DEPRECATED_MESSAGES == 0)
+
+#if !defined(__TBB_DEPRECATED)
+    #define __TBB_DEPRECATED
+    #define __TBB_DEPRECATED_MSG(msg)
+#elif !defined(__TBB_SUPPRESS_INTERNAL_DEPRECATED_MESSAGES)
+    // Suppress deprecated messages from self
+    #define __TBB_SUPPRESS_INTERNAL_DEPRECATED_MESSAGES 1
+#endif
+
+#if defined(TBB_SUPPRESS_DEPRECATED_MESSAGES) && (TBB_SUPPRESS_DEPRECATED_MESSAGES == 0)
+    #define __TBB_DEPRECATED_VERBOSE __TBB_DEPRECATED
+    #define __TBB_DEPRECATED_VERBOSE_MSG(msg) __TBB_DEPRECATED_MSG(msg)
+#else
+    #define __TBB_DEPRECATED_VERBOSE
+    #define __TBB_DEPRECATED_VERBOSE_MSG(msg)
+#endif // (TBB_SUPPRESS_DEPRECATED_MESSAGES == 0)
+
+#if (!defined(TBB_SUPPRESS_DEPRECATED_MESSAGES) || (TBB_SUPPRESS_DEPRECATED_MESSAGES == 0)) && !__TBB_CPP11_PRESENT
+    #pragma message("TBB Warning: Support for C++98/03 is deprecated. Please use the compiler that supports C++11 features at least.")
+#endif
+
 /** __TBB_WIN8UI_SUPPORT enables support of Windows* Store Apps and limit a possibility to load
     shared libraries at run time only from application container **/
 // TODO: Separate this single macro into two for Windows 8 Store* (win8ui mode) and UWP/UWD modes.
@@ -820,8 +859,17 @@ There are four cases that are supported:
 #define __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES     TBB_PREVIEW_FLOW_GRAPH_FEATURES
 #endif
 
+// This feature works only in combination with critical tasks (__TBB_PREVIEW_CRITICAL_TASKS)
+#ifndef __TBB_PREVIEW_RESUMABLE_TASKS
+#define __TBB_PREVIEW_RESUMABLE_TASKS           ((__TBB_CPF_BUILD || TBB_PREVIEW_RESUMABLE_TASKS) && !__TBB_WIN8UI_SUPPORT && !__ANDROID__ && !__TBB_ipf)
+#endif
+
 #ifndef __TBB_PREVIEW_CRITICAL_TASKS
-#define __TBB_PREVIEW_CRITICAL_TASKS            (__TBB_CPF_BUILD || __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES)
+#define __TBB_PREVIEW_CRITICAL_TASKS            (__TBB_CPF_BUILD || __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES || __TBB_PREVIEW_RESUMABLE_TASKS)
+#endif
+
+#ifndef __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+#define __TBB_PREVIEW_FLOW_GRAPH_NODE_SET       (TBB_PREVIEW_FLOW_GRAPH_FEATURES && __TBB_CPP11_PRESENT && __TBB_FLOW_GRAPH_CPP11_FEATURES)
 #endif
 
 #endif /* __TBB_tbb_config_H */
index 2dcb62b..ce6e092 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_exception_H
 #define __TBB_exception_H
 
+#define __TBB_tbb_exception_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "tbb_stddef.h"
 #include <exception>
 #include <new>    // required for bad_alloc definition, operators new
@@ -34,7 +37,7 @@ public:
 };
 
 //! Exception for PPL locks
-class improper_lock : public std::exception {
+class __TBB_DEPRECATED improper_lock : public std::exception {
 public:
     const char* what() const throw() __TBB_override;
 };
@@ -131,7 +134,7 @@ namespace tbb {
 
     TBB provides two implementations of this interface: tbb::captured_exception and
     template class tbb::movable_exception. See their declarations for more info. **/
-class tbb_exception : public std::exception
+class __TBB_DEPRECATED tbb_exception : public std::exception
 {
     /** No operator new is provided because the TBB usage model assumes dynamic
         creation of the TBB exception objects only by means of applying move()
@@ -185,7 +188,7 @@ public:
     algorithm ) if an unhandled exception was intercepted during the algorithm execution in one
     of the workers.
     \sa tbb::tbb_exception **/
-class captured_exception : public tbb_exception
+class __TBB_DEPRECATED captured_exception : public tbb_exception
 {
 public:
     captured_exception( const captured_exception& src )
@@ -241,7 +244,7 @@ private:
     and delivered to the root thread ().
     \sa tbb::tbb_exception **/
 template<typename ExceptionData>
-class movable_exception : public tbb_exception
+class __TBB_DEPRECATED movable_exception : public tbb_exception
 {
     typedef movable_exception<ExceptionData> self_type;
 
@@ -353,4 +356,7 @@ private:
 
 #endif /* __TBB_TASK_GROUP_CONTEXT */
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_tbb_exception_H_include_area
+
 #endif /* __TBB_exception_H */
index 2166580..9536e61 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef __TBB_profiling_H
 #define __TBB_profiling_H
 
+#define __TBB_tbb_profiling_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 namespace tbb {
     namespace internal {
 
@@ -118,6 +121,7 @@ namespace tbb {
 #endif /* no tools support */
 
 #include "atomic.h"
+
 // Need these to work regardless of tools support
 namespace tbb {
     namespace internal {
@@ -136,6 +140,8 @@ namespace tbb {
                                                          void *parent, unsigned long long parent_extra, string_index name_index );
         void __TBB_EXPORTED_FUNC itt_metadata_str_add_v7( itt_domain_enum domain, void *addr, unsigned long long addr_extra,
                                                           string_index key, const char *value );
+        void __TBB_EXPORTED_FUNC itt_metadata_ptr_add_v11( itt_domain_enum domain, void *addr, unsigned long long addr_extra,
+                                                           string_index key, void* value );
         void __TBB_EXPORTED_FUNC itt_relation_add_v7( itt_domain_enum domain, void *addr0, unsigned long long addr0_extra,
                                                       itt_relation relation, void *addr1, unsigned long long addr1_extra );
         void __TBB_EXPORTED_FUNC itt_task_begin_v7( itt_domain_enum domain, void *task, unsigned long long task_extra,
@@ -237,6 +243,11 @@ namespace tbb {
                                           string_index key, const char *value ) {
             itt_metadata_str_add_v7( domain, addr, addr_extra, key, value );
         }
+        
+        inline void register_node_addr(itt_domain_enum domain, void *addr, unsigned long long addr_extra,
+            string_index key, void *value) {
+            itt_metadata_ptr_add_v11(domain, addr, addr_extra, key, value);
+        }
 
         inline void itt_relation_add( itt_domain_enum domain, void *addr0, unsigned long long addr0_extra,
                                       itt_relation relation, void *addr1, unsigned long long addr1_extra ) {
@@ -261,6 +272,7 @@ namespace tbb {
             itt_region_end_v9( domain, region, region_extra );
         }
 #else
+        inline void register_node_addr( itt_domain_enum /*domain*/, void* /*addr*/, unsigned long long /*addr_extra*/, string_index /*key*/, void* /*value*/ ) {}
         inline void call_itt_notify(notify_type /*t*/, void* /*ptr*/) {}
 
         inline void itt_make_task_group( itt_domain_enum /*domain*/, void* /*group*/, unsigned long long /*group_extra*/,
@@ -337,4 +349,7 @@ using interface10::event;
 } // namespace tbb
 #endif // TBB_PREVIEW_FLOW_GRAPH_TRACE
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_tbb_profiling_H_include_area
+
 #endif /* __TBB_profiling_H */
index f9aa90b..86cb42f 100644 (file)
 
 // Marketing-driven product version
 #define TBB_VERSION_MAJOR 2019
-#define TBB_VERSION_MINOR 0
+#define TBB_VERSION_MINOR 9
 
 // Engineering-focused interface version
-#define TBB_INTERFACE_VERSION 11008
+#define TBB_INTERFACE_VERSION 11009
 #define TBB_INTERFACE_VERSION_MAJOR TBB_INTERFACE_VERSION/1000
 
 // The oldest major interface version still supported
@@ -316,6 +316,25 @@ inline T punned_cast( U* ptr ) {
     return reinterpret_cast<T>(x);
 }
 
+#if __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT
+
+//! Base class for types that should not be assigned.
+class no_assign {
+public:
+    void operator=( const no_assign& ) = delete;
+    no_assign( const no_assign& ) = default;
+    no_assign() = default;
+};
+
+//! Base class for types that should not be copied or assigned.
+class no_copy: no_assign {
+public:
+    no_copy( const no_copy& ) = delete;
+    no_copy() = default;
+};
+
+#else /*__TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT*/
+
 //! Base class for types that should not be assigned.
 class no_assign {
     // Deny assignment
@@ -336,6 +355,8 @@ public:
     no_copy() {}
 };
 
+#endif /*__TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT*/
+
 #if TBB_DEPRECATED_MUTEX_COPYING
 class mutex_copy_deprecated_and_disabled {};
 #else
index 52b96e4..4558411 100644 (file)
     limitations under the License.
 */
 
+#include "internal/_deprecated_header_message_guard.h"
+
+#if !defined(__TBB_show_deprecation_message_tbb_thread_H) && defined(__TBB_show_deprecated_header_message)
+#define  __TBB_show_deprecation_message_tbb_thread_H
+#pragma message("TBB Warning: tbb/tbb_thread.h is deprecated. For details, please see Deprecated Features appendix in the TBB reference manual.")
+#endif
+
+#if defined(__TBB_show_deprecated_header_message)
+#undef __TBB_show_deprecated_header_message
+#endif
+
 #ifndef __TBB_tbb_thread_H
 #define __TBB_tbb_thread_H
 
+#define __TBB_tbb_thread_H_include_area
+#include "internal/_warning_suppress_enable_notice.h"
+
 #include "tbb_stddef.h"
 
 #if _WIN32||_WIN64
@@ -293,7 +307,7 @@ namespace internal {
 } // namespace internal;
 
 //! Users reference thread class by name tbb_thread
-typedef internal::tbb_thread_v3 tbb_thread;
+__TBB_DEPRECATED_VERBOSE_MSG("tbb::thread is deprecated, use std::thread") typedef internal::tbb_thread_v3 tbb_thread;
 
 using internal::operator==;
 using internal::operator!=;
@@ -314,15 +328,18 @@ inline void swap( internal::tbb_thread_v3& t1, internal::tbb_thread_v3& t2 )  __
 }
 
 namespace this_tbb_thread {
-    inline tbb_thread::id get_id() { return internal::thread_get_id_v3(); }
+    __TBB_DEPRECATED_VERBOSE inline tbb_thread::id get_id() { return internal::thread_get_id_v3(); }
     //! Offers the operating system the opportunity to schedule another thread.
-    inline void yield() { internal::thread_yield_v3(); }
+    __TBB_DEPRECATED_VERBOSE inline void yield() { internal::thread_yield_v3(); }
     //! The current thread blocks at least until the time specified.
-    inline void sleep(const tick_count::interval_t &i) {
+    __TBB_DEPRECATED_VERBOSE inline void sleep(const tick_count::interval_t &i) {
         internal::thread_sleep_v3(i);
     }
 }  // namespace this_tbb_thread
 
 } // namespace tbb
 
+#include "internal/_warning_suppress_disable_notice.h"
+#undef __TBB_tbb_thread_H_include_area
+
 #endif /* __TBB_tbb_thread_H */
index 7792f65..a63d69f 100644 (file)
@@ -69,7 +69,7 @@ _tbb = Extension("tbb._api", ["tbb/api.i"],
         libraries   =(['tbb'] if not use_compiler_tbb else []) +
                      (['irml'] if platform.system() == "Linux" else []),   # TODO: why do we need this?
         library_dirs=[ rundir,                                              # for custom-builds
-                       os.path.join(tbb_root, 'lib', 'intel64', 'gcc4.4'),  # for Linux
+                       os.path.join(tbb_root, 'lib', 'intel64', 'gcc4.8'),  # for Linux
                        os.path.join(tbb_root, 'lib'),                       # for MacOS
                        os.path.join(tbb_root, 'lib', 'intel64', 'vc_mt'),   # for Windows
                      ] if not use_compiler_tbb else [],
index a76ae1c..d27eb9d 100644 (file)
@@ -50,13 +50,13 @@ public:
     //! Prefix on a page
     struct page {
         page* next;
-        uintptr_t mask; 
+        uintptr_t mask;
     };
 
 protected:
     //! Capacity of the queue
     ptrdiff_t my_capacity;
-   
+
     //! Always a power of 2
     size_t items_per_page;
 
@@ -90,7 +90,7 @@ protected:
 
 //! Type-independent portion of concurrent_queue_iterator.
 /** @ingroup containers */
-class concurrent_queue_iterator_base : no_assign{
+class concurrent_queue_iterator_base : no_assign {
     //! concurrent_queue over which we are iterating.
     /** NULL if one past last element in queue. */
     concurrent_queue_iterator_rep* my_rep;
@@ -105,10 +105,10 @@ protected:
     mutable void* my_item;
 
     //! Default constructor
-    __TBB_EXPORTED_METHOD concurrent_queue_iterator_base() : my_rep(NULL), my_item(NULL) {}
+    __TBB_EXPORTED_METHOD concurrent_queue_iterator_base() : no_assign(), my_rep(NULL), my_item(NULL) {}
 
     //! Copy constructor
-    concurrent_queue_iterator_base( const concurrent_queue_iterator_base& i ) : my_rep(NULL), my_item(NULL) {
+    concurrent_queue_iterator_base( const concurrent_queue_iterator_base& i ) : no_assign(), my_rep(NULL), my_item(NULL) {
         assign(i);
     }
 
@@ -135,7 +135,7 @@ class concurrent_queue_iterator: public concurrent_queue_iterator_base {
     friend class ::tbb::concurrent_queue;
 #else
 public: // workaround for MSVC
-#endif 
+#endif
     //! Construct iterator pointing to head of queue.
     concurrent_queue_iterator( const concurrent_queue_base& queue ) :
         concurrent_queue_iterator_base(queue)
@@ -144,7 +144,7 @@ public: // workaround for MSVC
 public:
     concurrent_queue_iterator() {}
 
-    /** If Value==Container::value_type, then this routine is the copy constructor. 
+    /** If Value==Container::value_type, then this routine is the copy constructor.
         If Value==const Container::value_type, then this routine is a conversion constructor. */
     concurrent_queue_iterator( const concurrent_queue_iterator<Container,typename Container::value_type>& other ) :
         concurrent_queue_iterator_base(other)
@@ -156,7 +156,7 @@ public:
         return *this;
     }
 
-    //! Reference to current item 
+    //! Reference to current item
     Value& operator*() const {
         return *static_cast<Value*>(my_item);
     }
@@ -198,12 +198,12 @@ template<typename T>
 class concurrent_queue: public internal::concurrent_queue_base {
     template<typename Container, typename Value> friend class internal::concurrent_queue_iterator;
 
-    //! Class used to ensure exception-safety of method "pop" 
+    //! Class used to ensure exception-safety of method "pop"
     class destroyer {
         T& my_value;
     public:
         destroyer( T& value ) : my_value(value) {}
-        ~destroyer() {my_value.~T();}          
+        ~destroyer() {my_value.~T();}
     };
 
     T& get_ref( page& pg, size_t index ) {
@@ -240,7 +240,7 @@ public:
     typedef std::ptrdiff_t difference_type;
 
     //! Construct empty queue
-    concurrent_queue() : 
+    concurrent_queue() :
         concurrent_queue_base( sizeof(T) )
     {
     }
@@ -274,8 +274,8 @@ public:
     }
 
     //! Return number of pushes minus number of pops.
-    /** Note that the result can be negative if there are pops waiting for the 
-        corresponding pushes.  The result can also exceed capacity() if there 
+    /** Note that the result can be negative if there are pops waiting for the
+        corresponding pushes.  The result can also exceed capacity() if there
         are push operations in flight. */
     size_type size() const {return internal_size();}
 
@@ -304,8 +304,8 @@ public:
     iterator end() {return iterator();}
     const_iterator begin() const {return const_iterator(*this);}
     const_iterator end() const {return const_iterator();}
-    
-}; 
+
+};
 
 template<typename T>
 concurrent_queue<T>::~concurrent_queue() {
diff --git a/src/perf/harness_perf.h b/src/perf/harness_perf.h
new file mode 100644 (file)
index 0000000..d19d177
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+    Copyright (c) 2005-2019 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.
+*/
+
+#ifndef __TBB_HARNESS_PERF
+#define __TBB_HARNESS_PERF
+
+#include <iterator>
+#include <algorithm>
+
+namespace harness_perf {
+
+template<typename InputIterator>
+typename InputIterator::value_type median(InputIterator first, InputIterator last) {
+    std::sort(first, last);
+    typename InputIterator::difference_type distance = std::distance(first, last);
+    std::advance(first, distance / 2 - 1);
+    if (distance % 2 == 0)
+        return typename InputIterator::value_type((*first + *(++first)) / 2);
+    else
+        return typename InputIterator::value_type(*first);
+}
+
+} // namespace harness_perf
+
+#endif // !__TBB_HARNESS_PERF
+
diff --git a/src/perf/time_resumable_tasks.cpp b/src/perf/time_resumable_tasks.cpp
new file mode 100644 (file)
index 0000000..f3a6933
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+    Copyright (c) 2005-2019 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.
+*/
+
+#define TBB_PREVIEW_RESUMABLE_TASKS 1
+#include "tbb/tbb_config.h"
+
+#include "tbb/task.h"
+#include "tbb/task_group.h"
+#include "tbb/task_scheduler_init.h"
+#include "tbb/tick_count.h"
+
+#include "tbb/parallel_for.h"
+
+#include <vector>
+#include <stack>
+#include <functional>
+#include <numeric>
+#include <algorithm>
+
+/************************************************************************/
+/* SETTINGS                                                             */
+/************************************************************************/
+
+const int DEF_BENCH_RUNS = 1000;
+
+/************************************************************************/
+/* HELPERS                                                              */
+/************************************************************************/
+
+#include "harness_perf.h" // harness_perf::median
+
+template<typename T>
+T get_median(std::vector<T>& times) {
+    return harness_perf::median(times.begin(), times.end());
+}
+
+/************************************************************************/
+/* SERIAL BENCHMARKS                                                    */
+/************************************************************************/
+
+//! Allocate COROUTINES_NUM fibers in a row (suspend) in a recursive manner
+//! and then swith back (resume) unwinding the ctx_stack.
+void BenchCoroutinesAllocation() {
+    tbb::task_scheduler_init init(1);
+
+    const int COROUTINES_NUM = 100;
+    std::stack<tbb::task::suspend_point> ctx_stack;
+    tbb::task_group tg;
+
+    std::function<void(int)> recursive_f;
+    recursive_f = [=, &ctx_stack, &tg, &recursive_f](int i) {
+        if (i < COROUTINES_NUM) {
+            tg.run([&recursive_f, i]() {
+                recursive_f(i + 1);
+            });
+            tbb::task::suspend([&ctx_stack](tbb::task::suspend_point ctx) {
+                ctx_stack.push(ctx);
+            });
+        }
+        if (ctx_stack.size() != 0) {
+            tbb::task::suspend_point ctx = ctx_stack.top(); ctx_stack.pop();
+            tbb::task::resume(ctx);
+        }
+    };
+    tg.run([=, &recursive_f]() {
+        std::vector<double> times;
+        for (int i = 0; i < DEF_BENCH_RUNS; i++) {
+            tbb::tick_count tick = tbb::tick_count::now();
+            recursive_f(1);
+            double interval = (tbb::tick_count::now() - tick).seconds() * 1e6;
+            times.push_back(interval);
+        }
+        // COROUTINES_NUM suspend and resume operations in each run
+        double median = get_median(times) / double(COROUTINES_NUM);
+        printf("Test 1 (Coroutines alloc/dealloc): Median time (microseconds): %.4f\n", median);
+    });
+    tg.wait();
+}
+
+//! Create a task, which suspends and resumes intself, thus reusing once created coroutine
+void BenchReusage() {
+    tbb::task_scheduler_init init(1);
+    tbb::task_group tg;
+
+    std::vector<double> times;
+    tg.run([&times]() {
+        for (int i = 0; i < DEF_BENCH_RUNS * 10; i++) {
+            tbb::tick_count tick = tbb::tick_count::now();
+            tbb::task::suspend([](tbb::task::suspend_point ctx) {
+                tbb::task::resume(ctx);
+            });
+            double diff = (tbb::tick_count::now() - tick).seconds() * 1e6;
+            times.push_back(diff);
+        }
+    });
+    tg.wait();
+    double median = get_median(times);
+    printf("Test 2 (Coroutine reusage): Median time (microseconds): %.4f\n", median);
+}
+
+//! Create two tasks and switch between them (suspend current and resume previously suspended coroutine)
+//! Measure an average time of the context switch
+void BenchContextSwitch() {
+    tbb::task_scheduler_init init(1);
+    tbb::task_group tg;
+    const int N = 10000; // number of switches
+    const int tasks_num = 2;
+
+    std::vector<double> times;
+    for (int i = 0; i < 100; ++i) {
+        int switch_counter = N;
+        tbb::task::suspend_point current_ctx = NULL;
+
+        tbb::tick_count tick = tbb::tick_count::now();
+        for (int j = 0; j < tasks_num; ++j) {
+            tg.run([=, &switch_counter, &current_ctx]() {
+                while (switch_counter-- > 0) {
+                    tbb::task::suspend([=, &switch_counter, &current_ctx](tbb::task::suspend_point ctx) {
+                        if (switch_counter == N - 1) {
+                            current_ctx = ctx;
+                        } else {
+                            tbb::task::suspend_point ctx_to_resume = current_ctx;
+                            current_ctx = ctx;
+                            tbb::task::resume(ctx_to_resume);
+                        }
+                    });
+                }
+                if (switch_counter == -1) {
+                    tbb::task::resume(current_ctx);
+                }
+            });
+        }
+        tg.wait();
+        // To get an average context switch time divide the bench time by the number of context switches
+        double diff = ((tbb::tick_count::now() - tick).seconds() / double(N)) * 1e6;
+        times.push_back(diff);
+    }
+    printf("Test 3 (Context Switch): Median time (microseconds): %.4f\n", get_median(times));
+}
+
+/************************************************************************/
+/* PARALLEL BENCHMARKS                                                  */
+/************************************************************************/
+
+//! Strong scaling benchmark with predefined number of iterations (N), each parallel_for task
+//! suspends and resumes itself with a predefined busy-waiting iterations (work size).
+//! Reports 3 numbers: serial, half of the machine, and full available concurrency
+template <bool UseResumableTasks>
+void ScalabilityBenchmark(const size_t work_size) {
+    const int N = 1000;
+    const int NUM_THREADS = tbb::task_scheduler_init::default_num_threads();
+    const int STEP_RATIO = 2;
+
+    // Count 3 scalability metrics: the serial, half and full machine concurrency
+    for (int i = 0; i <= NUM_THREADS; i += (NUM_THREADS / STEP_RATIO)) {
+        const int concurrency = (i == 0) ? 1 : i; // just to make step loop nice looking
+        tbb::task_scheduler_init init(concurrency);
+        std::vector<double> times;
+        for (int j = 0; j < 100; j++) {
+            tbb::tick_count tick = tbb::tick_count::now();
+            tbb::parallel_for(0, N, [&work_size](const int /*j*/) {
+                if (UseResumableTasks) {
+                    tbb::task::suspend([](tbb::task::suspend_point ctx) {
+                        tbb::task::resume(ctx);
+                    });
+                }
+                for (volatile size_t k = 0; k < work_size; ++k);
+            }, tbb::simple_partitioner());
+            double diff = (tbb::tick_count::now() - tick).seconds() * 1e3;
+            times.push_back(diff);
+        }
+        printf("Test 4 (Scalability): Work Size: %zu, With RT-feature: %s, Concurrency: %d, Time (milliseconds): %.4f\n",
+                work_size, (UseResumableTasks ? "true" : "false"), concurrency, get_median(times));
+    }
+}
+
+/************************************************************************/
+/* NATIVE IMPLEMENTATION                                                */
+/************************************************************************/
+
+// Dependencies section for co_context.h
+
+#if _WIN32
+#include <windows.h> // GetSystemInfo
+#else
+#include <unistd.h> // sysconf(_SC_PAGESIZE)
+#endif
+
+namespace tbb {
+namespace internal {
+//! System dependent impl
+inline size_t GetDefaultSystemPageSize() {
+#if _WIN32
+    SYSTEM_INFO si;
+    GetSystemInfo(&si);
+    return si.dwPageSize;
+#else
+    return sysconf(_SC_PAGESIZE);
+#endif
+}
+class governor {
+    //! Caches the size of OS regular memory page
+    static size_t DefaultPageSize;
+public:
+    //! Staic accessor for OS regular memory page size
+    static size_t default_page_size () {
+        return DefaultPageSize ? DefaultPageSize : DefaultPageSize = GetDefaultSystemPageSize();
+    }
+};
+size_t governor::DefaultPageSize;
+} // namespace internal
+} // namespace tbb
+
+// No-op versions of __TBB_ASSERT/EX for co_context.h header
+#define __TBB_ASSERT(predicate,comment) ((void)0)
+#define __TBB_ASSERT_EX(predicate,comment) ((void)(1 && (predicate)))
+
+// TBB coroutines implementation
+// Disable governor header to remove the dependency
+#define _TBB_governor_H
+#include "../tbb/co_context.h"
+using namespace tbb::internal;
+#undef _TBB_governor_H
+
+#define HARNESS_CUSTOM_MAIN 1
+#include "../test/harness.h" // NativeParallelFor
+
+namespace tbb {
+namespace internal {
+// Our native coroutine function
+#if _WIN32
+/* [[noreturn]] */ inline void __stdcall co_local_wait_for_all(void* arg) {
+#else
+/* [[noreturn]] */ inline void co_local_wait_for_all(void* arg) {
+#endif
+    coroutine_type next = *static_cast<coroutine_type*>(arg);
+    coroutine_type current; current_coroutine(current);
+    swap_coroutine(current, next);
+}
+} // namespace internal
+} // namespace tbb
+
+// The same scalability benchmark as for TBB, but written with native OS fibers implementation
+void BenchNativeImpl(const size_t work_size) {
+    const int N = 1000;
+    const int NUM_THREADS = tbb::task_scheduler_init::default_num_threads();
+    const int STEP_RATIO = 2;
+    const size_t STACK_SIZE = 4 * 1024 * 1024; // Just like default TBB worker thread stack size
+
+    // Count 3 scalability metrics: the serial, half and full machine concurrency
+    for (int i = 0; i <= NUM_THREADS; i += (NUM_THREADS / STEP_RATIO)) {
+        const int concurrency = (i == 0) ? 1 : i; // just to make step loop nice looking
+        const int sub_range = N / concurrency;
+        std::vector<double> times;
+        for (int r = 0; r < 100; r++) {
+            tbb::tick_count tick = tbb::tick_count::now();
+            NativeParallelFor(concurrency, [=, &work_size, &sub_range](int /*idx*/) {
+                // Each iteration of sub-range emulates a single TBB task
+                for (int j = 0; j < sub_range; j++) {
+                    coroutine_type co_next;
+                    coroutine_type co_current; current_coroutine(co_current);
+                    create_coroutine(co_next, STACK_SIZE, &co_current);
+                    swap_coroutine(co_current, co_next);
+
+                    // Busy-wait for a while emulating some work
+                    for (volatile size_t k = 0; k < work_size; ++k);
+                    destroy_coroutine(co_next);
+                }
+            });
+            double diff = (tbb::tick_count::now() - tick).seconds() * 1e3;
+            times.push_back(diff);
+        }
+        printf("Test 5 (Native Implementation): Work size: %zu, Concurrency: %d, Time (milliseconds): %.4f\n",
+                work_size, concurrency, get_median(times));
+    }
+}
+
+/************************************************************************/
+/* MAIN DRIVER                                                          */
+/************************************************************************/
+
+int main() {
+    // Serial microbenchmarks
+    BenchCoroutinesAllocation();
+    BenchReusage();
+    BenchContextSwitch();
+
+    // Scalability benchmarks
+    // Big work size + no resumable tasks feature (false)
+    ScalabilityBenchmark<false>(100000);
+    // Big work size + resumable tasks feature (true)
+    ScalabilityBenchmark<true>(100000);
+    // Small work size + no resumable tasks feature (false)
+    ScalabilityBenchmark<false>(1000);
+    // Small work size + resumable tasks feature (true)
+    ScalabilityBenchmark<true>(1000);
+    // No any work + just resumable tasks feature (true)
+    ScalabilityBenchmark<true>(0);
+
+    // Native implmentation
+    // Big work size
+    BenchNativeImpl(100000);
+    // Small work size
+    BenchNativeImpl(1000);
+    // Just coroutines/fibers switching
+    BenchNativeImpl(0);
+
+    return 0;
+}
+
index 5db496f..9a80029 100644 (file)
@@ -49,7 +49,7 @@
 #include <concrtrm.h>
 using namespace Concurrency;
 #include <vector>
-#include <hash_map>
+#include <unordered_map>
 #define __RML_REMOVE_VIRTUAL_PROCESSORS_DISABLED 0
 #endif /* RML_USE_WCRM */
 
@@ -870,7 +870,7 @@ skip:
 
 class thread_map : no_copy {
     friend class omp_connection_v2;
-    typedef ::std::hash_map<uintptr_t,server_thread*> hash_map_type;
+    typedef ::std::unordered_map<uintptr_t,server_thread*> unordered_map_type;
     size_t my_min_stack_size;
     size_t my_unrealized_threads;
     ::rml::client& my_client;
@@ -880,7 +880,7 @@ class thread_map : no_copy {
     ref_count my_server_ref_count;
     ref_count my_client_ref_count;
     // FIXME: pad this?
-    hash_map_type my_map;
+    unordered_map_type my_map;
     bool shutdown_in_progress;
     std::vector<IExecutionResource*> original_exec_resources;
     tbb::cache_aligned_allocator<padded<tbb_server_thread> > my_tbb_allocator;
@@ -918,7 +918,7 @@ public:
             my_scavenger_allocator.deallocate(static_cast<padded<thread_scavenger_thread>*>(tst),1);
         }
         // deallocate thread contexts
-        for( hash_map_type::const_iterator hi=my_map.begin(); hi!=my_map.end(); ++hi ) {
+        for( unordered_map_type::const_iterator hi=my_map.begin(); hi!=my_map.end(); ++hi ) {
             server_thread* thr = hi->second;
             if( thr->tbb_thread ) {
                 while( ((tbb_server_thread*)thr)->activation_count>1 )
@@ -939,9 +939,9 @@ public:
             __TBB_ASSERT( !my_scheduler, NULL );
         }
     }
-    typedef hash_map_type::key_type key_type;
-    typedef hash_map_type::value_type value_type;
-    typedef hash_map_type::iterator iterator;
+    typedef unordered_map_type::key_type key_type;
+    typedef unordered_map_type::value_type value_type;
+    typedef unordered_map_type::iterator iterator;
     iterator begin() {return my_map.begin();}
     iterator end() {return my_map.end();}
     iterator find( key_type k ) {return my_map.find( k );}
@@ -2352,8 +2352,8 @@ bool tbb_server_thread::switch_out() {
             // the thread's state should be either ts_idle or ts_done.
             while( is_removed() )
                 __TBB_Yield();
-            thread_state_t s = read_state();
-            __TBB_ASSERT( s==ts_idle || s==ts_done, NULL );
+            thread_state_t state = read_state();
+            __TBB_ASSERT( state==ts_idle || state==ts_done, NULL );
         }
 #endif
         __TBB_ASSERT( my_state==ts_asleep||my_state==ts_idle, NULL );
@@ -2708,7 +2708,7 @@ void thread_map::mark_virtual_processors_as_lent( IVirtualProcessorRoot** vproot
         iterator i = my_map.find( (key_type) vproots[c] );
         if( i==end ) {
             // The vproc has not been added to the map in create_oversubscribers()
-            my_map.insert( hash_map_type::value_type( (key_type) vproots[c], (server_thread*)1 ) );
+            my_map.insert( unordered_map_type::value_type( (key_type) vproots[c], (server_thread*)1 ) );
         } else {
             server_thread* thr = (*i).second;
             if( ((uintptr_t)thr)&~(uintptr_t)1 ) {
@@ -2726,8 +2726,8 @@ void thread_map::create_oversubscribers( unsigned n, std::vector<server_thread*>
         curr_exec_rsc = original_exec_resources; // copy construct
     }
     typedef std::vector<IExecutionResource*>::iterator iterator_er;
-    typedef ::std::vector<std::pair<hash_map_type::key_type, hash_map_type::mapped_type> > hash_val_vector_t;
-    hash_val_vector_t v_vec(n);
+    typedef ::std::vector<std::pair<unordered_map_type::key_type, unordered_map_type::mapped_type> > map_val_vector_t;
+    map_val_vector_t v_vec(n);
     iterator_er begin = curr_exec_rsc.begin();
     iterator_er end   = curr_exec_rsc.end();
     iterator_er i = begin;
@@ -2735,7 +2735,7 @@ void thread_map::create_oversubscribers( unsigned n, std::vector<server_thread*>
         IVirtualProcessorRoot* vpr = my_scheduler_proxy->CreateOversubscriber( *i );
         omp_server_thread* t = new ( my_omp_allocator.allocate(1) ) omp_server_thread( true, my_scheduler, (IExecutionResource*)vpr, &conn, *this, my_client );
         thr_vec[c] = t;
-        v_vec[c] = hash_map_type::value_type( (key_type) vpr, t );
+        v_vec[c] = unordered_map_type::value_type( (key_type) vpr, t );
         if( ++i==end ) i = begin;
     }
 
@@ -2744,17 +2744,17 @@ void thread_map::create_oversubscribers( unsigned n, std::vector<server_thread*>
 
         if( is_closing() ) return;
 
-        iterator end = my_map.end();
+        iterator map_end = my_map.end();
         unsigned c = 0;
-        for( hash_val_vector_t::iterator vi=v_vec.begin(); vi!=v_vec.end(); ++vi, ++c ) {
-            iterator i = my_map.find( (key_type) (*vi).first );
-            if( i==end ) {
+        for( map_val_vector_t::iterator vi=v_vec.begin(); vi!=v_vec.end(); ++vi, ++c ) {
+            iterator j = my_map.find( (key_type) (*vi).first );
+            if( j==map_end ) {
                 my_map.insert( *vi );
             } else {
                 // the vproc has not been added to the map in mark_virtual_processors_as_returned();
-                uintptr_t lent = (uintptr_t) (*i).second;
+                uintptr_t lent = (uintptr_t) (*j).second;
                 __TBB_ASSERT( lent<=1, "vproc map entry added incorrectly?");
-                (*i).second = thr_vec[c];
+                (*j).second = thr_vec[c];
                 if( lent )
                     ((omp_server_thread*)thr_vec[c])->set_lent();
                 else
@@ -2837,7 +2837,7 @@ void thread_map::mark_virtual_processors_as_returned( IVirtualProcessorRoot** vp
             iterator i = my_map.find( (key_type) vprocs[c] );
             if( i==end ) {
                 // the vproc has not been added to the map in create_oversubscribers()
-                my_map.insert( hash_map_type::value_type( (key_type) vprocs[c], static_cast<server_thread*>(0) ) );
+                my_map.insert( unordered_map_type::value_type( (key_type) vprocs[c], static_cast<server_thread*>(0) ) );
             } else {
                 omp_server_thread* thr = (omp_server_thread*) (*i).second;
                 if( ((uintptr_t)thr)&~(uintptr_t)1 ) {
index 28717e7..e192256 100644 (file)
@@ -139,11 +139,7 @@ void arena::process( generic_scheduler& s ) {
         __TBB_ASSERT( s.my_arena_slot->task_pool == EmptyTaskPool, "Empty task pool is not marked appropriately" );
         // This check prevents relinquishing more than necessary workers because
         // of the non-atomicity of the decision making procedure
-        if ( num_workers_active() > my_num_workers_allotted
-#if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-             || recall_by_mandatory_request()
-#endif
-            )
+        if ( is_recall_requested() )
             break;
         // Try to steal a task.
         // Passing reference count is technically unnecessary in this context,
@@ -204,12 +200,18 @@ arena::arena ( market& m, unsigned num_slots, unsigned num_reserved_slots ) {
 #if __TBB_ARENA_OBSERVER
     my_observers.my_arena = this;
 #endif
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    my_co_cache.init(4 * num_slots);
+#endif
     __TBB_ASSERT ( my_max_num_workers <= my_num_slots, NULL );
     // Construct slots. Mark internal synchronization elements for the tools.
     for( unsigned i = 0; i < my_num_slots; ++i ) {
         __TBB_ASSERT( !my_slots[i].my_scheduler && !my_slots[i].task_pool, NULL );
         __TBB_ASSERT( !my_slots[i].task_pool_ptr, NULL );
         __TBB_ASSERT( !my_slots[i].my_task_pool_size, NULL );
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+        __TBB_ASSERT( !my_slots[i].my_scheduler_is_recalled, NULL );
+#endif
         ITT_SYNC_CREATE(my_slots + i, SyncType_Scheduler, SyncObj_WorkerTaskPool);
         mailbox(i+1).construct();
         ITT_SYNC_CREATE(&mailbox(i+1), SyncType_Scheduler, SyncObj_Mailbox);
@@ -228,7 +230,8 @@ arena::arena ( market& m, unsigned num_slots, unsigned num_reserved_slots ) {
     ITT_SYNC_CREATE(&my_critical_task_stream, SyncType_Scheduler, SyncObj_CriticalTaskStream);
 #endif
 #if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-    my_concurrency_mode = cm_normal;
+    my_local_concurrency_mode = false;
+    my_global_concurrency_mode = false;
 #endif
 #if !__TBB_FP_CONTEXT
     my_cpu_ctl_env.get_env();
@@ -252,7 +255,7 @@ void arena::free_arena () {
     __TBB_ASSERT( !my_num_workers_requested && !my_num_workers_allotted, "Dying arena requests workers" );
     __TBB_ASSERT( my_pool_state == SNAPSHOT_EMPTY || !my_max_num_workers, "Inconsistent state of a dying arena" );
 #if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-    __TBB_ASSERT( my_concurrency_mode != cm_enforced_global, NULL );
+    __TBB_ASSERT( !my_global_concurrency_mode, NULL );
 #endif
 #if !__TBB_STATISTICS_EARLY_DUMP
     GATHER_STATISTIC( dump_arena_statistics() );
@@ -271,6 +274,10 @@ void arena::free_arena () {
         drained += mailbox(i+1).drain();
     }
     __TBB_ASSERT( my_task_stream.drain()==0, "Not all enqueued tasks were executed");
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    // Cleanup coroutines/schedulers cache
+    my_co_cache.cleanup();
+#endif
 #if __TBB_PREVIEW_CRITICAL_TASKS
     __TBB_ASSERT( my_critical_task_stream.drain()==0, "Not all critical tasks were executed");
 #endif
@@ -507,17 +514,9 @@ bool arena::is_out_of_work() {
                                 // to avoid race with advertise_new_work.
                                 int current_demand = (int)my_max_num_workers;
                                 if( my_pool_state.compare_and_swap( SNAPSHOT_EMPTY, busy )==busy ) {
-#if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-                                    if( my_concurrency_mode==cm_enforced_global  ) {
-                                        // adjust_demand() called inside, if needed
-                                        my_market->mandatory_concurrency_disable( this );
-                                    } else
-#endif /* __TBB_ENQUEUE_ENFORCED_CONCURRENCY */
-                                    {
-                                        // This thread transitioned pool to empty state, and thus is
-                                        // responsible for telling the market that there is no work to do.
-                                        my_market->adjust_demand( *this, -current_demand );
-                                    }
+                                    // This thread transitioned pool to empty state, and thus is
+                                    // responsible for telling the market that there is no work to do.
+                                    my_market->adjust_demand( *this, -current_demand );
                                     restore_priority_if_need();
                                     return true;
                                 }
@@ -630,6 +629,10 @@ public:
             mimic_outermost_level(a, type);
         } else {
             my_orig_state = *s;
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+            my_scheduler.my_properties.genuine = true;
+            my_scheduler.my_current_is_recalled = NULL;
+#endif
             mimic_outermost_level(a, type);
             s->nested_arena_entry(a, slot_index);
         }
@@ -694,6 +697,9 @@ void generic_scheduler::nested_arena_entry(arena* a, size_t slot_index) {
     my_last_local_observer = 0; // TODO: try optimize number of calls
     my_arena->my_observers.notify_entry_observers( my_last_local_observer, /*worker=*/false );
 #endif
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    my_wait_task = NULL;
+#endif
 }
 
 void generic_scheduler::nested_arena_exit() {
@@ -719,6 +725,80 @@ void generic_scheduler::wait_until_empty() {
     my_dummy_task->prefix().ref_count--;
 }
 
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+class resume_task : public task {
+    generic_scheduler& my_target;
+public:
+    resume_task(generic_scheduler& target) : my_target(target) {}
+    task* execute() __TBB_override {
+        generic_scheduler* s = governor::local_scheduler_if_initialized();
+        __TBB_ASSERT(s, NULL);
+        if (s->prepare_resume(my_target)) {
+            s->resume(my_target);
+        } else {
+            __TBB_ASSERT(prefix().state == task::executing, NULL);
+            // Request the dispatch loop to exit (because we in a coroutine on the outermost level).
+            prefix().state = task::to_resume;
+        }
+        return NULL;
+    }
+};
+
+static generic_scheduler& create_coroutine(generic_scheduler& curr) {
+    // We may have some coroutines cached
+    generic_scheduler* co_sched = curr.my_arena->my_co_cache.pop();
+    if (!co_sched) {
+        // TODO: avoid setting/unsetting the scheduler.
+        governor::assume_scheduler(NULL);
+        co_sched = generic_scheduler::create_worker(*curr.my_market, curr.my_arena_index, /* genuine = */ false);
+        governor::assume_scheduler(&curr);
+        // Prepare newly created scheduler
+        co_sched->my_arena = curr.my_arena;
+    }
+    // Prepare scheduler (general)
+    co_sched->my_dummy_task->prefix().context = co_sched->my_arena->my_default_ctx;
+    // Prolong the arena's lifetime until all coroutines is alive
+    // (otherwise the arena can be destroyed while some tasks are suspended).
+    co_sched->my_arena->my_references += arena::ref_external;
+    return *co_sched;
+}
+
+void internal_suspend(void* suspend_callback, void* user_callback) {
+    generic_scheduler& s = *governor::local_scheduler();
+    __TBB_ASSERT(s.my_arena_slot->my_scheduler_is_recalled != NULL, NULL);
+    bool is_recalled = *s.my_arena_slot->my_scheduler_is_recalled;
+    generic_scheduler& target = is_recalled ? *s.my_arena_slot->my_scheduler : create_coroutine(s);
+
+    generic_scheduler::callback_t callback = {
+        (generic_scheduler::suspend_callback_t)suspend_callback, user_callback, &s };
+    target.set_post_resume_action(generic_scheduler::PRA_CALLBACK, &callback);
+    s.resume(target);
+}
+
+void internal_resume(task::suspend_point tag) {
+    generic_scheduler& s = *static_cast<generic_scheduler*>(tag);
+    task* t = new(&s.allocate_task(sizeof(resume_task), __TBB_CONTEXT_ARG(NULL, s.my_dummy_task->context()))) resume_task(s);
+    make_critical(*t);
+
+    // TODO: remove this work-around
+    // Prolong the arena's lifetime until all coroutines is alive
+    // (otherwise the arena can be destroyed while some tasks are suspended).
+    arena& a = *s.my_arena;
+    a.my_references += arena::ref_external;
+
+    a.my_critical_task_stream.push(t, 0, tbb::internal::random_lane_selector(s.my_random));
+    // Do not access 's' after that point.
+    a.advertise_new_work<arena::work_spawned>();
+
+    // Release our reference to my_arena.
+    a.on_thread_leaving<arena::ref_external>();
+}
+
+task::suspend_point internal_current_suspend_point() {
+    return governor::local_scheduler();
+}
+#endif /* __TBB_PREVIEW_RESUMABLE_TASKS */
+
 } // namespace internal
 } // namespace tbb
 
@@ -835,6 +915,7 @@ class delegated_task : public task {
                 // Restore context for sake of registering potential exception
                 t->prefix().context = orig_ctx;
 #endif
+                // Restore scheduler state
                 s.my_properties = orig_props;
                 s.my_dummy_task = orig_dummy;
             }
@@ -844,8 +925,19 @@ class delegated_task : public task {
     }
     ~delegated_task() {
         // potential exception was already registered. It must happen before the notification
-        __TBB_ASSERT(my_root->ref_count()==2, NULL);
-        __TBB_store_with_release(my_root->prefix().ref_count, 1); // must precede the wakeup
+        __TBB_ASSERT(my_root->ref_count() == 2, NULL);
+        task_prefix& prefix = my_root->prefix();
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+        reference_count old_ref_count = __TBB_FetchAndStoreW(&prefix.ref_count, 1);
+        // Check if the scheduler was abandoned.
+        if (old_ref_count == internal::abandon_flag + 2) {
+            __TBB_ASSERT(prefix.abandoned_scheduler, NULL);
+            // The wait has been completed. Spawn a resume task.
+            tbb::task::resume(prefix.abandoned_scheduler);
+        }
+#else
+        __TBB_store_with_release(prefix.ref_count, 1); // must precede the wakeup
+#endif
         my_monitor.notify(*this); // do not relax, it needs a fence!
     }
 public:
@@ -878,7 +970,7 @@ void task_arena_base::internal_execute(internal::delegate_base& d) const {
                     dynamic_cast< internal::delegated_function< graph_funct, void>* >(&d);
 
             if (deleg_funct) {
-                internal_enqueue(*new(task::allocate_root(*my_context))
+                internal_enqueue(*new(task::allocate_root(__TBB_CONTEXT_ARG1(*my_context)))
                     internal::function_task< internal::strip< graph_funct >::type >
                         (internal::forward< graph_funct >(deleg_funct->my_func)), 0);
                 return;
@@ -1024,8 +1116,7 @@ public:
     }
 };
 
-void isolate_within_arena( delegate_base& d, intptr_t reserved ) {
-    __TBB_ASSERT_EX( reserved == 0, NULL );
+void isolate_within_arena( delegate_base& d, intptr_t isolation ) {
     // TODO: Decide what to do if the scheduler is not initialized. Is there a use case for it?
     generic_scheduler* s = governor::local_scheduler_weak();
     __TBB_ASSERT( s, "this_task_arena::isolate() needs an initialized scheduler" );
@@ -1034,7 +1125,7 @@ void isolate_within_arena( delegate_base& d, intptr_t reserved ) {
     isolation_tag& current_isolation = s->my_innermost_running_task->prefix().isolation;
     // We temporarily change the isolation tag of the currently running task. It will be restored in the destructor of the guard.
     isolation_guard guard( current_isolation );
-    current_isolation = reinterpret_cast<isolation_tag>(&d);
+    current_isolation = isolation? isolation : reinterpret_cast<isolation_tag>(&d);
     d();
 }
 #endif /* __TBB_TASK_ISOLATION */
index a5e9c06..44f22f7 100644 (file)
 #include "governor.h"
 #include "concurrent_monitor.h"
 
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+#include "tbb/spin_mutex.h"
+#endif
+
 namespace tbb {
 
 class task_group_context;
@@ -43,6 +47,94 @@ class allocate_root_with_context_proxy;
 
 namespace internal {
 
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+//! Bounded coroutines cache LIFO ring buffer
+class arena_co_cache {
+    //! Ring buffer storage
+    generic_scheduler** my_co_scheduler_cache;
+    //! Current cache index
+    unsigned my_head;
+    //! Cache capacity for arena
+    unsigned my_max_index;
+    //! Accessor lock for modification operations
+    tbb::spin_mutex my_co_cache_mutex;
+
+    unsigned next_index() {
+        return ( my_head == my_max_index ) ? 0 : my_head + 1;
+    }
+
+    unsigned prev_index() {
+        return ( my_head == 0 ) ? my_max_index : my_head - 1;
+    }
+
+    bool internal_empty() {
+        return my_co_scheduler_cache[prev_index()] == NULL;
+    }
+
+    void internal_scheduler_cleanup(generic_scheduler* to_cleanup) {
+        to_cleanup->my_arena_slot = NULL;
+        // Needed by cleanup_worker function, as well as arena slot clearing
+        governor::assume_scheduler(to_cleanup);
+        generic_scheduler::cleanup_worker(to_cleanup, true);
+    }
+
+public:
+    void init(unsigned cache_capacity) {
+        size_t alloc_size = cache_capacity * sizeof(generic_scheduler*);
+        my_co_scheduler_cache = (generic_scheduler**)NFS_Allocate(1, alloc_size, NULL);
+        memset( my_co_scheduler_cache, 0, alloc_size );
+        my_head = 0;
+        my_max_index = cache_capacity - 1;
+    }
+
+    void cleanup() {
+        generic_scheduler* current = governor::local_scheduler_if_initialized();
+        while (generic_scheduler* to_cleanup = pop()) {
+            internal_scheduler_cleanup(to_cleanup);
+        }
+        governor::assume_scheduler(current);
+        NFS_Free(my_co_scheduler_cache);
+    }
+
+    //! Insert scheduler to the current available place.
+    //! Replace an old value, if necessary.
+    void push(generic_scheduler* s) {
+        generic_scheduler* to_cleanup = NULL;
+        {
+            tbb::spin_mutex::scoped_lock lock(my_co_cache_mutex);
+            // Check if we are replacing some existing buffer entrance
+            if (my_co_scheduler_cache[my_head] != NULL) {
+                to_cleanup = my_co_scheduler_cache[my_head];
+            }
+            // Store the cached value
+            my_co_scheduler_cache[my_head] = s;
+            // Move head index to the next slot
+            my_head = next_index();
+        }
+        // Cleanup replaced buffer if any
+        if (to_cleanup) {
+            generic_scheduler* current = governor::local_scheduler_if_initialized();
+            internal_scheduler_cleanup(to_cleanup);
+            governor::assume_scheduler(current);
+        }
+    }
+
+    //! Get a cached scheduler if any
+    generic_scheduler* pop() {
+        tbb::spin_mutex::scoped_lock lock(my_co_cache_mutex);
+        // No cached coroutine
+        if (internal_empty()) return NULL;
+        // Move head index to the currently available value
+        my_head = prev_index();
+        // Retrieve the value from the buffer
+        generic_scheduler* to_return = my_co_scheduler_cache[my_head];
+        // Clear the previous entrance value
+        my_co_scheduler_cache[my_head] = NULL;
+        return to_return;
+    }
+};
+#endif // __TBB_PREVIEW_RESUMABLE_TASKS
+
 //! The structure of an arena, except the array of slots.
 /** Separated in order to simplify padding.
     Intrusive list node base class is used by market to form a list of arenas. **/
@@ -152,20 +244,20 @@ struct arena_base : padded<intrusive_list_node> {
     unsigned my_num_reserved_slots;
 
 #if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-    //! Possible states for the concurrency mode of an arena.
-    enum concurrency_mode {
-        cm_normal =  0,     // arena is served by workers as usual
-        cm_enforced_local,  // arena needs an extra worker despite the arena limit
-        cm_enforced_global  // arena needs an extra worker despite a global limit
-    };
-
-    //! The concurrency mode of an arena.
-    concurrency_mode my_concurrency_mode;
+    // arena needs an extra worker despite the arena limit
+    bool my_local_concurrency_mode;
+    // arena needs an extra worker despite a global limit
+    bool my_global_concurrency_mode;
 #endif /* __TBB_ENQUEUE_ENFORCED_CONCURRENCY */
 
     //! Waiting object for master threads that cannot join the arena.
     concurrent_monitor my_exit_monitors;
 
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    //! Coroutines cache buffer
+    arena_co_cache my_co_cache;
+#endif
+
 #if TBB_USE_ASSERT
     //! Used to trap accesses to the object after its destruction.
     uintptr_t my_guard;
@@ -230,10 +322,15 @@ public:
     static bool is_busy_or_empty( pool_state_t s ) { return s < SNAPSHOT_FULL; }
 
     //! The number of workers active in the arena.
-    unsigned num_workers_active( ) {
+    unsigned num_workers_active() const {
         return my_references >> ref_external_bits;
     }
 
+    //! Check if the recall is requested by the market.
+    bool is_recall_requested() const {
+        return num_workers_active() > my_num_workers_allotted;
+    }
+
     //! If necessary, raise a flag that there is new job in arena.
     template<arena::new_work_type work_type> void advertise_new_work();
 
@@ -273,18 +370,6 @@ public:
     //! Check for the presence of enqueued tasks at all priority levels
     bool has_enqueued_tasks();
 
-#if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-    //! Recall worker if global mandatory is enabled, but not for this arena
-    bool recall_by_mandatory_request() const {
-        return my_market->my_mandatory_num_requested && my_concurrency_mode==cm_normal;
-    }
-
-    //! The arena is currently in an enforced concurrency mode
-    bool must_have_concurrency() const {
-        return my_num_workers_requested &&
-               ( my_concurrency_mode==cm_enforced_local || my_concurrency_mode==cm_enforced_global );
-    }
-#endif
     static const size_t out_of_arena = ~size_t(0);
     //! Tries to occupy a slot in the arena. On success, returns the slot index; if no slot is available, returns out_of_arena.
     template <bool as_worker>
@@ -368,8 +453,9 @@ inline void arena::on_thread_leaving ( ) {
     // TODO: consider more strict conditions for the cleanup,
     // because it can create the demand of workers,
     // but the arena can be already empty (and so ready for destroying)
+    // TODO: Fix the race: while we check soft limit and it might be changed.
     if( ref_param==ref_external && my_num_slots != my_num_reserved_slots
-        && 0 == m->my_num_workers_soft_limit && my_concurrency_mode==cm_normal ) {
+        && 0 == m->my_num_workers_soft_limit && !my_global_concurrency_mode ) {
         bool is_out = false;
         for (int i=0; i<num_priority_levels; i++) {
             is_out = is_out_of_work();
@@ -377,7 +463,7 @@ inline void arena::on_thread_leaving ( ) {
                 break;
         }
         // We expect, that in worst case it's enough to have num_priority_levels-1
-        // calls to restore priorities and and yet another is_out_of_work() to conform
+        // calls to restore priorities and yet another is_out_of_work() to conform
         // that no work was found. But as market::set_active_num_workers() can be called
         // concurrently, can't guarantee last is_out_of_work() return true.
     }
@@ -389,19 +475,15 @@ inline void arena::on_thread_leaving ( ) {
 template<arena::new_work_type work_type> void arena::advertise_new_work() {
     if( work_type == work_enqueued ) {
 #if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-        if( my_market->my_num_workers_soft_limit == 0 ) {
-            if( my_concurrency_mode!=cm_enforced_global ) {
-                if( my_market->mandatory_concurrency_enable( this ) ) {
-                    my_pool_state = SNAPSHOT_FULL;
-                    return;
-                }
-            }
-        } else if( my_max_num_workers==0 && my_num_reserved_slots==1 ) {
-            my_max_num_workers = 1;
-            __TBB_ASSERT(my_concurrency_mode==cm_normal, NULL);
-            my_concurrency_mode = cm_enforced_local;
+        if ( as_atomic(my_market->my_num_workers_soft_limit) == 0 && as_atomic(my_global_concurrency_mode) == false )
+            my_market->enable_mandatory_concurrency(this);
+
+        if ( my_max_num_workers == 0 && my_num_reserved_slots == 1 ) {
+            __TBB_ASSERT(!my_local_concurrency_mode, NULL);
+            my_local_concurrency_mode = true;
             my_pool_state = SNAPSHOT_FULL;
-            my_market->adjust_demand( *this, 1 );
+            my_max_num_workers = 1;
+            my_market->adjust_demand(*this, my_max_num_workers);
             return;
         }
 #endif /* __TBB_ENQUEUE_ENFORCED_CONCURRENCY */
@@ -438,27 +520,19 @@ template<arena::new_work_type work_type> void arena::advertise_new_work() {
             // telling the market that there is work to do.
 #if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
             if( work_type == work_spawned ) {
-                if( my_concurrency_mode!=cm_normal ) {
-                    switch( my_concurrency_mode ) {
-                    case cm_enforced_local:
-                        __TBB_ASSERT(my_max_num_workers==1, "");
-                        __TBB_ASSERT(!governor::local_scheduler()->is_worker(), "");
-                        // There was deliberate oversubscription on 1 core for sake of starvation-resistant tasks.
-                        // Now a single active thread (must be the master) supposedly starts a new parallel region
-                        // with relaxed sequential semantics, and oversubscription should be avoided.
-                        // Demand for workers has been decreased to 0 during SNAPSHOT_EMPTY, so just keep it.
-                        my_max_num_workers = 0;
-                        my_concurrency_mode = cm_normal;
-                        break;
-                    case cm_enforced_global:
-                        my_market->mandatory_concurrency_disable( this );
-                        restore_priority_if_need();
-                        break;
-                    default:
-                        break;
-                    }
+                if( my_local_concurrency_mode ) {
+                    __TBB_ASSERT(my_max_num_workers==1, "");
+                    __TBB_ASSERT(!governor::local_scheduler()->is_worker(), "");
+                    // There was deliberate oversubscription on 1 core for sake of starvation-resistant tasks.
+                    // Now a single active thread (must be the master) supposedly starts a new parallel region
+                    // with relaxed sequential semantics, and oversubscription should be avoided.
+                    // Demand for workers has been decreased to 0 during SNAPSHOT_EMPTY, so just keep it.
+                    my_max_num_workers = 0;
+                    my_local_concurrency_mode = false;
                     return;
                 }
+                if ( as_atomic(my_global_concurrency_mode) == true )
+                    my_market->mandatory_concurrency_disable( this );
             }
 #endif /* __TBB_ENQUEUE_ENFORCED_CONCURRENCY */
             // TODO: investigate adjusting of arena's demand by a single worker.
diff --git a/src/tbb/co_context.h b/src/tbb/co_context.h
new file mode 100644 (file)
index 0000000..50c2a2c
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+    Copyright (c) 2005-2019 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.
+*/
+
+#ifndef _TBB_co_context_H
+#define _TBB_co_context_H
+
+#if _WIN32
+#include <windows.h>
+namespace tbb {
+namespace internal {
+    typedef LPVOID coroutine_type;
+}}
+#else // !_WIN32
+// ucontext.h API is deprecated since macOS 10.6
+#if __APPLE__
+    #if __INTEL_COMPILER
+        #pragma warning(push)
+        #pragma warning(disable:1478)
+    #elif __clang__
+        #pragma clang diagnostic push
+        #pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    #endif
+#endif // __APPLE__
+
+#include <ucontext.h>
+#include <sys/mman.h> // mprotect
+
+#include "governor.h" // default_page_size()
+
+#ifndef MAP_STACK
+// macOS* does not define MAP_STACK
+#define MAP_STACK 0
+#endif
+#ifndef MAP_ANONYMOUS
+// macOS* defines MAP_ANON, which is deprecated in Linux*.
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+namespace tbb {
+namespace internal {
+    struct coroutine_type {
+        coroutine_type() : my_context(), my_stack(), my_stack_size() {}
+        ucontext_t my_context;
+        void* my_stack;
+        size_t my_stack_size;
+    };
+}}
+#endif // _WIN32
+
+namespace tbb {
+namespace internal {
+
+    // Forward declaration of the coroutine API.
+    void create_coroutine(coroutine_type& c, size_t stack_size, void* arg);
+    void current_coroutine(coroutine_type& c);
+    void swap_coroutine(coroutine_type& prev_coroutine, coroutine_type& new_coroutine);
+    void destroy_coroutine(coroutine_type& c);
+
+class co_context {
+    enum co_state {
+        co_invalid,
+        co_suspended,
+        co_executing,
+        co_destroyed
+    };
+    coroutine_type      my_coroutine;
+    co_state            my_state;
+
+public:
+    co_context(size_t stack_size, void* arg)
+        : my_state(arg ? co_suspended : co_executing)
+    {
+        if (arg) {
+            create_coroutine(my_coroutine, stack_size, arg);
+        } else {
+            current_coroutine(my_coroutine);
+        }
+    }
+
+    ~co_context() {
+        __TBB_ASSERT(1 << my_state & (1 << co_suspended | 1 << co_executing), NULL);
+        if (my_state == co_suspended)
+            destroy_coroutine(my_coroutine);
+        my_state = co_destroyed;
+    }
+
+    void resume(co_context& target) {
+        // Do not create non-trivial objects on the stack of this function. They might never be destroyed.
+        __TBB_ASSERT(my_state == co_executing, NULL);
+        __TBB_ASSERT(target.my_state == co_suspended, NULL);
+
+        my_state = co_suspended;
+        target.my_state = co_executing;
+
+        // 'target' can reference an invalid object after swap_coroutine. Do not access it.
+        swap_coroutine(my_coroutine, target.my_coroutine);
+
+        __TBB_ASSERT(my_state == co_executing, NULL);
+    }
+#if !_WIN32
+    void* get_stack_limit() {
+        return my_coroutine.my_stack;
+    }
+#endif
+};
+
+// Defined in scheduler.h
+#if _WIN32
+void __stdcall co_local_wait_for_all(void*);
+#else
+void co_local_wait_for_all(void*);
+#endif
+
+#if _WIN32
+inline void create_coroutine(coroutine_type& c, size_t stack_size, void* arg) {
+    __TBB_ASSERT(arg, NULL);
+    c = CreateFiber(stack_size, co_local_wait_for_all, arg);
+    __TBB_ASSERT(c, NULL);
+}
+
+inline void current_coroutine(coroutine_type& c) {
+    c = IsThreadAFiber() ? GetCurrentFiber() :
+        ConvertThreadToFiberEx(nullptr, FIBER_FLAG_FLOAT_SWITCH);
+    __TBB_ASSERT(c, NULL);
+}
+
+inline void swap_coroutine(coroutine_type& prev_coroutine, coroutine_type& new_coroutine) {
+    __TBB_ASSERT(IsThreadAFiber(), NULL);
+    __TBB_ASSERT(new_coroutine, NULL);
+    prev_coroutine = GetCurrentFiber();
+    __TBB_ASSERT(prev_coroutine, NULL);
+    SwitchToFiber(new_coroutine);
+}
+
+inline void destroy_coroutine(coroutine_type& c) {
+    __TBB_ASSERT(c, NULL);
+    DeleteFiber(c);
+}
+#else // !_WIN32
+
+inline void create_coroutine(coroutine_type& c, size_t stack_size, void* arg) {
+    const size_t REG_PAGE_SIZE = governor::default_page_size();
+    const size_t page_aligned_stack_size = (stack_size + (REG_PAGE_SIZE - 1)) & ~(REG_PAGE_SIZE - 1);
+    const size_t protected_stack_size = page_aligned_stack_size + 2 * REG_PAGE_SIZE;
+
+    // Allocate the stack with protection property
+    uintptr_t stack_ptr = (uintptr_t)mmap(NULL, protected_stack_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
+    __TBB_ASSERT((void*)stack_ptr != MAP_FAILED, NULL);
+
+    // Alow read write on our stack (guarded pages are still protected)
+    int err = mprotect((void*)(stack_ptr + REG_PAGE_SIZE), page_aligned_stack_size, PROT_READ | PROT_WRITE);
+    __TBB_ASSERT_EX(!err, NULL);
+
+    // Remember the stack state
+    c.my_stack = (void*)(stack_ptr + REG_PAGE_SIZE);
+    c.my_stack_size = page_aligned_stack_size;
+
+    err = getcontext(&c.my_context);
+    __TBB_ASSERT_EX(!err, NULL);
+
+    c.my_context.uc_link = 0;
+    // cast to char* to disable FreeBSD clang-3.4.1 'incompatible type' error
+    c.my_context.uc_stack.ss_sp = (char*)c.my_stack;
+    c.my_context.uc_stack.ss_size = c.my_stack_size;
+    c.my_context.uc_stack.ss_flags = 0;
+
+    typedef void(*coroutine_func_t)();
+    makecontext(&c.my_context, (coroutine_func_t)co_local_wait_for_all, sizeof(arg) / sizeof(int), arg);
+}
+
+inline void current_coroutine(coroutine_type& c) {
+    int err = getcontext(&c.my_context);
+    __TBB_ASSERT_EX(!err, NULL);
+}
+
+inline void swap_coroutine(coroutine_type& prev_coroutine, coroutine_type& new_coroutine) {
+    int err = swapcontext(&prev_coroutine.my_context, &new_coroutine.my_context);
+    __TBB_ASSERT_EX(!err, NULL);
+}
+
+inline void destroy_coroutine(coroutine_type& c) {
+    const size_t REG_PAGE_SIZE = governor::default_page_size();
+    // Free stack memory with guarded pages
+    munmap((void*)((uintptr_t)c.my_stack - REG_PAGE_SIZE), c.my_stack_size + 2 * REG_PAGE_SIZE);
+    // Clear the stack state afterwards
+    c.my_stack = NULL;
+    c.my_stack_size = 0;
+}
+
+#if __APPLE__
+    #if __INTEL_COMPILER
+        #pragma warning(pop) // 1478 warning
+    #elif __clang__
+        #pragma clang diagnostic pop // "-Wdeprecated-declarations"
+    #endif
+#endif
+
+#endif // _WIN32
+
+} // namespace internal
+} // namespace tbb
+
+#endif /* _TBB_co_context_H */
+
index d703b9e..ec82697 100644 (file)
@@ -52,7 +52,7 @@ template<typename SchedulerTraits>
 class custom_scheduler: private generic_scheduler {
     typedef custom_scheduler<SchedulerTraits> scheduler_type;
 
-    custom_scheduler( market& m ) : generic_scheduler(m) {}
+    custom_scheduler( market& m, bool genuine ) : generic_scheduler(m, genuine) {}
 
     //! Scheduler loop that dispatches tasks.
     /** If child is non-NULL, it is dispatched first.
@@ -71,13 +71,27 @@ class custom_scheduler: private generic_scheduler {
         When changing, remember that this is a hot path function. */
     void tally_completion_of_predecessor( task& s, __TBB_ISOLATION_ARG( task*& bypass_slot, isolation_tag isolation ) ) {
         task_prefix& p = s.prefix();
+        __TBB_ASSERT(p.ref_count > 0, NULL);
         if( SchedulerTraits::itt_possible )
             ITT_NOTIFY(sync_releasing, &p.ref_count);
         if( SchedulerTraits::has_slow_atomic && p.ref_count==1 )
             p.ref_count=0;
-        else if( __TBB_FetchAndDecrementWrelease(&p.ref_count) > 1 ) {// more references exist
-            // '__TBB_cl_evict(&p)' degraded performance of parallel_preorder example
-            return;
+        else {
+            reference_count old_ref_count = __TBB_FetchAndDecrementWrelease(&p.ref_count);
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+            if (old_ref_count == internal::abandon_flag + 2) {
+                // Remove the abandon flag.
+                p.ref_count = 1;
+                // The wait has been completed. Spawn a resume task.
+                tbb::task::resume(p.abandoned_scheduler);
+                return;
+            }
+#endif
+            if (old_ref_count > 1) {
+                // more references exist
+                // '__TBB_cl_evict(&p)' degraded performance of parallel_preorder example
+                return;
+            }
         }
 
         // Ordering on p.ref_count (superfluous if SchedulerTraits::has_slow_atomic)
@@ -115,11 +129,15 @@ class custom_scheduler: private generic_scheduler {
             local_spawn( &s, s.prefix().next );
     }
 
+    //! Implements the bypass loop of the dispatch loop (local_wait_for_all).
+    bool process_bypass_loop( context_guard_helper</*report_tasks=*/SchedulerTraits::itt_possible>& context_guard,
+        __TBB_ISOLATION_ARG(task* t, isolation_tag isolation) );
+
 public:
-    static generic_scheduler* allocate_scheduler( market& m ) {
+    static generic_scheduler* allocate_scheduler( market& m, bool genuine ) {
         void* p = NFS_Allocate(1, sizeof(scheduler_type), NULL);
         std::memset(p, 0, sizeof(scheduler_type));
-        scheduler_type* s = new( p ) scheduler_type( m );
+        scheduler_type* s = new( p ) scheduler_type( m, genuine );
         s->assert_task_pool_valid();
         ITT_SYNC_CREATE(s, SyncType_Scheduler, SyncObj_TaskPoolSpinning);
         return s;
@@ -140,6 +158,10 @@ task* custom_scheduler<SchedulerTraits>::receive_or_steal_task( __TBB_ISOLATION_
     bool outermost_worker_level = worker_outermost_level();
     bool outermost_dispatch_level = outermost_worker_level || master_outermost_level();
     bool can_steal_here = can_steal();
+    bool outermost_current_worker_level = outermost_worker_level;
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    outermost_current_worker_level &= my_properties.genuine;
+#endif
     my_inbox.set_is_idle( true );
 #if __TBB_HOARD_NONLOCAL_TASKS
     __TBB_ASSERT(!my_nonlocal_free_list, NULL);
@@ -167,7 +189,7 @@ task* custom_scheduler<SchedulerTraits>::receive_or_steal_task( __TBB_ISOLATION_
     for( int failure_count = -static_cast<int>(SchedulerTraits::itt_possible);; ++failure_count) {
         __TBB_ASSERT( my_arena->my_limit > 0, NULL );
         __TBB_ASSERT( my_arena_index <= n, NULL );
-        if( completion_ref_count==1 ) {
+        if( completion_ref_count == 1 ) {
             if( SchedulerTraits::itt_possible ) {
                 if( failure_count!=-1 ) {
                     ITT_NOTIFY(sync_prepare, &completion_ref_count);
@@ -184,15 +206,21 @@ task* custom_scheduler<SchedulerTraits>::receive_or_steal_task( __TBB_ISOLATION_
             break; // exit stealing loop and return;
         }
         // Check if the resource manager requires our arena to relinquish some threads
-        if ( outermost_worker_level && (my_arena->my_num_workers_allotted < my_arena->num_workers_active()
-#if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-                 || my_arena->recall_by_mandatory_request()
-#endif
-                 ) ) {
-            if( SchedulerTraits::itt_possible && failure_count != -1 )
-                ITT_NOTIFY(sync_cancel, this);
+        if ( outermost_current_worker_level ) {
+            if ( ( my_arena->my_num_workers_allotted < my_arena->num_workers_active() ) ) {
+                if ( SchedulerTraits::itt_possible && failure_count != -1 )
+                    ITT_NOTIFY(sync_cancel, this);
+                return NULL;
+            }
+        }
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+        else if ( *my_arena_slot->my_scheduler_is_recalled ) {
+            // Original scheduler was requested, return from stealing loop and recall.
+            if ( my_inbox.is_idle_state(true) )
+                my_inbox.set_is_idle(false);
             return NULL;
         }
+#endif
 #if __TBB_TASK_PRIORITY
         const int p = int(my_arena->my_top_priority);
 #else /* !__TBB_TASK_PRIORITY */
@@ -315,10 +343,10 @@ fail:
                 // When a worker thread has nothing to do, return it to RML.
                 // For purposes of affinity support, the thread is considered idle while in RML.
 #if __TBB_TASK_PRIORITY
-                if( outermost_worker_level || my_arena->my_top_priority > my_arena->my_bottom_priority ) {
-                    if ( my_arena->is_out_of_work() && outermost_worker_level ) {
+                if( outermost_current_worker_level || my_arena->my_top_priority > my_arena->my_bottom_priority ) {
+                    if ( my_arena->is_out_of_work() && outermost_current_worker_level ) {
 #else /* !__TBB_TASK_PRIORITY */
-                    if ( outermost_worker_level && my_arena->is_out_of_work() ) {
+                    if ( outermost_current_worker_level && my_arena->is_out_of_work() ) {
 #endif /* !__TBB_TASK_PRIORITY */
                         if( SchedulerTraits::itt_possible )
                             ITT_NOTIFY(sync_cancel, this);
@@ -353,72 +381,240 @@ fail:
 }
 
 template<typename SchedulerTraits>
+bool custom_scheduler<SchedulerTraits>::process_bypass_loop(
+            context_guard_helper</*report_tasks=*/SchedulerTraits::itt_possible>& context_guard,
+            __TBB_ISOLATION_ARG(task* t, isolation_tag isolation) )
+{
+    while ( t ) {
+        __TBB_ASSERT( my_inbox.is_idle_state(false), NULL );
+        __TBB_ASSERT(!is_proxy(*t),"unexpected proxy");
+        __TBB_ASSERT( t->prefix().owner, NULL );
+#if __TBB_TASK_ISOLATION
+        __TBB_ASSERT( isolation == no_isolation || isolation == t->prefix().isolation,
+            "A task from another isolated region is going to be executed" );
+#endif /* __TBB_TASK_ISOLATION */
+        assert_task_valid(t);
+#if __TBB_TASK_GROUP_CONTEXT && TBB_USE_ASSERT
+        assert_context_valid(t->prefix().context);
+        if ( !t->prefix().context->my_cancellation_requested )
+#endif
+        // TODO: make the assert stronger by prohibiting allocated state.
+        __TBB_ASSERT( 1L<<t->state() & (1L<<task::allocated|1L<<task::ready|1L<<task::reexecute), NULL );
+        assert_task_pool_valid();
+#if __TBB_PREVIEW_CRITICAL_TASKS
+        // TODO: check performance and optimize if needed for added conditions on the
+        // hot-path.
+        if( !internal::is_critical(*t) && !t->is_enqueued_task() ) {
+            if( task* critical_task = get_critical_task( __TBB_ISOLATION_EXPR(isolation) ) ) {
+                __TBB_ASSERT( internal::is_critical(*critical_task),
+                              "Received task must be critical one" );
+                ITT_NOTIFY(sync_acquired, &my_arena->my_critical_task_stream);
+                t->prefix().state = task::allocated;
+                my_innermost_running_task = t; // required during spawn to propagate isolation
+                local_spawn(t, t->prefix().next);
+                t = critical_task;
+            } else {
+#endif /* __TBB_PREVIEW_CRITICAL_TASKS */
+#if __TBB_TASK_PRIORITY
+                intptr_t p = priority(*t);
+                if ( p != *my_ref_top_priority
+                     && !t->is_enqueued_task() ) {
+                    assert_priority_valid(p);
+                    if ( p != my_arena->my_top_priority ) {
+                        my_market->update_arena_priority( *my_arena, p );
+                    }
+                    if ( p < effective_reference_priority() ) {
+                        if ( !my_offloaded_tasks ) {
+                            my_offloaded_task_list_tail_link = &t->prefix().next_offloaded;
+                            // Erase possible reference to the owner scheduler
+                            // (next_offloaded is a union member)
+                            *my_offloaded_task_list_tail_link = NULL;
+                        }
+                        offload_task( *t, p );
+                        t = NULL;
+                        if ( is_task_pool_published() ) {
+                            t = winnow_task_pool( __TBB_ISOLATION_EXPR( isolation ) );
+                            if ( t )
+                                continue;
+                        } else {
+                            // Mark arena as full to unlock arena priority level adjustment
+                            // by arena::is_out_of_work(), and ensure worker's presence.
+                            my_arena->advertise_new_work<arena::wakeup>();
+                        }
+                        break; /* exit bypass loop */
+                    }
+                }
+#endif /* __TBB_TASK_PRIORITY */
+#if __TBB_PREVIEW_CRITICAL_TASKS
+            }
+        } // if is not critical
+#endif
+        task* t_next = NULL;
+        my_innermost_running_task = t;
+        t->prefix().owner = this;
+        t->prefix().state = task::executing;
+#if __TBB_TASK_GROUP_CONTEXT
+        context_guard.set_ctx( t->prefix().context );
+        if ( !t->prefix().context->my_cancellation_requested )
+#endif
+        {
+            GATHER_STATISTIC( ++my_counters.tasks_executed );
+            GATHER_STATISTIC( my_counters.avg_arena_concurrency += my_arena->num_workers_active() );
+            GATHER_STATISTIC( my_counters.avg_assigned_workers += my_arena->my_num_workers_allotted );
+#if __TBB_TASK_PRIORITY
+            GATHER_STATISTIC( my_counters.avg_arena_prio += p );
+            GATHER_STATISTIC( my_counters.avg_market_prio += my_market->my_global_top_priority );
+#endif /* __TBB_TASK_PRIORITY */
+            ITT_STACK(SchedulerTraits::itt_possible, callee_enter, t->prefix().context->itt_caller);
+            t_next = t->execute();
+            ITT_STACK(SchedulerTraits::itt_possible, callee_leave, t->prefix().context->itt_caller);
+            if (t_next) {
+                assert_task_valid(t_next);
+                __TBB_ASSERT( t_next->state()==task::allocated,
+                              "if task::execute() returns task, it must be marked as allocated" );
+                reset_extra_state(t_next);
+                __TBB_ISOLATION_EXPR( t_next->prefix().isolation = t->prefix().isolation );
+#if TBB_USE_ASSERT
+                affinity_id next_affinity=t_next->prefix().affinity;
+                if (next_affinity != 0 && next_affinity != my_affinity_id)
+                    GATHER_STATISTIC( ++my_counters.affinity_ignored );
+#endif
+            } // if there is bypassed task
+        }
+        assert_task_pool_valid();
+        switch( t->state() ) {
+            case task::executing: {
+                task* s = t->parent();
+                __TBB_ASSERT( my_innermost_running_task==t, NULL );
+                __TBB_ASSERT( t->prefix().ref_count==0, "Task still has children after it has been executed" );
+                t->~task();
+                if( s )
+                    tally_completion_of_predecessor( *s, __TBB_ISOLATION_ARG( t_next, t->prefix().isolation ) );
+                free_task<no_hint>( *t );
+                poison_pointer( my_innermost_running_task );
+                assert_task_pool_valid();
+                break;
+            }
+
+            case task::recycle: // set by recycle_as_safe_continuation()
+                t->prefix().state = task::allocated;
+#if __TBB_RECYCLE_TO_ENQUEUE
+                __TBB_fallthrough;
+            case task::to_enqueue: // set by recycle_to_enqueue()
+#endif
+                __TBB_ASSERT( t_next != t, "a task returned from method execute() can not be recycled in another way" );
+                reset_extra_state(t);
+                // for safe continuation, need atomically decrement ref_count;
+                tally_completion_of_predecessor(*t, __TBB_ISOLATION_ARG( t_next, t->prefix().isolation ) );
+                assert_task_pool_valid();
+                break;
+
+            case task::reexecute: // set by recycle_to_reexecute()
+                __TBB_ASSERT( t_next, "reexecution requires that method execute() return another task" );
+                __TBB_ASSERT( t_next != t, "a task returned from method execute() can not be recycled in another way" );
+                t->prefix().state = task::allocated;
+                reset_extra_state(t);
+                local_spawn( t, t->prefix().next );
+                assert_task_pool_valid();
+                break;
+            case task::allocated:
+                reset_extra_state(t);
+                break;
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+            case task::to_resume:
+                __TBB_ASSERT(my_innermost_running_task == t, NULL);
+                __TBB_ASSERT(t->prefix().ref_count == 0, "Task still has children after it has been executed");
+                t->~task();
+                free_task<no_hint>(*t);
+                __TBB_ASSERT(!my_properties.genuine && my_properties.outermost,
+                    "Only a coroutine on outermost level can be left.");
+                // Leave the outermost coroutine
+                return false;
+#endif
+#if TBB_USE_ASSERT
+            case task::ready:
+                __TBB_ASSERT( false, "task is in READY state upon return from method execute()" );
+                break;
+#endif
+            default:
+                __TBB_ASSERT( false, "illegal state" );
+                break;
+        }
+        GATHER_STATISTIC( t_next ? ++my_counters.spawns_bypassed : 0 );
+        t = t_next;
+    } // end of scheduler bypass loop
+    return true;
+}
+
+// TODO: Rename args 'parent' into 'controlling_task' and 'child' into 't' or consider introducing
+// a wait object (a la task_handle) to replace the 'parent' logic.
+template<typename SchedulerTraits>
 void custom_scheduler<SchedulerTraits>::local_wait_for_all( task& parent, task* child ) {
     __TBB_ASSERT( governor::is_set(this), NULL );
     __TBB_ASSERT( parent.ref_count() >= (child && child->parent() == &parent ? 2 : 1), "ref_count is too small" );
     __TBB_ASSERT( my_innermost_running_task, NULL );
+#if __TBB_TASK_GROUP_CONTEXT
+    __TBB_ASSERT( parent.prefix().context, "parent task does not have context" );
+#endif /* __TBB_TASK_GROUP_CONTEXT */
     assert_task_pool_valid();
     // Using parent's refcount in sync_prepare (in the stealing loop below) is
     // a workaround for TP. We need to name it here to display correctly in Ampl.
     if( SchedulerTraits::itt_possible )
         ITT_SYNC_CREATE(&parent.prefix().ref_count, SyncType_Scheduler, SyncObj_TaskStealingLoop);
-#if __TBB_TASK_GROUP_CONTEXT
-    __TBB_ASSERT( parent.prefix().context, "parent task does not have context" );
-#endif /* __TBB_TASK_GROUP_CONTEXT */
+
+    // TODO: consider extending the "context" guard to a "dispatch loop" guard to additionally
+    // guard old_innermost_running_task and old_properties states.
+    context_guard_helper</*report_tasks=*/SchedulerTraits::itt_possible> context_guard;
+    task* old_innermost_running_task = my_innermost_running_task;
+    scheduler_properties old_properties = my_properties;
+
     task* t = child;
-    // Constant all_local_work_done is an unreachable refcount value that prevents
-    // early quitting the dispatch loop. It is defined to be in the middle of the range
-    // of negative values representable by the reference_count type.
-    static const reference_count
-        // For normal dispatch loops
-        parents_work_done = 1,
-        // For termination dispatch loops in masters
-        all_local_work_done = (reference_count)3 << (sizeof(reference_count) * 8 - 2);
-    reference_count quit_point;
+    bool cleanup = !is_worker() && &parent==my_dummy_task;
+    // Remove outermost property to indicate nested level.
+    __TBB_ASSERT(my_properties.outermost || my_innermost_running_task!=my_dummy_task, "The outermost property should be set out of a dispatch loop");
+    my_properties.outermost &= my_innermost_running_task==my_dummy_task;
+#if __TBB_PREVIEW_CRITICAL_TASKS
+    my_properties.has_taken_critical_task |= is_critical(*my_innermost_running_task);
+#endif
 #if __TBB_TASK_PRIORITY
     __TBB_ASSERT( (uintptr_t)*my_ref_top_priority < (uintptr_t)num_priority_levels, NULL );
     volatile intptr_t *old_ref_top_priority = my_ref_top_priority;
     // When entering nested parallelism level market level counter
     // must be replaced with the one local to this arena.
     volatile uintptr_t *old_ref_reload_epoch = my_ref_reload_epoch;
+    if ( !outermost_level() ) {
+        // We are in a nested dispatch loop.
+        // Market or arena priority must not prevent child tasks from being
+        // executed so that dynamic priority changes did not cause deadlock.
+        my_ref_top_priority = &parent.prefix().context->my_priority;
+        my_ref_reload_epoch = &my_arena->my_reload_epoch;
+        if (my_ref_reload_epoch != old_ref_reload_epoch)
+            my_local_reload_epoch = *my_ref_reload_epoch - 1;
+    }
 #endif /* __TBB_TASK_PRIORITY */
-    task* old_innermost_running_task = my_innermost_running_task;
-    scheduler_properties old_properties = my_properties;
-    // Remove outermost property to indicate nested level.
-    __TBB_ASSERT( my_properties.outermost || my_innermost_running_task!=my_dummy_task, "The outermost property should be set out of a dispatch loop" );
-    my_properties.outermost &= my_innermost_running_task==my_dummy_task;
 #if __TBB_TASK_ISOLATION
     isolation_tag isolation = my_innermost_running_task->prefix().isolation;
-#endif /* __TBB_TASK_ISOLATION */
-    if( master_outermost_level() ) {
-        // We are in the outermost task dispatch loop of a master thread or a worker which mimics master
-        quit_point = &parent == my_dummy_task ? all_local_work_done : parents_work_done;
-    } else {
-        quit_point = parents_work_done;
-#if __TBB_TASK_PRIORITY
-        if ( &parent != my_dummy_task ) {
-            // We are in a nested dispatch loop.
-            // Market or arena priority must not prevent child tasks from being
-            // executed so that dynamic priority changes did not cause deadlock.
-            my_ref_top_priority = &parent.prefix().context->my_priority;
-            my_ref_reload_epoch = &my_arena->my_reload_epoch;
-            if(my_ref_reload_epoch != old_ref_reload_epoch)
-                my_local_reload_epoch = *my_ref_reload_epoch-1;
-        }
-#endif /* __TBB_TASK_PRIORITY */
+    if (t && isolation != no_isolation) {
+        __TBB_ASSERT(t->prefix().isolation == no_isolation, NULL);
+        // Propagate the isolation to the task executed without spawn.
+        t->prefix().isolation = isolation;
     }
-
-    context_guard_helper</*report_tasks=*/SchedulerTraits::itt_possible> context_guard;
-    if ( t ) {
-        context_guard.set_ctx( __TBB_CONTEXT_ARG1(t->prefix().context) );
-#if __TBB_TASK_ISOLATION
-        if ( isolation != no_isolation ) {
-            __TBB_ASSERT( t->prefix().isolation == no_isolation, NULL );
-            // Propagate the isolation to the task executed without spawn.
-            t->prefix().isolation = isolation;
-        }
 #endif /* __TBB_TASK_ISOLATION */
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    // The recall flag for the original owner of this scheduler.
+    // It is used only on outermost level of currently attached arena slot.
+    tbb::atomic<bool> recall_flag;
+    recall_flag = false;
+    if (outermost_level() && my_wait_task == NULL && my_properties.genuine) {
+        __TBB_ASSERT(my_arena_slot->my_scheduler == this, NULL);
+        __TBB_ASSERT(my_arena_slot->my_scheduler_is_recalled == NULL, NULL);
+        my_arena_slot->my_scheduler_is_recalled = &recall_flag;
+        my_current_is_recalled = &recall_flag;
     }
+    __TBB_ASSERT(my_arena_slot->my_scheduler_is_recalled != NULL, NULL);
+    task* old_wait_task = my_wait_task;
+    my_wait_task = &parent;
+#endif
 #if TBB_USE_EXCEPTIONS
     // Infinite safeguard EH loop
     for (;;) {
@@ -432,179 +628,50 @@ void custom_scheduler<SchedulerTraits>::local_wait_for_all( task& parent, task*
         for(;;) {
             // Inner loop evaluates tasks coming from nesting loops and those returned
             // by just executed tasks (bypassing spawn or enqueue calls).
-            while(t) {
-                __TBB_ASSERT( my_inbox.is_idle_state(false), NULL );
-                __TBB_ASSERT(!is_proxy(*t),"unexpected proxy");
-                __TBB_ASSERT( t->prefix().owner, NULL );
-#if __TBB_TASK_ISOLATION
-                __TBB_ASSERT( isolation == no_isolation || isolation == t->prefix().isolation,
-                    "A task from another isolated region is going to be executed" );
-#endif /* __TBB_TASK_ISOLATION */
-                assert_task_valid(t);
-#if __TBB_TASK_GROUP_CONTEXT && TBB_USE_ASSERT
-                assert_context_valid(t->prefix().context);
-                if ( !t->prefix().context->my_cancellation_requested )
-#endif
-                // TODO: make the assert stronger by prohibiting allocated state.
-                __TBB_ASSERT( 1L<<t->state() & (1L<<task::allocated|1L<<task::ready|1L<<task::reexecute), NULL );
-                assert_task_pool_valid();
-#if __TBB_PREVIEW_CRITICAL_TASKS
-                // TODO: check performance and optimize if needed for added conditions on the
-                // hot-path.
-                if( !internal::is_critical(*t) ) {
-                    if( task* critical_task = get_critical_task( __TBB_ISOLATION_EXPR(isolation) ) ) {
-                        __TBB_ASSERT( internal::is_critical(*critical_task),
-                                      "Received task must be critical one" );
-                        ITT_NOTIFY(sync_acquired, &my_arena->my_critical_task_stream);
-                        t->prefix().state = task::allocated;
-                        my_innermost_running_task = t; // required during spawn to propagate isolation
-                        local_spawn(t, t->prefix().next);
-                        t = critical_task;
-                    } else {
-#endif /* __TBB_PREVIEW_CRITICAL_TASKS */
-#if __TBB_TASK_PRIORITY
-                        intptr_t p = priority(*t);
-                        if ( p != *my_ref_top_priority
-                             && (t->prefix().extra_state & es_task_enqueued) == 0 ) {
-                            assert_priority_valid(p);
-                            if ( p != my_arena->my_top_priority ) {
-                                my_market->update_arena_priority( *my_arena, p );
-                            }
-                            if ( p < effective_reference_priority() ) {
-                                if ( !my_offloaded_tasks ) {
-                                    my_offloaded_task_list_tail_link = &t->prefix().next_offloaded;
-                                    // Erase possible reference to the owner scheduler
-                                    // (next_offloaded is a union member)
-                                    *my_offloaded_task_list_tail_link = NULL;
-                                }
-                                offload_task( *t, p );
-                                if ( is_task_pool_published() ) {
-                                    t = winnow_task_pool( __TBB_ISOLATION_EXPR( isolation ) );
-                                    if ( t )
-                                        continue;
-                                } else {
-                                    // Mark arena as full to unlock arena priority level adjustment
-                                    // by arena::is_out_of_work(), and ensure worker's presence.
-                                    my_arena->advertise_new_work<arena::wakeup>();
-                                }
-                                goto stealing_ground;
-                            }
-                        }
-#endif /* __TBB_TASK_PRIORITY */
-#if __TBB_PREVIEW_CRITICAL_TASKS
-                    }
-                } // if is not critical
-#endif
-                task* t_next = NULL;
-                my_innermost_running_task = t;
-                t->prefix().owner = this;
-                t->prefix().state = task::executing;
-#if __TBB_TASK_GROUP_CONTEXT
-                if ( !t->prefix().context->my_cancellation_requested )
-#endif
-                {
-                    GATHER_STATISTIC( ++my_counters.tasks_executed );
-                    GATHER_STATISTIC( my_counters.avg_arena_concurrency += my_arena->num_workers_active() );
-                    GATHER_STATISTIC( my_counters.avg_assigned_workers += my_arena->my_num_workers_allotted );
-#if __TBB_TASK_PRIORITY
-                    GATHER_STATISTIC( my_counters.avg_arena_prio += p );
-                    GATHER_STATISTIC( my_counters.avg_market_prio += my_market->my_global_top_priority );
-#endif /* __TBB_TASK_PRIORITY */
-                    ITT_STACK(SchedulerTraits::itt_possible, callee_enter, t->prefix().context->itt_caller);
-#if __TBB_PREVIEW_CRITICAL_TASKS
-                    internal::critical_task_count_guard tc_guard(my_properties, *t);
+            if ( !process_bypass_loop( context_guard, __TBB_ISOLATION_ARG(t, isolation) ) ) {
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+                // Restore the old properties for the coroutine reusage (leave in a valid state)
+                my_innermost_running_task = old_innermost_running_task;
+                my_properties = old_properties;
+                my_wait_task = old_wait_task;
 #endif
-                    t_next = t->execute();
-                    ITT_STACK(SchedulerTraits::itt_possible, callee_leave, t->prefix().context->itt_caller);
-                    if (t_next) {
-                        __TBB_ASSERT( t_next->state()==task::allocated,
-                                      "if task::execute() returns task, it must be marked as allocated" );
-                        reset_extra_state(t_next);
-                        __TBB_ISOLATION_EXPR( t_next->prefix().isolation = t->prefix().isolation );
-#if TBB_USE_ASSERT
-                        affinity_id next_affinity=t_next->prefix().affinity;
-                        if (next_affinity != 0 && next_affinity != my_affinity_id)
-                            GATHER_STATISTIC( ++my_counters.affinity_ignored );
-#endif
-                    } // if there is bypassed task
-                }
-                assert_task_pool_valid();
-                switch( t->state() ) {
-                    case task::executing: {
-                        task* s = t->parent();
-                        __TBB_ASSERT( my_innermost_running_task==t, NULL );
-                        __TBB_ASSERT( t->prefix().ref_count==0, "Task still has children after it has been executed" );
-                        t->~task();
-                        if( s )
-                            tally_completion_of_predecessor( *s, __TBB_ISOLATION_ARG( t_next, t->prefix().isolation ) );
-                        free_task<no_hint>( *t );
-                        poison_pointer( my_innermost_running_task );
-                        assert_task_pool_valid();
-                        break;
-                    }
-
-                    case task::recycle: // set by recycle_as_safe_continuation()
-                        t->prefix().state = task::allocated;
-#if __TBB_RECYCLE_TO_ENQUEUE
-                        __TBB_fallthrough;
-                    case task::to_enqueue: // set by recycle_to_enqueue()
-#endif
-                        __TBB_ASSERT( t_next != t, "a task returned from method execute() can not be recycled in another way" );
-                        reset_extra_state(t);
-                        // for safe continuation, need atomically decrement ref_count;
-                        tally_completion_of_predecessor(*t, __TBB_ISOLATION_ARG( t_next, t->prefix().isolation ) );
-                        assert_task_pool_valid();
-                        break;
-
-                    case task::reexecute: // set by recycle_to_reexecute()
-                        __TBB_ASSERT( t_next, "reexecution requires that method execute() return another task" );
-                        __TBB_ASSERT( t_next != t, "a task returned from method execute() can not be recycled in another way" );
-                        t->prefix().state = task::allocated;
-                        reset_extra_state(t);
-                        local_spawn( t, t->prefix().next );
-                        assert_task_pool_valid();
-                        break;
-                    case task::allocated:
-                        reset_extra_state(t);
-                        break;
-#if TBB_USE_ASSERT
-                    case task::ready:
-                        __TBB_ASSERT( false, "task is in READY state upon return from method execute()" );
-                        break;
-                    default:
-                        __TBB_ASSERT( false, "illegal state" );
-#else
-                    default: // just to shut up some compilation warnings
-                        break;
-#endif /* TBB_USE_ASSERT */
-                }
-                GATHER_STATISTIC( t_next ? ++my_counters.spawns_bypassed : 0 );
-                t = t_next;
-            } // end of scheduler bypass loop
+                return;
+            }
 
-            assert_task_pool_valid();
-            if ( parent.prefix().ref_count == quit_point ) {
-                __TBB_ASSERT( quit_point != all_local_work_done, NULL );
+            // Check "normal" exit condition when parent's work is done.
+            if ( parent.prefix().ref_count == 1 ) {
+                __TBB_ASSERT( !cleanup, NULL );
                 __TBB_control_consistency_helper(); // on ref_count
-                ITT_NOTIFY(sync_acquired, &parent.prefix().ref_count);
+                ITT_NOTIFY( sync_acquired, &parent.prefix().ref_count );
                 goto done;
             }
-            if ( is_task_pool_published() ) {
-                t = get_task( __TBB_ISOLATION_EXPR( isolation ) );
-            } else {
-                __TBB_ASSERT( is_quiescent_local_task_pool_reset(), NULL );
-                break;
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+            // The thread may be otside of its original scheduler. Check the recall request.
+            if ( &recall_flag != my_arena_slot->my_scheduler_is_recalled ) {
+                __TBB_ASSERT( my_arena_slot->my_scheduler_is_recalled != NULL, "A broken recall flag" );
+                if ( *my_arena_slot->my_scheduler_is_recalled ) {
+                    if ( !resume_original_scheduler() ) {
+                        // We are requested to finish the current coroutine before the resume.
+                        __TBB_ASSERT( !my_properties.genuine && my_properties.outermost,
+                            "Only a coroutine on outermost level can be left." );
+                        // Restore the old properties for the coroutine reusage (leave in a valid state)
+                        my_innermost_running_task = old_innermost_running_task;
+                        my_properties = old_properties;
+                        my_wait_task = old_wait_task;
+                        return;
+                    }
+                }
             }
+#endif
+            // Retrieve the task from local task pool.
+            __TBB_ASSERT( is_task_pool_published() || is_quiescent_local_task_pool_reset(), NULL );
+            t = is_task_pool_published() ? get_task( __TBB_ISOLATION_EXPR( isolation ) ) : NULL;
             assert_task_pool_valid();
 
-            if ( !t ) break;
-
-            context_guard.set_ctx( __TBB_CONTEXT_ARG1(t->prefix().context) );
+            if ( !t ) // No tasks in the local task pool. Go to stealing loop.
+                break;
         }; // end of local task pool retrieval loop
 
-#if __TBB_TASK_PRIORITY
-stealing_ground:
-#endif /* __TBB_TASK_PRIORITY */
 #if __TBB_HOARD_NONLOCAL_TASKS
         // before stealing, previously stolen task objects are returned
         for (; my_nonlocal_free_list; my_nonlocal_free_list = t ) {
@@ -612,7 +679,7 @@ stealing_ground:
             free_nonlocal_small_task( *my_nonlocal_free_list );
         }
 #endif
-        if ( quit_point == all_local_work_done ) {
+        if ( cleanup ) {
             __TBB_ASSERT( !is_task_pool_published() && is_quiescent_local_task_pool_reset(), NULL );
             __TBB_ASSERT( !worker_outermost_level(), NULL );
             my_innermost_running_task = old_innermost_running_task;
@@ -623,21 +690,45 @@ stealing_ground:
                 my_local_reload_epoch = *old_ref_reload_epoch-1;
             my_ref_reload_epoch = old_ref_reload_epoch;
 #endif /* __TBB_TASK_PRIORITY */
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+            if (&recall_flag != my_arena_slot->my_scheduler_is_recalled) {
+                // The recall point
+                __TBB_ASSERT(!recall_flag, NULL);
+                tbb::task::suspend(recall_functor(&recall_flag));
+                if (my_inbox.is_idle_state(true))
+                    my_inbox.set_is_idle(false);
+                continue;
+            }
+            __TBB_ASSERT(&recall_flag == my_arena_slot->my_scheduler_is_recalled, NULL);
+            __TBB_ASSERT(!(my_wait_task->prefix().ref_count & internal::abandon_flag), NULL);
+            my_wait_task = old_wait_task;
+#endif
             return;
         }
-        
         t = receive_or_steal_task( __TBB_ISOLATION_ARG( parent.prefix().ref_count, isolation ) );
-        if ( !t )
+        if ( !t ) {
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+            if ( *my_arena_slot->my_scheduler_is_recalled )
+                continue;
+            // Done if either original thread enters or we are on the nested level or attached the same arena
+            if ( &recall_flag == my_arena_slot->my_scheduler_is_recalled || old_wait_task != NULL )
+                goto done;
+            // The recall point. Continue dispatch loop because recalled thread may have tasks in it's task pool.
+            __TBB_ASSERT(!recall_flag, NULL);
+            tbb::task::suspend( recall_functor(&recall_flag) );
+            if ( my_inbox.is_idle_state(true) )
+                my_inbox.set_is_idle(false);
+#else
+            // Just exit dispatch loop
             goto done;
-        // The user can capture another the FPU settings to the context so the
-        // cached data in the helper can be out-of-date and we cannot do fast
-        // check.
-        context_guard.set_ctx( __TBB_CONTEXT_ARG1(t->prefix().context) );
+#endif
+        }
     } // end of infinite stealing loop
 #if TBB_USE_EXCEPTIONS
     __TBB_ASSERT( false, "Must never get here" );
     } // end of try-block
-    TbbCatchAll( t->prefix().context );
+    TbbCatchAll( my_innermost_running_task->prefix().context );
+    t = my_innermost_running_task;
     // Complete post-processing ...
     if( t->state() == task::recycle
 #if __TBB_RECYCLE_TO_ENQUEUE
@@ -660,6 +751,25 @@ stealing_ground:
     __TBB_ASSERT( false, "Must never get here too" );
 #endif /* TBB_USE_EXCEPTIONS */
 done:
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    __TBB_ASSERT(!(parent.prefix().ref_count & internal::abandon_flag), NULL);
+    my_wait_task = old_wait_task;
+    if (my_wait_task == NULL) {
+        __TBB_ASSERT(outermost_level(), "my_wait_task could be NULL only on outermost level");
+        if (&recall_flag != my_arena_slot->my_scheduler_is_recalled) {
+            // The recall point.
+            __TBB_ASSERT(my_properties.genuine, NULL);
+            __TBB_ASSERT(!recall_flag, NULL);
+            tbb::task::suspend(recall_functor(&recall_flag));
+            if (my_inbox.is_idle_state(true))
+                my_inbox.set_is_idle(false);
+        }
+        __TBB_ASSERT(my_arena_slot->my_scheduler == this, NULL);
+        my_arena_slot->my_scheduler_is_recalled = NULL;
+        my_current_is_recalled = NULL;
+    }
+
+#endif /* __TBB_PREVIEW_RESUMABLE_TASKS */
     my_innermost_running_task = old_innermost_running_task;
     my_properties = old_properties;
 #if __TBB_TASK_PRIORITY
@@ -669,7 +779,7 @@ done:
     my_ref_reload_epoch = old_ref_reload_epoch;
 #endif /* __TBB_TASK_PRIORITY */
     if ( !ConcurrentWaitsEnabled(parent) ) {
-        if ( parent.prefix().ref_count != parents_work_done ) {
+        if ( parent.prefix().ref_count != 1) {
             // This is a worker that was revoked by the market.
             __TBB_ASSERT( worker_outermost_level(),
                 "Worker thread exits nested dispatch loop prematurely" );
index 99516a9..029d083 100644 (file)
@@ -180,7 +180,9 @@ generic_scheduler* governor::init_scheduler( int num_threads, stack_size_type st
             s->attach_arena( market::create_arena( default_num_threads(), 1, 0 ), 0, /*is_master*/true );
             __TBB_ASSERT( s->my_arena_index == 0, "Master thread must occupy the first slot in its arena" );
             s->my_arena_slot->my_scheduler = s;
+#if __TBB_TASK_GROUP_CONTEXT
             s->my_arena->my_default_ctx = s->default_context(); // it also transfers implied ownership
+#endif
             // Mark the scheduler as fully initialized
             assume_scheduler( s );
         }
index 3a773bb..c37ef1c 100644 (file)
@@ -56,6 +56,9 @@ private:
     //! Caches the maximal level of parallelism supported by the hardware
     static unsigned DefaultNumberOfThreads;
 
+    //! Caches the size of OS regular memory page
+    static size_t DefaultPageSize;
+
     static rml::tbb_factory theRMLServerFactory;
 
     static bool UsePrivateRML;
@@ -83,6 +86,10 @@ public:
         return DefaultNumberOfThreads ? DefaultNumberOfThreads :
                                         DefaultNumberOfThreads = AvailableHwConcurrency();
     }
+    static size_t default_page_size () {
+        return DefaultPageSize ? DefaultPageSize :
+                                 DefaultPageSize = DefaultSystemPageSize();
+    }
     static void one_time_init();
     //! Processes scheduler initialization request (possibly nested) in a master thread
     /** If necessary creates new instance of arena and/or local scheduler.
index 12a21b4..20413b8 100644 (file)
@@ -173,6 +173,7 @@ __TBB_SYMBOL( _ZN3tbb8internal17itt_task_begin_v7ENS0_15itt_domain_enumEPvyS2_yN
 __TBB_SYMBOL( _ZN3tbb8internal15itt_task_end_v7ENS0_15itt_domain_enumE )
 __TBB_SYMBOL( _ZN3tbb8internal19itt_region_begin_v9ENS0_15itt_domain_enumEPvyS2_yNS0_12string_indexE )
 __TBB_SYMBOL( _ZN3tbb8internal17itt_region_end_v9ENS0_15itt_domain_enumEPvy )
+__TBB_SYMBOL( _ZN3tbb8internal24itt_metadata_ptr_add_v11ENS0_15itt_domain_enumEPvyNS0_12string_indexES2_ )
 
 /* pipeline.cpp */
 __TBB_SYMBOL( _ZTIN3tbb6filterE )
@@ -395,4 +396,10 @@ __TBB_SYMBOL( _ZN3tbb10interface914global_control12active_valueEi )
 __TBB_SYMBOL( _ZN3tbb10interface914global_control15internal_createEv )
 __TBB_SYMBOL( _ZN3tbb10interface914global_control16internal_destroyEv )
 
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+__TBB_SYMBOL( _ZN3tbb8internal16internal_suspendEPvS1_ )
+__TBB_SYMBOL( _ZN3tbb8internal15internal_resumeEPv )
+__TBB_SYMBOL( _ZN3tbb8internal30internal_current_suspend_pointEv )
+#endif
+
 #undef __TBB_SYMBOL
index 6f56983..1b2f9cd 100644 (file)
@@ -168,6 +168,7 @@ __TBB_SYMBOL( _ZN3tbb8internal19itt_relation_add_v7ENS0_15itt_domain_enumEPvyNS0
 __TBB_SYMBOL( _ZN3tbb8internal15itt_task_end_v7ENS0_15itt_domain_enumE )
 __TBB_SYMBOL( _ZN3tbb8internal19itt_region_begin_v9ENS0_15itt_domain_enumEPvyS2_yNS0_12string_indexE )
 __TBB_SYMBOL( _ZN3tbb8internal17itt_region_end_v9ENS0_15itt_domain_enumEPvy )
+__TBB_SYMBOL( _ZN3tbb8internal24itt_metadata_ptr_add_v11ENS0_15itt_domain_enumEPvyNS0_12string_indexES2_ )
 
 /* pipeline.cpp */
 __TBB_SYMBOL( _ZTIN3tbb6filterE )
@@ -376,4 +377,10 @@ __TBB_SYMBOL( _ZN3tbb8internal15thread_sleep_v3ERKNS_10tick_count10interval_tE )
 __TBB_SYMBOL( _ZN3tbb10interface914global_control12active_valueEi )
 __TBB_SYMBOL( _ZN3tbb10interface914global_control15internal_createEv )
 __TBB_SYMBOL( _ZN3tbb10interface914global_control16internal_destroyEv )
+
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+__TBB_SYMBOL( _ZN3tbb8internal16internal_suspendEPvS1_ )
+__TBB_SYMBOL( _ZN3tbb8internal15internal_resumeEPv )
+__TBB_SYMBOL( _ZN3tbb8internal30internal_current_suspend_pointEv )
+#endif
 #undef __TBB_SYMBOL
index 908f514..79cbf38 100644 (file)
@@ -169,6 +169,7 @@ __TBB_SYMBOL( _ZN3tbb8internal19itt_relation_add_v7ENS0_15itt_domain_enumEPvyNS0
 __TBB_SYMBOL( _ZN3tbb8internal15itt_task_end_v7ENS0_15itt_domain_enumE )
 __TBB_SYMBOL( _ZN3tbb8internal19itt_region_begin_v9ENS0_15itt_domain_enumEPvyS2_yNS0_12string_indexE )
 __TBB_SYMBOL( _ZN3tbb8internal17itt_region_end_v9ENS0_15itt_domain_enumEPvy )
+__TBB_SYMBOL( _ZN3tbb8internal24itt_metadata_ptr_add_v11ENS0_15itt_domain_enumEPvyNS0_12string_indexES2_ )
 
 /* pipeline.cpp */
 __TBB_SYMBOL( _ZTIN3tbb6filterE )
@@ -417,4 +418,10 @@ __TBB_SYMBOL( _ZN3tbb10interface914global_control12active_valueEi )
 __TBB_SYMBOL( _ZN3tbb10interface914global_control15internal_createEv )
 __TBB_SYMBOL( _ZN3tbb10interface914global_control16internal_destroyEv )
 
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+__TBB_SYMBOL( _ZN3tbb8internal16internal_suspendEPvS1_ )
+__TBB_SYMBOL( _ZN3tbb8internal15internal_resumeEPv )
+__TBB_SYMBOL( _ZN3tbb8internal30internal_current_suspend_pointEv )
+#endif
+
 #undef __TBB_SYMBOL
index 1ef5869..cc1c3e6 100644 (file)
@@ -194,6 +194,7 @@ __TBB_SYMBOL( _ZN3tbb8internal17itt_task_begin_v7ENS0_15itt_domain_enumEPvyS2_yN
 __TBB_SYMBOL( _ZN3tbb8internal15itt_task_end_v7ENS0_15itt_domain_enumE )
 __TBB_SYMBOL( _ZN3tbb8internal19itt_region_begin_v9ENS0_15itt_domain_enumEPvyS2_yNS0_12string_indexE )
 __TBB_SYMBOL( _ZN3tbb8internal17itt_region_end_v9ENS0_15itt_domain_enumEPvy )
+__TBB_SYMBOL( _ZN3tbb8internal24itt_metadata_ptr_add_v11ENS0_15itt_domain_enumEPvyNS0_12string_indexES2_ )
 
 // pipeline.cpp
 __TBB_SYMBOL( _ZTIN3tbb6filterE )
@@ -403,4 +404,10 @@ __TBB_SYMBOL( _ZN3tbb10interface914global_control12active_valueEi )
 __TBB_SYMBOL( _ZN3tbb10interface914global_control15internal_createEv )
 __TBB_SYMBOL( _ZN3tbb10interface914global_control16internal_destroyEv )
 
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+__TBB_SYMBOL( _ZN3tbb8internal16internal_suspendEPvS1_ )
+__TBB_SYMBOL( _ZN3tbb8internal15internal_resumeEPv )
+__TBB_SYMBOL( _ZN3tbb8internal30internal_current_suspend_pointEv )
+#endif
+
 #undef __TBB_SYMBOL
index c2d82d9..1761f31 100644 (file)
@@ -191,6 +191,7 @@ __TBB_SYMBOL( _ZN3tbb8internal19itt_relation_add_v7ENS0_15itt_domain_enumEPvyNS0
 __TBB_SYMBOL( _ZN3tbb8internal15itt_task_end_v7ENS0_15itt_domain_enumE )
 __TBB_SYMBOL( _ZN3tbb8internal19itt_region_begin_v9ENS0_15itt_domain_enumEPvyS2_yNS0_12string_indexE )
 __TBB_SYMBOL( _ZN3tbb8internal17itt_region_end_v9ENS0_15itt_domain_enumEPvy )
+__TBB_SYMBOL( _ZN3tbb8internal24itt_metadata_ptr_add_v11ENS0_15itt_domain_enumEPvyNS0_12string_indexES2_ )
 
 // pipeline.cpp
 __TBB_SYMBOL( _ZTIN3tbb6filterE )
@@ -400,4 +401,10 @@ __TBB_SYMBOL( _ZN3tbb10interface914global_control12active_valueEi )
 __TBB_SYMBOL( _ZN3tbb10interface914global_control15internal_createEv )
 __TBB_SYMBOL( _ZN3tbb10interface914global_control16internal_destroyEv )
 
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+__TBB_SYMBOL( _ZN3tbb8internal16internal_suspendEPvS1_ )
+__TBB_SYMBOL( _ZN3tbb8internal15internal_resumeEPv )
+__TBB_SYMBOL( _ZN3tbb8internal30internal_current_suspend_pointEv )
+#endif
+
 #undef __TBB_SYMBOL
index 98f3a02..bd8f830 100644 (file)
@@ -214,9 +214,25 @@ bool market::release ( bool is_public, bool blocking_terminate ) {
     return false;
 }
 
+int market::update_workers_request() {
+    int old_request = my_num_workers_requested;
+    my_num_workers_requested = min(my_total_demand, (int)my_num_workers_soft_limit);
+#if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
+    if (my_mandatory_num_requested > 0) {
+        __TBB_ASSERT(my_num_workers_soft_limit == 0, NULL);
+        my_num_workers_requested = 1;
+    }
+#endif
+#if __TBB_TASK_PRIORITY
+    my_priority_levels[my_global_top_priority].workers_available = my_num_workers_requested;
+    update_allotment(my_global_top_priority);
+#else
+    update_allotment();
+#endif
+    return my_num_workers_requested - old_request;
+}
+
 void market::set_active_num_workers ( unsigned soft_limit ) {
-    int old_requested=0, requested=0;
-    bool need_mandatory = false;
     market *m;
 
     {
@@ -224,65 +240,60 @@ void market::set_active_num_workers ( unsigned soft_limit ) {
         if ( !theMarket )
             return; // actual value will be used at market creation
         m = theMarket;
+        if (m->my_num_workers_soft_limit == soft_limit)
+            return;
         ++m->my_ref_count;
     }
     // have my_ref_count for market, use it safely
+
+    int delta = 0;
     {
         arenas_list_mutex_type::scoped_lock lock( m->my_arenas_list_mutex );
         __TBB_ASSERT(soft_limit <= m->my_num_workers_hard_limit, NULL);
-        m->my_num_workers_soft_limit = soft_limit;
-        // report only once after new soft limit value is set
-        m->my_workers_soft_limit_to_report = soft_limit;
 
 #if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-        // updates soft_limit to zero must be postponed
-        // while mandatory parallelism is enabled
-        if( !(m->my_mandatory_num_requested && !soft_limit) )
-#endif
-        {
-            const int demand =
-#if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-                m->my_mandatory_num_requested? 0 :
-#endif
-                m->my_total_demand;
-            requested = min(demand, (int)soft_limit);
-            old_requested = m->my_num_workers_requested;
-            m->my_num_workers_requested = requested;
 #if __TBB_TASK_PRIORITY
-            m->my_priority_levels[m->my_global_top_priority].workers_available = soft_limit;
-            m->update_allotment( m->my_global_top_priority );
+#define FOR_EACH_PRIORITY_LEVEL_BEGIN {                                                         \
+        for (int p = m->my_global_top_priority; p >= m->my_global_bottom_priority; --p) {       \
+            priority_level_info& pl = m->my_priority_levels[p];                                 \
+            arena_list_type& arenas = pl.arenas;
 #else
-            m->update_allotment();
+#define FOR_EACH_PRIORITY_LEVEL_BEGIN { {                                                       \
+            const int p = 0;                                                                    \
+            arena_list_type& arenas = m->my_arenas;
 #endif
+#define FOR_EACH_PRIORITY_LEVEL_END } }
+
+        if (m->my_num_workers_soft_limit == 0 && m->my_mandatory_num_requested > 0) {
+            FOR_EACH_PRIORITY_LEVEL_BEGIN
+                for (arena_list_type::iterator it = arenas.begin(); it != arenas.end(); ++it)
+                    if (it->my_global_concurrency_mode)
+                        m->disable_mandatory_concurrency_impl(&*it);
+            FOR_EACH_PRIORITY_LEVEL_END
         }
+        __TBB_ASSERT(m->my_mandatory_num_requested == 0, NULL);
+#endif
+
+        as_atomic(m->my_num_workers_soft_limit) = soft_limit;
+        // report only once after new soft limit value is set
+        m->my_workers_soft_limit_to_report = soft_limit;
+
 #if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-        if( !m->my_mandatory_num_requested && !soft_limit ) {
-            // enable mandatory concurrency, if enqueued tasks are found
-            // and zero soft_limit requested
-#if __TBB_TASK_PRIORITY
-            for( int p = m->my_global_top_priority; p >= m->my_global_bottom_priority; --p ) {
-                priority_level_info &pl = m->my_priority_levels[p];
-                arena_list_type &arenas = pl.arenas;
-#else
-                const int p = 0;
-                arena_list_type &arenas = m->my_arenas;
-#endif /* __TBB_TASK_PRIORITY */
-                for( arena_list_type::iterator it = arenas.begin(); it != arenas.end(); ++it ) {
-                    if( !it->my_task_stream.empty(p) ) {
-                        // switch local_mandatory to global_mandatory unconditionally
-                        if( m->mandatory_concurrency_enable_impl( &*it ) )
-                            need_mandatory = true;
-                    }
+        if (m->my_num_workers_soft_limit == 0) {
+            FOR_EACH_PRIORITY_LEVEL_BEGIN
+                for (arena_list_type::iterator it = arenas.begin(); it != arenas.end(); ++it) {
+                    if (!it->my_task_stream.empty(p))
+                        m->enable_mandatory_concurrency_impl(&*it);
                 }
-#if __TBB_TASK_PRIORITY
-            }
-#endif /* __TBB_TASK_PRIORITY */
+            FOR_EACH_PRIORITY_LEVEL_END
         }
-#endif /* __TBB_ENQUEUE_ENFORCED_CONCURRENCY */
+#undef FOR_EACH_PRIORITY_LEVEL_BEGIN
+#undef FOR_EACH_PRIORITY_LEVEL_END
+#endif
+
+        delta = m->update_workers_request();
     }
     // adjust_job_count_estimate must be called outside of any locks
-    int delta = requested - old_requested;
-    if( need_mandatory ) ++delta;
     if( delta!=0 )
         m->my_server->adjust_job_count_estimate( delta );
     // release internal market reference to match ++m->my_ref_count above
@@ -310,6 +321,9 @@ arena* market::create_arena ( int num_slots, int num_reserved_slots, size_t stac
 void market::detach_arena ( arena& a ) {
     __TBB_ASSERT( theMarket == this, "Global market instance was destroyed prematurely?" );
     __TBB_ASSERT( !a.my_slots[0].my_scheduler, NULL );
+    if (a.my_global_concurrency_mode)
+        disable_mandatory_concurrency_impl(&a);
+
     remove_arena_from_list(a);
     if ( a.my_aba_epoch == my_arenas_aba_epoch )
         ++my_arenas_aba_epoch;
@@ -365,11 +379,7 @@ arena* market::arena_in_need ( arena_list_type &arenas, arena *hint ) {
         arena& a = *it;
         if ( ++it == arenas.end() )
             it = arenas.begin();
-        if( a.num_workers_active() < a.my_num_workers_allotted
-#if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-            && !a.recall_by_mandatory_request()
-#endif
-            ) {
+        if( a.num_workers_active() < a.my_num_workers_allotted ) {
             a.my_references += arena::ref_worker;
             return &a;
         }
@@ -378,34 +388,34 @@ arena* market::arena_in_need ( arena_list_type &arenas, arena *hint ) {
 }
 
 int market::update_allotment ( arena_list_type& arenas, int workers_demand, int max_workers ) {
-    __TBB_ASSERT( workers_demand, NULL );
+    __TBB_ASSERT( workers_demand > 0, NULL );
     max_workers = min(workers_demand, max_workers);
-    int carry = 0;
     int assigned = 0;
-    arena_list_type::iterator it = arenas.begin();
-    for ( ; it != arenas.end(); ++it ) {
+    int carry = 0;
+    for (arena_list_type::iterator it = arenas.begin(); it != arenas.end(); ++it) {
         arena& a = *it;
-        if ( a.my_num_workers_requested <= 0 ) {
-            __TBB_ASSERT( !a.my_num_workers_allotted, NULL );
+        if (a.my_num_workers_requested <= 0) {
+            __TBB_ASSERT(!a.my_num_workers_allotted, NULL);
             continue;
         }
-        int tmp = a.my_num_workers_requested * max_workers + carry;
-        int allotted = tmp / workers_demand;
-        carry = tmp % workers_demand;
-        // a.my_num_workers_requested may temporarily exceed a.my_max_num_workers
-        allotted = min( allotted, (int)a.my_max_num_workers );
+        int allotted = 0;
 #if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-        if ( !allotted && a.must_have_concurrency() )
-            allotted = 1;
+        if (my_num_workers_soft_limit == 0) {
+            __TBB_ASSERT(max_workers == 0 || max_workers == 1, NULL);
+            allotted = a.my_global_concurrency_mode && assigned < max_workers ? 1 : 0;
+        } else
 #endif
+        {
+            int tmp = a.my_num_workers_requested * max_workers + carry;
+            allotted = tmp / workers_demand;
+            carry = tmp % workers_demand;
+            // a.my_num_workers_requested may temporarily exceed a.my_max_num_workers
+            allotted = min(allotted, (int)a.my_max_num_workers);
+        }
         a.my_num_workers_allotted = allotted;
         assigned += allotted;
     }
-#if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-    __TBB_ASSERT( assigned <= workers_demand, NULL ); // weaker assertion due to enforced allotment
-#else
-    __TBB_ASSERT( assigned <= max_workers, NULL );
-#endif
+    __TBB_ASSERT( 0 <= assigned && assigned <= max_workers, NULL );
     return assigned;
 }
 
@@ -470,7 +480,7 @@ void market::update_allotment ( intptr_t highest_affected_priority ) {
         pl.workers_available = available;
         if ( pl.workers_requested ) {
             available -= update_allotment( pl.arenas, pl.workers_requested, available );
-            if ( available < 0 ) { // TODO: assertion?
+            if ( available <= 0 ) { // TODO: assertion?
                 available = 0;
                 break;
             }
@@ -483,103 +493,63 @@ void market::update_allotment ( intptr_t highest_affected_priority ) {
         arena_list_type::iterator it = pl.arenas.begin();
         for ( ; it != pl.arenas.end(); ++it ) {
             __TBB_ASSERT( it->my_num_workers_requested >= 0 || !it->my_num_workers_allotted, NULL );
-#if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-            it->my_num_workers_allotted = it->must_have_concurrency() ? 1 : 0;
-#else
             it->my_num_workers_allotted = 0;
-#endif
         }
     }
 }
 #endif /* __TBB_TASK_PRIORITY */
 
 #if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-bool market::mandatory_concurrency_enable_impl ( arena *a, bool *enabled ) {
-    if( a->my_concurrency_mode==arena_base::cm_enforced_global ) {
-        if( enabled )
-            *enabled = false;
-        return false;
-    }
-    if( enabled )
-        *enabled = true;
-    a->my_max_num_workers = 1;
-    a->my_concurrency_mode = arena_base::cm_enforced_global;
-#if __TBB_TASK_PRIORITY
-    priority_level_info &pl = my_priority_levels[a->my_top_priority];
-    pl.workers_requested++;
-    if( my_global_top_priority < a->my_top_priority ) {
-        my_global_top_priority = a->my_top_priority;
-        advance_global_reload_epoch();
-    }
-#endif
-    a->my_num_workers_requested++;
-    a->my_num_workers_allotted++;
-    if( 1 == ++my_mandatory_num_requested ) {
-        my_total_demand++;
-        return true;
-    }
-    return false;
+void market::enable_mandatory_concurrency_impl ( arena *a ) {
+    __TBB_ASSERT(!a->my_global_concurrency_mode, NULL);
+    __TBB_ASSERT(my_num_workers_soft_limit == 0, NULL);
+
+    a->my_global_concurrency_mode = true;
+    my_mandatory_num_requested++;
 }
 
-bool market::mandatory_concurrency_enable ( arena *a ) {
-    bool add_thread;
-    bool enabled;
+void market::enable_mandatory_concurrency ( arena *a ) {
+    int delta = 0;
     {
         arenas_list_mutex_type::scoped_lock lock(my_arenas_list_mutex);
-        add_thread = mandatory_concurrency_enable_impl(a, &enabled);
+        if (my_num_workers_soft_limit != 0 || a->my_global_concurrency_mode)
+            return;
+
+        enable_mandatory_concurrency_impl(a);
+        delta = update_workers_request();
     }
-    if( add_thread )
-        my_server->adjust_job_count_estimate( 1 );
-    return enabled;
+
+    if (delta != 0)
+        my_server->adjust_job_count_estimate(delta);
 }
 
-void market::mandatory_concurrency_disable ( arena *a ) {
-    bool remove_thread = false;
-    int delta_adjust_demand = 0;
+void market::disable_mandatory_concurrency_impl(arena* a) {
+    __TBB_ASSERT(a->my_global_concurrency_mode, NULL);
+    __TBB_ASSERT(my_mandatory_num_requested > 0, NULL);
+
+    a->my_global_concurrency_mode = false;
+    my_mandatory_num_requested--;
+}
 
+void market::mandatory_concurrency_disable ( arena *a ) {
+    int delta = 0;
     {
         arenas_list_mutex_type::scoped_lock lock(my_arenas_list_mutex);
-
-        if( a->my_concurrency_mode!=arena_base::cm_enforced_global  )
+        if (!a->my_global_concurrency_mode)
+            return;
+        // There is a racy window in advertise_new_work between mandtory concurrency enabling and 
+        // setting SNAPSHOT_FULL. It gives a chance to spawn request to disable mandatory concurrency.
+        // Therefore, we double check that there is no enqueued tasks.
+        if (a->has_enqueued_tasks())
             return;
-        __TBB_ASSERT( a->my_max_num_workers==1, NULL );
-        a->my_max_num_workers = 0;
-#if __TBB_TASK_PRIORITY
-        if ( a->my_top_priority != normalized_normal_priority ) {
-            update_arena_top_priority( *a, normalized_normal_priority );
-        }
-        a->my_bottom_priority = normalized_normal_priority;
-#endif
 
-        int val = --my_mandatory_num_requested;
-        __TBB_ASSERT_EX( val >= 0, NULL );
-        if( val == 0 ) {
-            my_total_demand--;
-            remove_thread = true;
-        }
-        a->my_num_workers_requested--;
-        if (a->my_num_workers_requested > 0)
-            delta_adjust_demand = a->my_num_workers_requested;
-        else
-            a->my_num_workers_allotted = 0;
+        __TBB_ASSERT(my_num_workers_soft_limit == 0, NULL);
+        disable_mandatory_concurrency_impl(a);
 
-#if __TBB_TASK_PRIORITY
-        priority_level_info &pl = my_priority_levels[a->my_top_priority];
-        pl.workers_requested--;
-        intptr_t p = my_global_top_priority;
-        for (; !my_priority_levels[p].workers_requested && p>0; p--)
-            ;
-        if( !p )
-            reset_global_priority();
-        else if( p!= my_global_top_priority )
-            update_global_top_priority(p);
-#endif
-        a->my_concurrency_mode = arena::cm_normal;
+        delta = update_workers_request();
     }
-    if( delta_adjust_demand )
-        adjust_demand( *a, -delta_adjust_demand );
-    if( remove_thread )
-        my_server->adjust_job_count_estimate( -1 );
+    if (delta != 0)
+        my_server->adjust_job_count_estimate(delta);
 }
 #endif /* __TBB_ENQUEUE_ENFORCED_CONCURRENCY */
 
@@ -591,13 +561,7 @@ void market::adjust_demand ( arena& a, int delta ) {
     int prev_req = a.my_num_workers_requested;
     a.my_num_workers_requested += delta;
     if ( a.my_num_workers_requested <= 0 ) {
-#if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-        // must not recall worker from arena with mandatory parallelism
-        if ( a.my_market->my_mandatory_num_requested && a.my_concurrency_mode!=arena_base::cm_normal )
-            a.my_num_workers_allotted = 1;
-        else
-#endif
-            a.my_num_workers_allotted = 0;
+        a.my_num_workers_allotted = 0;
         if ( prev_req <= 0 ) {
             my_arenas_list_mutex.unlock();
             return;
@@ -622,6 +586,12 @@ void market::adjust_demand ( arena& a, int delta ) {
         }
         a.my_bottom_priority = normalized_normal_priority;
     }
+    unsigned effective_soft_limit = my_num_workers_soft_limit;
+    if (my_mandatory_num_requested > 0) {
+        __TBB_ASSERT(effective_soft_limit == 0, NULL);
+        effective_soft_limit = 1;
+
+    }
     if ( p == my_global_top_priority ) {
         if ( !pl.workers_requested ) {
             while ( --p >= my_global_bottom_priority && !my_priority_levels[p].workers_requested )
@@ -631,6 +601,7 @@ void market::adjust_demand ( arena& a, int delta ) {
             else
                 update_global_top_priority(p);
         }
+        my_priority_levels[my_global_top_priority].workers_available = effective_soft_limit;
         update_allotment( my_global_top_priority );
     }
     else if ( p > my_global_top_priority ) {
@@ -638,14 +609,8 @@ void market::adjust_demand ( arena& a, int delta ) {
         // TODO: investigate if the following invariant is always valid
         __TBB_ASSERT( a.my_num_workers_requested >= 0, NULL );
         update_global_top_priority(p);
-        a.my_num_workers_allotted = min( (int)my_num_workers_soft_limit, a.my_num_workers_requested );
-#if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-        // must not recall worker from arena with mandatory parallelism
-        if ( !a.my_num_workers_allotted && a.my_num_workers_requested
-             && a.my_market->my_mandatory_num_requested && a.my_concurrency_mode!=arena_base::cm_normal )
-            a.my_num_workers_allotted = 1;
-#endif
-        my_priority_levels[p - 1].workers_available = my_num_workers_soft_limit - a.my_num_workers_allotted;
+        a.my_num_workers_allotted = min( (int)effective_soft_limit, a.my_num_workers_requested );
+        my_priority_levels[p - 1].workers_available = effective_soft_limit - a.my_num_workers_allotted;
         update_allotment( p - 1 );
     }
     else if ( p == my_global_bottom_priority ) {
@@ -675,15 +640,15 @@ void market::adjust_demand ( arena& a, int delta ) {
     if ( delta > 0 ) {
         // can't overflow soft_limit, but remember values request by arenas in
         // my_total_demand to not prematurely release workers to RML
-        if ( my_num_workers_requested+delta > (int)my_num_workers_soft_limit )
-            delta = my_num_workers_soft_limit - my_num_workers_requested;
+        if ( my_num_workers_requested+delta > (int)effective_soft_limit)
+            delta = effective_soft_limit - my_num_workers_requested;
     } else {
         // the number of workers should not be decreased below my_total_demand
         if ( my_num_workers_requested+delta < my_total_demand )
-            delta = min(my_total_demand, (int)my_num_workers_soft_limit) - my_num_workers_requested;
+            delta = min(my_total_demand, (int)effective_soft_limit) - my_num_workers_requested;
     }
     my_num_workers_requested += delta;
-    __TBB_ASSERT( my_num_workers_requested <= (int)my_num_workers_soft_limit, NULL );
+    __TBB_ASSERT( my_num_workers_requested <= (int)effective_soft_limit, NULL );
 
     my_arenas_list_mutex.unlock();
     // Must be called outside of any locks
@@ -709,7 +674,7 @@ void market::process( job& j ) {
         if ( !i )
             __TBB_Yield();
     }
-    
+
     GATHER_STATISTIC( ++s.my_counters.market_roundtrips );
 }
 
@@ -736,7 +701,7 @@ void market::acknowledge_close_connection() {
     __TBB_ASSERT( index > 0, NULL );
     ITT_THREAD_SET_NAME(_T("TBB Worker Thread"));
     // index serves as a hint decreasing conflicts between workers when they migrate between arenas
-    generic_scheduler* s = generic_scheduler::create_worker( *this, index );
+    generic_scheduler* s = generic_scheduler::create_worker( *this, index, /* genuine = */ true );
 #if __TBB_TASK_GROUP_CONTEXT
     __TBB_ASSERT( index <= my_num_workers_hard_limit, NULL );
     __TBB_ASSERT( !my_workers[index - 1], NULL );
@@ -840,12 +805,7 @@ bool market::update_arena_priority ( arena& a, intptr_t new_priority ) {
                 && !my_priority_levels[my_global_bottom_priority].workers_requested )
             ++my_global_bottom_priority;
         __TBB_ASSERT( my_global_bottom_priority <= new_priority, NULL );
-#if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-        const bool enforced_concurrency = my_mandatory_num_requested && a.must_have_concurrency();
-#else
-        const bool enforced_concurrency = false;
-#endif
-        __TBB_ASSERT_EX( enforced_concurrency || my_priority_levels[my_global_bottom_priority].workers_requested > 0, NULL );
+        __TBB_ASSERT( my_priority_levels[my_global_bottom_priority].workers_requested > 0, NULL );
     }
     update_allotment( highest_affected_level );
 
index ee4e903..b611930 100644 (file)
@@ -178,6 +178,9 @@ private:
     //! Returns next arena that needs more workers, or NULL.
     arena* arena_in_need ( arena* prev_arena );
 
+    //! Recalculates the number of workers requested from RML and updates the allotment.
+    int update_workers_request();
+
     //! Recalculates the number of workers assigned to each arena at and below the specified priority.
     /** The actual number of workers servicing a particular arena may temporarily
         deviate from the calculated value. **/
@@ -233,7 +236,7 @@ private:
 
     arena* arena_in_need ( arena_list_type &arenas, arena *hint );
 
-    static int update_allotment ( arena_list_type& arenas, int total_demand, int max_workers );
+    int update_allotment ( arena_list_type& arenas, int total_demand, int max_workers );
 
     bool is_arena_in_list( arena_list_type &arenas, arena *a );
 
@@ -274,10 +277,13 @@ public:
 
 #if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
     //! Imlpementation of mandatory concurrency enabling
-    bool mandatory_concurrency_enable_impl ( arena *a, bool *enabled = NULL );
+    void enable_mandatory_concurrency_impl ( arena *a );
 
     //! Inform the master that there is an arena with mandatory concurrency
-    bool mandatory_concurrency_enable ( arena *a );
+    void enable_mandatory_concurrency ( arena *a );
+
+    //! Inform the master that the arena is no more interested in mandatory concurrency
+    void disable_mandatory_concurrency_impl(arena* a);
 
     //! Inform the master that the arena is no more interested in mandatory concurrency
     void mandatory_concurrency_disable ( arena *a );
index 9b08d40..d0d0e86 100644 (file)
@@ -32,10 +32,10 @@ namespace internal {
 //------------------------------------------------------------------------
 
 /** Defined in tbb_main.cpp **/
-extern generic_scheduler* (*AllocateSchedulerPtr)( market& );
+extern generic_scheduler* (*AllocateSchedulerPtr)( market&, bool );
 
-inline generic_scheduler* allocate_scheduler ( market& m ) {
-    return AllocateSchedulerPtr( m );
+inline generic_scheduler* allocate_scheduler ( market& m, bool genuine ) {
+    return AllocateSchedulerPtr( m, genuine);
 }
 
 #if __TBB_TASK_GROUP_CONTEXT
@@ -81,10 +81,13 @@ scheduler::~scheduler( ) {}
     #pragma warning(disable:4355)
 #endif
 
-generic_scheduler::generic_scheduler( market& m )
+generic_scheduler::generic_scheduler( market& m, bool genuine )
     : my_market(&m)
     , my_random(this)
     , my_ref_count(1)
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    , my_co_context(m.worker_stack_size(), genuine ? NULL : this)
+#endif
     , my_small_task_count(1)   // Extra 1 is a guard reference
 #if __TBB_SURVIVE_THREAD_SWITCH && TBB_USE_ASSERT
     , my_cilk_state(cs_none)
@@ -97,6 +100,15 @@ generic_scheduler::generic_scheduler( market& m )
 #if __TBB_PREVIEW_CRITICAL_TASKS
     my_properties.has_taken_critical_task = false;
 #endif
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    my_properties.genuine = genuine;
+    my_current_is_recalled = NULL;
+    my_post_resume_action = PRA_NONE;
+    my_post_resume_arg = NULL;
+    my_wait_task = NULL;
+#else
+    suppress_unused_warning(genuine);
+#endif
     my_properties.outermost = true;
 #if __TBB_TASK_PRIORITY
     my_ref_top_priority = &m.my_global_top_priority;
@@ -181,9 +193,20 @@ void generic_scheduler::init_stack_info () {
     void    *rsb_base = __TBB_get_bsp();
 #endif
     size_t  np_stack_size = 0;
+    // Points to the lowest addressable byte of a stack.
     void    *stack_limit = NULL;
+
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    if ( !my_properties.genuine ) {
+        stack_limit = my_co_context.get_stack_limit();
+        __TBB_ASSERT( (uintptr_t)stack_base > (uintptr_t)stack_limit, "stack size must be positive" );
+        // Size of the stack free part
+        stack_size = size_t((char*)stack_base - (char*)stack_limit);
+    }
+#endif
+
     pthread_attr_t  np_attr_stack;
-    if( 0 == pthread_getattr_np(pthread_self(), &np_attr_stack) ) {
+    if( !stack_limit && 0 == pthread_getattr_np(pthread_self(), &np_attr_stack) ) {
         if ( 0 == pthread_attr_getstack(&np_attr_stack, &stack_limit, &np_stack_size) ) {
 #if __TBB_ipf
             pthread_attr_t  attr_stack;
@@ -206,6 +229,8 @@ void generic_scheduler::init_stack_info () {
             // IA-64 architecture stack is split into RSE backup and memory parts
             my_rsb_stealing_threshold = (uintptr_t)((char*)rsb_base + stack_size/2);
 #endif /* __TBB_ipf */
+            // TODO: pthread_attr_getstack cannot be used with Intel(R) Cilk(TM) Plus
+            // __TBB_ASSERT( (uintptr_t)stack_base > (uintptr_t)stack_limit, "stack size must be positive" );
             // Size of the stack free part
             stack_size = size_t((char*)stack_base - (char*)stack_limit);
         }
@@ -257,8 +282,18 @@ void generic_scheduler::cleanup_local_context_list () {
 }
 #endif /* __TBB_TASK_GROUP_CONTEXT */
 
-void generic_scheduler::free_scheduler() {
+void generic_scheduler::destroy() {
+    __TBB_ASSERT(my_small_task_count == 0, "The scheduler is still in use.");
+    this->~generic_scheduler();
+#if TBB_USE_DEBUG
+    memset((void*)this, -1, sizeof(generic_scheduler));
+#endif
+    NFS_Free(this);
+}
+
+void generic_scheduler::cleanup_scheduler() {
     __TBB_ASSERT( !my_arena_slot, NULL );
+    __TBB_ASSERT( my_offloaded_tasks == NULL, NULL );
 #if __TBB_PREVIEW_CRITICAL_TASKS
     __TBB_ASSERT( !my_properties.has_taken_critical_task, "Critical tasks miscount." );
 #endif
@@ -294,7 +329,7 @@ void generic_scheduler::free_scheduler() {
     __TBB_ASSERT( my_small_task_count>=k, "my_small_task_count corrupted" );
     governor::sign_off(this);
     if( __TBB_FetchAndAddW( &my_small_task_count, -k )==k )
-        NFS_Free( this );
+        destroy();
 }
 
 task& generic_scheduler::allocate_task( size_t number_of_bytes,
@@ -395,7 +430,7 @@ void generic_scheduler::free_nonlocal_small_task( task& t ) {
     if( __TBB_FetchAndDecrementWrelease( &s.my_small_task_count )==1 ) {
         // We freed the last task allocated by scheduler s, so it's our responsibility
         // to free the scheduler.
-        NFS_Free( &s );
+        s.destroy();
     }
 }
 
@@ -949,7 +984,6 @@ inline task* generic_scheduler::get_task( size_t T )
         GATHER_STATISTIC( ++my_counters.proxies_executed );
         // Following assertion should be true because TBB 2.0 tasks never specify affinity, and hence are not proxied.
         __TBB_ASSERT( is_version_3_task( *t ), "backwards compatibility with TBB 2.0 broken" );
-        __TBB_ASSERT( my_innermost_running_task != t, NULL );
         my_innermost_running_task = t; // prepare for calling note_affinity()
 #if __TBB_TASK_ISOLATION
         // Task affinity has changed. Postpone calling note_affinity because the task pool is in invalid state.
@@ -1232,14 +1266,15 @@ inline void generic_scheduler::leave_task_pool() {
     __TBB_store_relaxed( my_arena_slot->task_pool, EmptyTaskPool );
 }
 
-generic_scheduler* generic_scheduler::create_worker( market& m, size_t index ) {
-    generic_scheduler* s = allocate_scheduler( m );
-    __TBB_ASSERT(index, "workers should have index > 0");
+generic_scheduler* generic_scheduler::create_worker( market& m, size_t index, bool genuine ) {
+    generic_scheduler* s = allocate_scheduler( m, genuine );
+    __TBB_ASSERT(!genuine || index, "workers should have index > 0");
     s->my_arena_index = index; // index is not a real slot in arena yet
     s->my_dummy_task->prefix().ref_count = 2;
     s->my_properties.type = scheduler_properties::worker;
     // Do not call init_stack_info before the scheduler is set as master or worker.
-    s->init_stack_info();
+    if (genuine)
+        s->init_stack_info();
     governor::sign_on(s);
     return s;
 }
@@ -1247,7 +1282,7 @@ generic_scheduler* generic_scheduler::create_worker( market& m, size_t index ) {
 // TODO: make it a member method
 generic_scheduler* generic_scheduler::create_master( arena* a ) {
     // add an internal market reference; the public reference is possibly added in create_arena
-    generic_scheduler* s = allocate_scheduler( market::global_market(/*is_public=*/false) );
+    generic_scheduler* s = allocate_scheduler( market::global_market(/*is_public=*/false), /* genuine = */ true );
     __TBB_ASSERT( !s->my_arena, NULL );
     __TBB_ASSERT( s->my_market, NULL );
     task& t = *s->my_dummy_task;
@@ -1266,10 +1301,12 @@ generic_scheduler* generic_scheduler::create_master( arena* a ) {
     lock.release();
 #endif /* __TBB_TASK_GROUP_CONTEXT */
     if( a ) {
-    // Master thread always occupies the first slot
+        // Master thread always occupies the first slot
         s->attach_arena( a, /*index*/0, /*is_master*/true );
-    s->my_arena_slot->my_scheduler = s;
+        s->my_arena_slot->my_scheduler = s;
+#if __TBB_TASK_GROUP_CONTEXT
         a->my_default_ctx = s->default_context(); // also transfers implied ownership
+#endif
     }
     __TBB_ASSERT( s->my_arena_index == 0, "Master thread must occupy the first slot in its arena" );
     governor::sign_on(s);
@@ -1294,7 +1331,7 @@ void generic_scheduler::cleanup_worker( void* arg, bool worker ) {
     if ( worker ) // can be called by master for worker, do not notify master twice
         the_global_observer_list.notify_exit_observers( s.my_last_global_observer, /*worker=*/true );
 #endif /* __TBB_SCHEDULER_OBSERVER */
-    s.free_scheduler();
+    s.cleanup_scheduler();
 }
 
 bool generic_scheduler::cleanup_master( bool blocking_terminate ) {
@@ -1313,6 +1350,8 @@ bool generic_scheduler::cleanup_master( bool blocking_terminate ) {
             // Master's local task pool may e.g. contain proxies of affinitized tasks.
             release_task_pool();
             __TBB_ASSERT ( governor::is_set(this), "TLS slot is cleared before the task pool cleanup" );
+            // Set refcount to make the following dispach loop infinite (it is interrupted by the cleanup logic).
+            my_dummy_task->set_ref_count(2);
             local_wait_for_all( *my_dummy_task, NULL );
             __TBB_ASSERT( !is_task_pool_published(), NULL );
             __TBB_ASSERT ( governor::is_set(this), "Other thread reused our TLS key during the task pool cleanup" );
@@ -1345,7 +1384,7 @@ bool generic_scheduler::cleanup_master( bool blocking_terminate ) {
     lock.release();
 #endif /* __TBB_TASK_GROUP_CONTEXT */
     my_arena_slot = NULL; // detached from slot
-    free_scheduler(); // do not use scheduler state after this point
+    cleanup_scheduler(); // do not use scheduler state after this point
 
     if( a )
         a->on_thread_leaving<arena::ref_external>();
index ace18db..feb1948 100644 (file)
 #include "cilk-tbb-interop.h"
 #endif /* __TBB_SURVIVE_THREAD_SWITCH */
 
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+#include "co_context.h"
+#endif
+
 namespace tbb {
 namespace internal {
 
@@ -54,13 +58,20 @@ struct scheduler_properties {
 #if __TBB_PREVIEW_CRITICAL_TASKS
     //! Indicates that a scheduler is in the process of executing critical task(s).
     bool has_taken_critical_task : 1;
-
+#endif
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    //! Indicates that the scheduler is bound to an original thread stack.
+    bool genuine : 1;
+#endif
     //! Reserved bits
-    unsigned char : 5;
+    unsigned char :
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+                    4;
+#elif __TBB_PREVIEW_CRITICAL_TASKS
+                    5;
 #else
-    //! Reserved bits
-    unsigned char : 6;
-#endif /* __TBB_PREVIEW_CRITICAL_TASKS */
+                    6;
+#endif
 };
 
 struct scheduler_state {
@@ -76,7 +87,6 @@ struct scheduler_state {
     //! Innermost task whose task::execute() is running. A dummy task on the outermost level.
     task* my_innermost_running_task;
 
-
     mail_inbox my_inbox;
 
     //! The mailbox id assigned to this scheduler.
@@ -108,6 +118,13 @@ struct scheduler_state {
     //! Pointer to market's (for workers) or current arena's (for the master) reload epoch counter.
     volatile uintptr_t *my_ref_reload_epoch;
 #endif /* __TBB_TASK_PRIORITY */
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    //! The currently waited task.
+    task* my_wait_task;
+
+    //! The currently recalled stack.
+    tbb::atomic<bool>* my_current_is_recalled;
+#endif
 };
 
 //! Work stealing task scheduler.
@@ -184,6 +201,68 @@ public: // almost every class in TBB uses generic_scheduler
     intptr_t my_task_node_count;
 #endif /* __TBB_COUNT_TASK_NODES */
 
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    //! The list of possible post resume actions.
+    enum post_resume_action {
+        PRA_INVALID,
+        PRA_ABANDON,
+        PRA_CALLBACK,
+        PRA_CLEANUP,
+        PRA_NOTIFY,
+        PRA_NONE
+    };
+
+    //! The suspend callback function type.
+    typedef void(*suspend_callback_t)(void*, task::suspend_point);
+
+    //! The callback to call the user callback passed to tbb::suspend.
+    struct callback_t {
+        suspend_callback_t suspend_callback;
+        void* user_callback;
+        task::suspend_point tag;
+
+        void operator()() {
+            if (suspend_callback) {
+                __TBB_ASSERT(suspend_callback && user_callback && tag, NULL);
+                suspend_callback(user_callback, tag);
+            }
+        }
+    };
+
+    //! The coroutine context associated with the current scheduler.
+    co_context my_co_context;
+
+    //! The post resume action requested for the current scheduler.
+    post_resume_action my_post_resume_action;
+
+    //! The post resume action argument.
+    void* my_post_resume_arg;
+
+    //! The scheduler to resume on exit.
+    generic_scheduler* my_target_on_exit;
+
+    //! Set post resume action to perform after resume.
+    void set_post_resume_action(post_resume_action, void* arg);
+
+    //! Performs post resume action.
+    void do_post_resume_action();
+
+    //! Decides how to switch and sets post resume action.
+    /** Returns false if the caller should finish the coroutine and then resume the target scheduler.
+        Returns true if the caller should resume the target scheduler immediately. **/
+    bool prepare_resume(generic_scheduler& target);
+
+    //! Resumes the original scheduler of the calling thread.
+    /** Returns false if the current stack should be left to perform the resume.
+        Returns true if the current stack is resumed. **/
+    bool resume_original_scheduler();
+
+    //! Resumes the target scheduler. The prepare_resume must be called for the target scheduler in advance.
+    void resume(generic_scheduler& target);
+
+    friend void recall_function(task::suspend_point tag);
+#endif /* __TBB_PREVIEW_RESUMABLE_TASKS */
+
     //! Sets up the data necessary for the stealing limiting heuristics
     void init_stack_info ();
 
@@ -301,14 +380,14 @@ public: // almost every class in TBB uses generic_scheduler
     bool cleanup_master( bool blocking_terminate );
 
     //! Initialize a scheduler for a worker thread.
-    static generic_scheduler* create_worker( market& m, size_t index );
+    static generic_scheduler* create_worker( market& m, size_t index, bool geniune );
 
     //! Perform necessary cleanup when a worker thread finishes.
     static void cleanup_worker( void* arg, bool worker );
 
 protected:
     template<typename SchedulerTraits> friend class custom_scheduler;
-    generic_scheduler( market & );
+    generic_scheduler( market &, bool );
 
 public:
 #if TBB_USE_ASSERT > 1
@@ -334,8 +413,11 @@ public:
     void local_spawn_root_and_wait( task* first, task*& next );
     virtual void local_wait_for_all( task& parent, task* child ) = 0;
 
-    //! Destroy and deallocate this scheduler object
-    void free_scheduler();
+    //! Destroy and deallocate this scheduler object.
+    void destroy();
+
+    //! Cleans up this scheduler (the scheduler might be destroyed).
+    void cleanup_scheduler();
 
     //! Allocate task object, either from the heap or a free list.
     /** Returns uninitialized task object with initialized prefix. */
@@ -660,7 +742,11 @@ void generic_scheduler::free_task( task& t ) {
     poison_value(p.depth);
     poison_value(p.ref_count);
     poison_pointer(p.owner);
-    __TBB_ASSERT( 1L<<t.state() & (1L<<task::executing|1L<<task::allocated), NULL );
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    __TBB_ASSERT(1L << t.state() & (1L << task::executing | 1L << task::allocated | 1 << task::to_resume), NULL);
+#else
+    __TBB_ASSERT(1L << t.state() & (1L << task::executing | 1L << task::allocated), NULL);
+#endif
     p.state = task::freed;
     if( h==small_local_task || p.origin==this ) {
         GATHER_STATISTIC(++my_counters.free_list_length);
@@ -693,11 +779,7 @@ inline intptr_t generic_scheduler::effective_reference_priority () const {
     // be trapped in a futile spinning (because market's priority would prohibit
     // executing ANY tasks in this arena).
     return !worker_outermost_level() ||
-        (my_arena->my_num_workers_allotted < my_arena->num_workers_active()
-#if __TBB_ENQUEUE_ENFORCED_CONCURRENCY
-         && my_arena->my_concurrency_mode!=arena_base::cm_enforced_global
-#endif
-            ) ? *my_ref_top_priority : my_arena->my_top_priority;
+        my_arena->my_num_workers_allotted < my_arena->num_workers_active() ? *my_ref_top_priority : my_arena->my_top_priority;
 }
 
 inline void generic_scheduler::offload_task ( task& t, intptr_t /*priority*/ ) {
@@ -712,43 +794,174 @@ inline void generic_scheduler::offload_task ( task& t, intptr_t /*priority*/ ) {
 }
 #endif /* __TBB_TASK_PRIORITY */
 
-#if __TBB_PREVIEW_CRITICAL_TASKS
-class critical_task_count_guard : internal::no_copy {
-public:
-    critical_task_count_guard(scheduler_properties& properties, task& t)
-        : my_properties(properties),
-          my_original_critical_task_state(properties.has_taken_critical_task) {
-        my_properties.has_taken_critical_task |= internal::is_critical(t);
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+inline void generic_scheduler::set_post_resume_action(post_resume_action pra, void* arg) {
+    __TBB_ASSERT(my_post_resume_action == PRA_NONE, "Post resume action has already been set.");
+    __TBB_ASSERT(!my_post_resume_arg, NULL);
+
+    my_post_resume_action = pra;
+    my_post_resume_arg = arg;
+}
+
+inline bool generic_scheduler::prepare_resume(generic_scheduler& target) {
+    // The second condition is valid for worker or cleanup operation for master
+    if (my_properties.outermost && my_wait_task == my_dummy_task) {
+        if (my_properties.genuine) {
+            // We are in someone's original scheduler.
+            target.set_post_resume_action(PRA_NOTIFY, my_current_is_recalled);
+            return true;
+        }
+        // We are in a coroutine on outermost level.
+        target.set_post_resume_action(PRA_CLEANUP, this);
+        my_target_on_exit = &target;
+        // Request to finish coroutine instead of immediate resume.
+        return false;
     }
-    ~critical_task_count_guard() {
-        my_properties.has_taken_critical_task = my_original_critical_task_state;
+    __TBB_ASSERT(my_wait_task != my_dummy_task, NULL);
+    // We are in the coroutine on a nested level.
+    my_wait_task->prefix().abandoned_scheduler = this;
+    target.set_post_resume_action(PRA_ABANDON, my_wait_task);
+    return true;
+}
+
+inline bool generic_scheduler::resume_original_scheduler() {
+    generic_scheduler& target = *my_arena_slot->my_scheduler;
+    if (!prepare_resume(target)) {
+        // We should return and finish the current coroutine.
+        return false;
+    }
+    resume(target);
+    return true;
+}
+
+inline void generic_scheduler::resume(generic_scheduler& target) {
+    // Do not create non-trivial objects on the stack of this function. They might never be destroyed.
+    __TBB_ASSERT(governor::is_set(this), NULL);
+    __TBB_ASSERT(target.my_post_resume_action != PRA_NONE,
+        "The post resume action is not set. Has prepare_resume been called?");
+    __TBB_ASSERT(target.my_post_resume_arg, NULL);
+    __TBB_ASSERT(&target != this, NULL);
+    __TBB_ASSERT(target.my_arena == my_arena, "Cross-arena switch is forbidden.");
+
+    // Transfer thread related data.
+    target.my_arena_index = my_arena_index;
+    target.my_arena_slot = my_arena_slot;
+    target.attach_mailbox(affinity_id(target.my_arena_index + 1));
+
+#if __TBB_TASK_PRIORITY
+    if (my_offloaded_tasks)
+        my_arena->orphan_offloaded_tasks(*this);
+#endif /* __TBB_TASK_PRIORITY */
+
+    governor::assume_scheduler(&target);
+    my_co_context.resume(target.my_co_context);
+    __TBB_ASSERT(governor::is_set(this), NULL);
+
+    do_post_resume_action();
+    if (this == my_arena_slot->my_scheduler) {
+        my_arena_slot->my_scheduler_is_recalled->store<tbb::relaxed>(false);
+    }
+}
+
+inline void generic_scheduler::do_post_resume_action() {
+    __TBB_ASSERT(my_post_resume_action != PRA_NONE, "The post resume action is not set.");
+    __TBB_ASSERT(my_post_resume_arg, NULL);
+
+    switch (my_post_resume_action) {
+    case PRA_ABANDON:
+    {
+        task_prefix& wait_task_prefix = static_cast<task*>(my_post_resume_arg)->prefix();
+        reference_count old_ref_count = __TBB_FetchAndAddW(&wait_task_prefix.ref_count, internal::abandon_flag);
+        __TBB_ASSERT(old_ref_count > 0, NULL);
+        if (old_ref_count == 1) {
+            // Remove the abandon flag.
+            __TBB_store_with_release(wait_task_prefix.ref_count, 1);
+            // The wait has been completed. Spawn a resume task.
+            tbb::task::resume(wait_task_prefix.abandoned_scheduler);
+        }
+        break;
+    }
+    case PRA_CALLBACK:
+    {
+        callback_t callback = *static_cast<callback_t*>(my_post_resume_arg);
+        callback();
+        break;
+    }
+    case PRA_CLEANUP:
+    {
+        generic_scheduler* to_cleanup = static_cast<generic_scheduler*>(my_post_resume_arg);
+        __TBB_ASSERT(!to_cleanup->my_properties.genuine, NULL);
+        // Release coroutine's reference to my_arena.
+        to_cleanup->my_arena->on_thread_leaving<arena::ref_external>();
+        // Cache the coroutine for possible later re-usage
+        to_cleanup->my_arena->my_co_cache.push(to_cleanup);
+        break;
+    }
+    case PRA_NOTIFY:
+    {
+        tbb::atomic<bool>& scheduler_recall_flag = *static_cast<tbb::atomic<bool>*>(my_post_resume_arg);
+        scheduler_recall_flag = true;
+        // Do not access recall_flag because it can be destroyed after the notification.
+        break;
+    }
+    default:
+        __TBB_ASSERT(false, NULL);
+    }
+
+    my_post_resume_action = PRA_NONE;
+    my_post_resume_arg = NULL;
+}
+
+struct recall_functor {
+    tbb::atomic<bool>* scheduler_recall_flag;
+
+    recall_functor(tbb::atomic<bool>* recall_flag_) :
+        scheduler_recall_flag(recall_flag_) {}
+
+    void operator()(task::suspend_point /*tag*/) {
+        *scheduler_recall_flag = true;
     }
-private:
-    scheduler_properties& my_properties;
-    bool my_original_critical_task_state;
 };
-#endif /* __TBB_PREVIEW_CRITICAL_TASKS */
 
-#if __TBB_FP_CONTEXT || __TBB_TASK_GROUP_CONTEXT
+#if _WIN32
+/* [[noreturn]] */ inline void __stdcall co_local_wait_for_all(void* arg) {
+#else
+/* [[noreturn]] */ inline void co_local_wait_for_all(void* arg) {
+#endif
+    // Do not create non-trivial objects on the stack of this function. They will never be destroyed.
+    generic_scheduler& s = *static_cast<generic_scheduler*>(arg);
+    __TBB_ASSERT(governor::is_set(&s), NULL);
+    // For correct task stealing threshold, calculate stack on a coroutine start
+    s.init_stack_info();
+    // Basically calls the user callback passed to the tbb::task::suspend function
+    s.do_post_resume_action();
+    // Endless loop here because coroutine could be reused
+    for( ;; ) {
+        __TBB_ASSERT(s.my_innermost_running_task == s.my_dummy_task, NULL);
+        __TBB_ASSERT(s.worker_outermost_level(), NULL);
+        s.local_wait_for_all(*s.my_dummy_task, NULL);
+        __TBB_ASSERT(s.my_target_on_exit, NULL);
+        __TBB_ASSERT(s.my_wait_task == NULL, NULL);
+        s.resume(*s.my_target_on_exit);
+    }
+    // This code is unreachable
+}
+#endif /* __TBB_PREVIEW_RESUMABLE_TASKS */
+
+#if __TBB_TASK_GROUP_CONTEXT
 //! Helper class for tracking floating point context and task group context switches
 /** Assuming presence of an itt collector, in addition to keeping track of floating
     point context, this class emits itt events to indicate begin and end of task group
     context execution **/
 template <bool report_tasks>
 class context_guard_helper {
-#if __TBB_TASK_GROUP_CONTEXT
     const task_group_context *curr_ctx;
-#endif
 #if __TBB_FP_CONTEXT
     cpu_ctl_env guard_cpu_ctl_env;
     cpu_ctl_env curr_cpu_ctl_env;
 #endif
 public:
-    context_guard_helper()
-#if __TBB_TASK_GROUP_CONTEXT
-        : curr_ctx(NULL)
-#endif
-    {
+    context_guard_helper() : curr_ctx( NULL ) {
 #if __TBB_FP_CONTEXT
         guard_cpu_ctl_env.get_env();
         curr_cpu_ctl_env = guard_cpu_ctl_env;
@@ -759,38 +972,31 @@ public:
         if ( curr_cpu_ctl_env != guard_cpu_ctl_env )
             guard_cpu_ctl_env.set_env();
 #endif
-#if __TBB_TASK_GROUP_CONTEXT
-        if (report_tasks && curr_ctx)
+        if ( report_tasks && curr_ctx )
             ITT_TASK_END;
-#endif
     }
+    // The function is called from bypass dispatch loop on the hot path.
+    // Consider performance issues when refactoring.
     void set_ctx( const task_group_context *ctx ) {
-        generic_scheduler::assert_context_valid(ctx);
-#if __TBB_FP_CONTEXT
-        const cpu_ctl_env &ctl = *punned_cast<cpu_ctl_env*>(&ctx->my_cpu_ctl_env);
-#endif
-#if __TBB_TASK_GROUP_CONTEXT
-        if(ctx != curr_ctx) {
-#endif
+        generic_scheduler::assert_context_valid( ctx );
 #if __TBB_FP_CONTEXT
-            if ( ctl != curr_cpu_ctl_env ) {
-                curr_cpu_ctl_env = ctl;
-                curr_cpu_ctl_env.set_env();
-            }
+        const cpu_ctl_env &ctl = *punned_cast<cpu_ctl_env*>( &ctx->my_cpu_ctl_env );
+        // Compare the FPU settings directly because the context can be reused between parallel algorithms.
+        if ( ctl != curr_cpu_ctl_env ) {
+            curr_cpu_ctl_env = ctl;
+            curr_cpu_ctl_env.set_env();
+        }
 #endif
-#if __TBB_TASK_GROUP_CONTEXT
+        if ( report_tasks && ctx != curr_ctx ) {
             // if task group context was active, report end of current execution frame.
-            if (report_tasks) {
-                if (curr_ctx)
-                    ITT_TASK_END;
-                // reporting begin of new task group context execution frame.
-                // using address of task group context object to group tasks (parent).
-                // id of task execution frame is NULL and reserved for future use.
-                ITT_TASK_BEGIN(ctx,ctx->my_name,NULL);
-                curr_ctx = ctx;
-            }
+            if ( curr_ctx )
+                ITT_TASK_END;
+            // reporting begin of new task group context execution frame.
+            // using address of task group context object to group tasks (parent).
+            // id of task execution frame is NULL and reserved for future use.
+            ITT_TASK_BEGIN( ctx,ctx->my_name, NULL );
+            curr_ctx = ctx;
         }
-#endif
     }
     void restore_default() {
 #if __TBB_FP_CONTEXT
@@ -804,10 +1010,10 @@ public:
 #else
 template <bool T>
 struct context_guard_helper {
-    void set_ctx( __TBB_CONTEXT_ARG1(task_group_context *) ) {}
+    void set_ctx() {}
     void restore_default() {}
 };
-#endif /* __TBB_FP_CONTEXT */
+#endif /* __TBB_TASK_GROUP_CONTEXT */
 
 } // namespace internal
 } // namespace tbb
index 19c494e..a44f35c 100644 (file)
@@ -220,6 +220,7 @@ inline void assert_task_valid( const task* task ) {
     __TBB_ASSERT( task!=NULL, NULL );
     __TBB_ASSERT( !is_poisoned(&task), NULL );
     __TBB_ASSERT( (uintptr_t)task % task_alignment == 0, "misaligned task" );
+    __TBB_ASSERT( task->prefix().ref_count >= 0, NULL);
 #if __TBB_RECYCLE_TO_ENQUEUE
     __TBB_ASSERT( (unsigned)task->state()<=(unsigned)task::to_enqueue, "corrupt task (invalid state)" );
 #else
@@ -340,6 +341,11 @@ struct arena_slot_line1 {
     //! Index of the first ready task in the deque.
     /** Modified by thieves, and by the owner during compaction/reallocation **/
     __TBB_atomic size_t head;
+
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+    //! The flag is raised when the original owner of the scheduler should return to this scheduler (for resume).
+    tbb::atomic<bool>* my_scheduler_is_recalled;
+#endif
 };
 
 struct arena_slot_line2 {
@@ -359,7 +365,7 @@ struct arena_slot_line2 {
     //! Capacity of the primary task pool (number of elements - pointers to task).
     size_t my_task_pool_size;
 
-    // Task pool of the scheduler that owns this slot
+    //! Task pool of the scheduler that owns this slot
     task* *__TBB_atomic task_pool_ptr;
 
 #if __TBB_STATISTICS
index 18ccc51..5fb1b28 100644 (file)
@@ -37,6 +37,7 @@ static const char _pad[NFS_MaxLineSize - sizeof(int)] = {};
 // governor data
 basic_tls<uintptr_t> governor::theTLS;
 unsigned governor::DefaultNumberOfThreads;
+size_t governor::DefaultPageSize;
 rml::tbb_factory governor::theRMLServerFactory;
 bool governor::UsePrivateRML;
 bool governor::is_speculation_enabled;
@@ -71,7 +72,7 @@ bool __TBB_InitOnce::InitializationDone;
 // generic_scheduler data
 
 //! Pointer to the scheduler factory function
-generic_scheduler* (*AllocateSchedulerPtr)( market& );
+generic_scheduler* (*AllocateSchedulerPtr)( market&, bool );
 
 #if __TBB_OLD_PRIMES_RNG
 //! Table of primes used by fast random-number generator (FastRandom).
@@ -229,6 +230,8 @@ void DoOneTimeInitializations() {
         Scheduler_OneTimeInitialization( itt_present );
         // Force processor groups support detection
         governor::default_num_threads();
+        // Force OS regular page size detection
+        governor::default_page_size();
         // Dump version data
         governor::print_version_info();
         PrintExtraVersionInfo( "Tools support", itt_present ? "enabled" : "disabled" );
@@ -337,6 +340,21 @@ void itt_metadata_str_add_v7( itt_domain_enum domain, void *addr, unsigned long
     }
 }
 
+void itt_metadata_ptr_add_v11( itt_domain_enum domain, void *addr, unsigned long long addr_extra,
+                              string_index key, void *value ) {
+    if ( __itt_domain *d = get_itt_domain( domain ) ) {
+        __itt_id id = itt_null_id;
+        itt_id_make( &id, addr, addr_extra );
+        __itt_string_handle *k = ITT_get_string_handle(key);
+#if __TBB_x86_32
+        ITTNOTIFY_VOID_D5(metadata_add, d, id, k, __itt_metadata_u32, 1, value);
+#else
+        ITTNOTIFY_VOID_D5(metadata_add, d, id, k, __itt_metadata_u64, 1, value);
+#endif 
+    }
+}
+
+
 void itt_relation_add_v7( itt_domain_enum domain, void *addr0, unsigned long long addr0_extra,
                           itt_relation relation, void *addr1, unsigned long long addr1_extra ) {
     if ( __itt_domain *d = get_itt_domain( domain ) ) {
@@ -402,6 +420,9 @@ void itt_metadata_str_add_v7( itt_domain_enum /*domain*/, void* /*addr*/, unsign
 void itt_relation_add_v7( itt_domain_enum /*domain*/, void* /*addr0*/, unsigned long long /*addr0_extra*/,
                           itt_relation /*relation*/, void* /*addr1*/, unsigned long long /*addr1_extra*/ ) { }
 
+void itt_metadata_ptr_add_v11( itt_domain_enum /*domain*/, void * /*addr*/, unsigned long long /*addr_extra*/,
+                              string_index /*key*/, void * /*value*/ ) {}
+
 void itt_task_begin_v7( itt_domain_enum /*domain*/, void* /*task*/, unsigned long long /*task_extra*/,
                         void* /*parent*/, unsigned long long /*parent_extra*/, string_index /*name_index*/ ) { }
 
index 1e71cdc..2b39d1c 100644 (file)
 #include "tbb/machine/windows_api.h"
 #endif
 
+#if !_WIN32
+#include <unistd.h> // sysconf(_SC_PAGESIZE)
+#endif
+
 #define __TBB_STD_RETHROW_EXCEPTION_POSSIBLY_BROKEN                             \
     (__GLIBCXX__ && __TBB_GLIBCXX_VERSION>=40700 && __TBB_GLIBCXX_VERSION<60000 \
      && TBB_USE_EXCEPTIONS && !TBB_USE_CAPTURED_EXCEPTION)
@@ -63,6 +67,15 @@ namespace internal {
     #define DO_THROW(exc, init_args) PRINT_ERROR_AND_ABORT(#exc, #init_args)
 #endif /* !TBB_USE_EXCEPTIONS */
 
+size_t DefaultSystemPageSize() {
+#if _WIN32
+    SYSTEM_INFO si;
+    GetSystemInfo(&si);
+    return si.dwPageSize;
+#else
+    return sysconf(_SC_PAGESIZE);
+#endif
+}
 
 /* The "what" should be fairly short, not more than about 128 characters.
    Because we control all the call sites to handle_perror, it is pointless
index 6042bb5..632a632 100644 (file)
@@ -62,6 +62,8 @@ inline int AvailableHwConcurrency() {
 }
 #endif /* __TBB_HardwareConcurrency */
 
+//! Returns OS regular memory page size
+size_t DefaultSystemPageSize();
 
 #if _WIN32||_WIN64
 
index a6c4b78..03bc710 100644 (file)
@@ -141,6 +141,7 @@ __TBB_SYMBOL( ?itt_task_begin_v7@internal@tbb@@YAXW4itt_domain_enum@12@PAX_K12W4
 __TBB_SYMBOL( ?itt_task_end_v7@internal@tbb@@YAXW4itt_domain_enum@12@@Z )
 __TBB_SYMBOL( ?itt_region_begin_v9@internal@tbb@@YAXW4itt_domain_enum@12@PAX_K12W4string_index@12@@Z )
 __TBB_SYMBOL( ?itt_region_end_v9@internal@tbb@@YAXW4itt_domain_enum@12@PAX_K@Z )
+__TBB_SYMBOL( ?itt_metadata_ptr_add_v11@internal@tbb@@YAXW4itt_domain_enum@12@PAX_KW4string_index@12@1@Z )
 
 // pipeline.cpp
 __TBB_SYMBOL( ??0pipeline@tbb@@QAE@XZ )
@@ -335,4 +336,10 @@ __TBB_SYMBOL( ?active_value@global_control@interface9@tbb@@CAIH@Z )
 __TBB_SYMBOL( ?internal_create@global_control@interface9@tbb@@AAEXXZ )
 __TBB_SYMBOL( ?internal_destroy@global_control@interface9@tbb@@AAEXXZ )
 
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+__TBB_SYMBOL( ?internal_suspend@internal@tbb@@YAXPAX0@Z )
+__TBB_SYMBOL( ?internal_resume@internal@tbb@@YAXPAX@Z )
+__TBB_SYMBOL( ?internal_current_suspend_point@internal@tbb@@YAPAXXZ )
+#endif
+
 #undef __TBB_SYMBOL
index 452c137..b48ae31 100644 (file)
@@ -169,7 +169,7 @@ __TBB_SYMBOL( _ZN3tbb8internal17itt_task_begin_v7ENS0_15itt_domain_enumEPvyS2_yN
 __TBB_SYMBOL( _ZN3tbb8internal15itt_task_end_v7ENS0_15itt_domain_enumE )
 __TBB_SYMBOL( _ZN3tbb8internal19itt_region_begin_v9ENS0_15itt_domain_enumEPvyS2_yNS0_12string_indexE )
 __TBB_SYMBOL( _ZN3tbb8internal17itt_region_end_v9ENS0_15itt_domain_enumEPvy )
-
+__TBB_SYMBOL( _ZN3tbb8internal24itt_metadata_ptr_add_v11ENS0_15itt_domain_enumEPvyNS0_12string_indexES2_ )
 
 /* pipeline.cpp */
 __TBB_SYMBOL( _ZTIN3tbb6filterE )
@@ -385,4 +385,10 @@ __TBB_SYMBOL( _ZN3tbb10interface914global_control12active_valueEi )
 __TBB_SYMBOL( _ZN3tbb10interface914global_control15internal_createEv )
 __TBB_SYMBOL( _ZN3tbb10interface914global_control16internal_destroyEv )
 
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+__TBB_SYMBOL( _ZN3tbb8internal16internal_suspendEPvS1_ )
+__TBB_SYMBOL( _ZN3tbb8internal15internal_resumeEPv )
+__TBB_SYMBOL( _ZN3tbb8internal30internal_current_suspend_pointEv )
+#endif
+
 #undef __TBB_SYMBOL
index b044bbe..d28ca54 100644 (file)
@@ -136,6 +136,7 @@ __TBB_SYMBOL( ?itt_task_begin_v7@internal@tbb@@YAXW4itt_domain_enum@12@PEAX_K12W
 __TBB_SYMBOL( ?itt_task_end_v7@internal@tbb@@YAXW4itt_domain_enum@12@@Z )
 __TBB_SYMBOL( ?itt_region_begin_v9@internal@tbb@@YAXW4itt_domain_enum@12@PEAX_K12W4string_index@12@@Z )
 __TBB_SYMBOL( ?itt_region_end_v9@internal@tbb@@YAXW4itt_domain_enum@12@PEAX_K@Z )
+__TBB_SYMBOL( ?itt_metadata_ptr_add_v11@internal@tbb@@YAXW4itt_domain_enum@12@PEAX_KW4string_index@12@1@Z )
 
 // pipeline.cpp
 __TBB_SYMBOL( ??_7pipeline@tbb@@6B@ )
@@ -330,4 +331,10 @@ __TBB_SYMBOL( ?active_value@global_control@interface9@tbb@@CA_KH@Z )
 __TBB_SYMBOL( ?internal_create@global_control@interface9@tbb@@AEAAXXZ )
 __TBB_SYMBOL( ?internal_destroy@global_control@interface9@tbb@@AEAAXXZ )
 
+#if __TBB_PREVIEW_RESUMABLE_TASKS
+__TBB_SYMBOL( ?internal_suspend@internal@tbb@@YAXPEAX0@Z )
+__TBB_SYMBOL( ?internal_resume@internal@tbb@@YAXPEAX@Z )
+__TBB_SYMBOL( ?internal_current_suspend_point@internal@tbb@@YAPEAXXZ )
+#endif
+
 #undef __TBB_SYMBOL
index ed47a36..20a5d19 100644 (file)
@@ -443,6 +443,25 @@ int main(int argc, char* argv[]) {
 
 #endif /* !HARNESS_CUSTOM_MAIN */
 
+#if __TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT
+
+//! Base class for types that should not be assigned.
+class NoAssign {
+public:
+    void operator=( const NoAssign& ) = delete;
+    NoAssign( const NoAssign& ) = default;
+    NoAssign() = default;
+};
+
+//! Base class for types that should not be copied or assigned.
+class NoCopy: NoAssign {
+public:
+    NoCopy( const NoCopy& ) = delete;
+    NoCopy() = default;
+};
+
+#else /*__TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT*/
+
 //! Base class for prohibiting compiler-generated operator=
 class NoAssign {
     //! Assignment not allowed
@@ -459,6 +478,8 @@ public:
     NoCopy() {}
 };
 
+#endif /*__TBB_DEFAULTED_AND_DELETED_FUNC_PRESENT*/
+
 #if __TBB_CPP11_RVALUE_REF_PRESENT
 #include <utility>
 
index 1ba4e69..68a5a10 100644 (file)
@@ -292,7 +292,7 @@ struct harness_counting_receiver : public tbb::flow::receiver<T>, NoAssign {
        num_copies = c;
     }
 
-    tbb::flow::graph& graph_reference() __TBB_override {
+    tbb::flow::graph& graph_reference() const __TBB_override {
         return my_graph;
     }
 
@@ -362,7 +362,7 @@ struct harness_mapped_receiver : public tbb::flow::receiver<T>, NoCopy {
       return const_cast<tbb::task *>(SUCCESSFULLY_ENQUEUED);
     }
 
-    tbb::flow::graph& graph_reference() __TBB_override {
+    tbb::flow::graph& graph_reference() const __TBB_override {
         return my_graph;
     }
 
index 3e4985b..7e536e4 100644 (file)
@@ -44,6 +44,11 @@ class ClassWithVectorType {
 public:
     ClassWithVectorType() {init(-n);}
     ClassWithVectorType( int i ) {init(i);}
+    ClassWithVectorType( const ClassWithVectorType& src ) {
+        for( int i=0; i<n; ++i ) {
+            field[i] = src.field[i];
+        }
+    }
     void operator=( const ClassWithVectorType& src ) {
         __Mvec stack[n];
         for( int i=0; i<n; ++i )
index 96e9dad..0dac4ce 100644 (file)
@@ -44,8 +44,15 @@ struct Foo {
     }
     Foo( const Foo& x ) {
         *this = x;
+        //Internal call of assignment
+    }
+    Foo& operator=( const Foo& x ) {
+        for (size_t i = 0; i < N; i++)
+            foo_array[i] = x.foo_array[i];
         ++NumberOfFoo;
+        return *this;
     }
+
     ~Foo() {
         --NumberOfFoo;
     }
index 76d9d3b..470eab9 100644 (file)
@@ -409,13 +409,13 @@ static bool testChaining() {
 namespace testFunctionsAvailabilityNS {
 
 using namespace tbb::flow;
-using tbb::flow::interface10::internal::untyped_sender;
-using tbb::flow::interface10::internal::untyped_receiver;
+using tbb::flow::interface11::internal::untyped_sender;
+using tbb::flow::interface11::internal::untyped_receiver;
 
 using tbb::internal::is_same_type;
 using tbb::internal::strip;
-using tbb::flow::interface10::internal::wrap_tuple_elements;
-using tbb::flow::interface10::internal::async_helpers;
+using tbb::flow::interface11::internal::wrap_tuple_elements;
+using tbb::flow::interface11::internal::async_helpers;
 
 class A {}; // Any type (usually called 'T')
 struct ImpossibleType {};
index e6d33a9..dc3a097 100644 (file)
@@ -688,6 +688,129 @@ int run_test_equeueing_on_inner_level() {
     return Harness::Done;
 }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+#include <array>
+#include <thread>
+
+template<typename NodeType>
+class AsyncActivity {
+public:
+    using gateway_t = typename NodeType::gateway_type;
+
+    struct work_type {
+        int input;
+        gateway_t* gateway;
+    };
+
+    AsyncActivity(size_t limit) : thr([this]() {
+        while(!end_of_work()) {
+            work_type w;
+            while( my_q.try_pop(w) ) {
+                int res = do_work(w.input);
+                w.gateway->try_put(res);
+                w.gateway->release_wait();
+                ++c;
+            }
+        }
+    }), stop_limit(limit), c(0) {}
+
+    void submit(int i, gateway_t* gateway) {
+        work_type w = {i, gateway};
+        gateway->reserve_wait();
+        my_q.push(w);
+    }
+
+    void wait_for_all() { thr.join(); }
+
+private:
+    bool end_of_work() { return c >= stop_limit; }
+
+    int do_work(int& i) { return i + i; }
+
+    tbb::concurrent_queue<work_type> my_q;
+    tbb::tbb_thread thr;
+    size_t stop_limit;
+    size_t c;
+};
+
+void test_follows() {
+    using namespace tbb::flow;
+
+    using input_t = int;
+    using output_t = int;
+    using node_t = async_node<input_t, output_t>;
+
+    graph g;
+
+    AsyncActivity<node_t> async_activity(3);
+
+    std::array<broadcast_node<input_t>, 3> preds = {
+        broadcast_node<input_t>(g),
+        broadcast_node<input_t>(g),
+        broadcast_node<input_t>(g)
+    };
+
+    node_t node(follows(preds[0], preds[1], preds[2]), unlimited, [&](int input, node_t::gateway_type& gtw) {
+        async_activity.submit(input, &gtw);
+    });
+
+    buffer_node<output_t> buf(g);
+    make_edge(node, buf);
+
+    for(auto& pred: preds) {
+        pred.try_put(1);
+    }
+
+    g.wait_for_all();
+    async_activity.wait_for_all();
+
+    output_t storage;
+    ASSERT((buf.try_get(storage) && buf.try_get(storage) && buf.try_get(storage) && !buf.try_get(storage)),
+            "Not exact edge quantity was made");
+}
+
+void test_precedes() {
+    using namespace tbb::flow;
+
+    using input_t = int;
+    using output_t = int;
+    using node_t = async_node<input_t, output_t>;
+
+    graph g;
+
+    AsyncActivity<node_t> async_activity(1);
+
+    std::array<buffer_node<input_t>, 2> successors = {
+        buffer_node<input_t>(g),
+        buffer_node<input_t>(g)
+    };
+
+    broadcast_node<input_t> start(g);
+
+    node_t node(precedes(successors[0], successors[1]), unlimited, [&](int input, node_t::gateway_type& gtw) {
+        async_activity.submit(input, &gtw);
+    });
+
+    make_edge(start, node);
+
+    start.try_put(1);
+
+    g.wait_for_all();
+    async_activity.wait_for_all();
+
+    for(auto& successor : successors) {
+        output_t storage;
+        ASSERT(successor.try_get(storage) && !successor.try_get(storage),
+               "Not exact edge quantity was made");
+    }
+}
+
+void test_follows_and_precedes_api() {
+    test_follows();
+    test_precedes();
+}
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
 int TestMain() {
     tbb::task_scheduler_init init(4);
     run_tests<int, int>();
@@ -700,6 +823,9 @@ int TestMain() {
     test_copy_ctor();
     test_for_spin_avoidance();
     run_test_equeueing_on_inner_level();
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    test_follows_and_precedes_api();
+#endif
     return Harness::Done;
 }
 
index 362419b..82a6634 100644 (file)
     limitations under the License.
 */
 
-#include "harness.h"
-
 #if __TBB_CPF_BUILD
 #define TBB_DEPRECATED_FLOW_NODE_EXTRACTION 1
 #endif
 
+#include "harness.h"
+
 #include "tbb/flow_graph.h"
 #include "tbb/task.h"
 #include "tbb/atomic.h"
+#include "test_follows_and_precedes_api.h"
 
 const int N = 1000;
 const int R = 4;
@@ -62,7 +63,7 @@ public:
         return const_cast<tbb::task *>(tbb::flow::internal::SUCCESSFULLY_ENQUEUED);
     }
 
-    tbb::flow::graph& graph_reference() __TBB_override {
+    tbb::flow::graph& graph_reference() const __TBB_override {
         return my_graph;
     }
 
@@ -316,6 +317,43 @@ void test_extract() {
 }
 #endif  // TBB_DEPRECATED_FLOW_NODE_EXTRACTION
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+#include <array>
+#include <vector>
+void test_follows_and_precedes_api() {
+    using msg_t = tbb::flow::continue_msg;
+
+    std::array<msg_t, 3> messages_for_follows= {msg_t(), msg_t(), msg_t()};
+    std::vector<msg_t> messages_for_precedes = {msg_t()};
+
+    follows_and_precedes_testing::test_follows <msg_t, tbb::flow::broadcast_node<msg_t>>(messages_for_follows);
+    follows_and_precedes_testing::test_precedes <msg_t, tbb::flow::broadcast_node<msg_t>>(messages_for_precedes);
+}
+#endif
+
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+void test_deduction_guides() {
+    using namespace tbb::flow;
+
+    graph g;
+
+    broadcast_node<int> b0(g);
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    buffer_node<int> buf(g);
+
+    broadcast_node b1(follows(buf));
+    static_assert(std::is_same_v<decltype(b1), broadcast_node<int>>);
+
+    broadcast_node b2(precedes(buf));
+    static_assert(std::is_same_v<decltype(b2), broadcast_node<int>>);
+#endif
+
+    broadcast_node b3(b0);
+    static_assert(std::is_same_v<decltype(b3), broadcast_node<int>>);
+    g.wait_for_all();
+}
+#endif
+
 int TestMain() {
     if( MinThread<1 ) {
         REPORT("number of threads must be positive\n");
@@ -335,8 +373,13 @@ int TestMain() {
    test_resets<int>();
    test_resets<float>();
 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
-   test_extract();
+    test_extract();
+#endif
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    test_follows_and_precedes_api();
+#endif
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+    test_deduction_guides();
 #endif
-
    return Harness::Done;
 }
index c2a8f09..b5ec373 100644 (file)
     limitations under the License.
 */
 
-#include "harness.h"
-
 #if __TBB_CPF_BUILD
 #define TBB_DEPRECATED_FLOW_NODE_EXTRACTION 1
 #endif
 
+#include "harness.h"
 #include "harness_graph.h"
 
 #include "tbb/task_scheduler_init.h"
 #include "tbb/tick_count.h"
+#include "test_follows_and_precedes_api.h"
 
 #define N 1000
 #define C 10
@@ -424,6 +424,41 @@ int test_serial() {
     return 0;
 }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+#include <array>
+#include <vector>
+void test_follow_and_precedes_api() {
+    using msg_t = tbb::flow::continue_msg;
+
+    std::array<msg_t, 3> messages_for_follows = {msg_t(), msg_t(), msg_t()};
+    std::vector<msg_t> messages_for_precedes = {msg_t(), msg_t(), msg_t()};
+
+    follows_and_precedes_testing::test_follows<msg_t, tbb::flow::buffer_node<msg_t>>(messages_for_follows);
+    follows_and_precedes_testing::test_precedes<msg_t, tbb::flow::buffer_node<msg_t>>(messages_for_precedes);
+}
+#endif
+
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+void test_deduction_guides() {
+    using namespace tbb::flow;
+    graph g;
+    broadcast_node<int> br(g);
+    buffer_node<int> b0(g);
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    buffer_node b1(follows(br));
+    static_assert(std::is_same_v<decltype(b1), buffer_node<int>>);
+
+    buffer_node b2(precedes(br));
+    static_assert(std::is_same_v<decltype(b2), buffer_node<int>>);
+#endif
+
+    buffer_node b3(b0);
+    static_assert(std::is_same_v<decltype(b3), buffer_node<int>>);
+    g.wait_for_all();
+}
+#endif
+
 int TestMain() {
     tbb::tick_count start = tbb::tick_count::now(), stop;
     for (int p = 2; p <= 4; ++p) {
@@ -438,5 +473,11 @@ int TestMain() {
 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
     test_buffer_extract<tbb::flow::buffer_node<int> >().run_tests();
 #endif
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    test_follow_and_precedes_api();
+#endif
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+    test_deduction_guides();
+#endif
     return Harness::Done;
 }
index e288f6b..4d6e0b9 100644 (file)
@@ -102,10 +102,6 @@ class CombineEachHelper {
 public:
     CombineEachHelper(T& _result) : my_result(_result) {}
     void operator()(const T& new_bit) { my_result +=  new_bit; }
-    CombineEachHelper& operator=(const CombineEachHelper& other) {
-        my_result =  other;
-        return *this;
-    }
 private:
     T& my_result;
 };
@@ -115,11 +111,6 @@ class CombineEachHelperCnt {
 public:
     CombineEachHelperCnt(T& _result, int& _nbuckets) : my_result(_result), nBuckets(_nbuckets) {}
     void operator()(const T& new_bit) { my_result +=  new_bit; ++nBuckets; }
-    CombineEachHelperCnt& operator=(const CombineEachHelperCnt& other) {
-        my_result =  other.my_result;
-        nBuckets = other.nBuckets;
-        return *this;
-    }
 private:
     T& my_result;
     int& nBuckets;
@@ -135,10 +126,6 @@ public:
             my_result +=  *ci;
         }
     }
-    CombineEachVectorHelper& operator=(const CombineEachVectorHelper& other) {
-        my_result=other.my_result;
-        return *this;
-    }
 
 private:
     T& my_result;
index 614a0df..4438792 100644 (file)
@@ -239,6 +239,31 @@ void CheckMultiMap(MultiMap &m, int *targets, int tcount, int key) {
 }
 
 template <typename MultiMap>
+void MultiMapEraseTests(){
+    MultiMap cont1, cont2;
+
+    typename MultiMap::iterator erased_it;
+    for (int i = 0; i < 10; ++i) {
+        if ( i != 1 ) {
+            cont1.emplace(1, i);
+            cont2.emplace(1, i);
+        } else {
+            erased_it = cont1.emplace(1, i).first;
+        }
+    }
+
+    cont1.unsafe_erase(erased_it);
+
+    ASSERT(cont1.size() == cont2.size(), "Incorrect count of elements was erased");
+    typename MultiMap::iterator it1 = cont1.begin();
+    typename MultiMap::iterator it2 = cont2.begin();
+    
+    for (typename MultiMap::size_type i = 0; i < cont2.size(); ++i) {
+        ASSERT(*(it1++) == *(it2++), "Multimap repetitive key was not erased properly");
+    }
+}
+
+template <typename MultiMap>
 void SpecialMultiMapTests( const char *str ){
     int one_values[] = { 7, 2, 13, 23, 13 };
     int zero_values[] = { 4, 9, 13, 29, 42, 111};
@@ -302,6 +327,7 @@ void SpecialMultiMapTests( const char *str ){
     CheckMultiMap(cont, one_values, n_one_values, 1);
     CheckMultiMap(cont, zero_values, n_zero_values, 0);
 
+    MultiMapEraseTests<MultiMap>();
 
     REMARK( "passed -- specialized %s tests\n", str );
 }
@@ -470,10 +496,15 @@ void test_basic_common(const char * str, do_check_element_state)
     typename T::size_type size = cont.unsafe_erase(1);
     ASSERT(T::allow_multimapping ? (size == 2) : (size == 1), "Erase has not removed the right number of elements");
 
-    // iterator unsafe_erase(const_iterator position);
+    // iterator unsafe_erase(iterator position);
     typename T::iterator it4 = cont.unsafe_erase(cont.find(2));
     ASSERT(it4 == cont.end() && cont.size() == 0, "Erase has not removed the last element properly");
 
+    // iterator unsafe_erase(const_iterator position);
+    cont.insert(Value<T>::make(3));
+    typename T::iterator it5 = cont.unsafe_erase(cont.cbegin());
+    ASSERT(it5 == cont.end() && cont.size() == 0, "Erase has not removed the last element properly");
+
     // template<class InputIterator> void insert(InputIterator first, InputIterator last);
     cont.insert(newcont.begin(), newcont.end());
     ASSERT(T::allow_multimapping ? (cont.size() == 3) : (cont.size() == 2), "Range insert has not copied the elements properly");
@@ -1367,70 +1398,69 @@ namespace node_handling{
         node_handling::TestMergeOverloads(multitable2, table2);
     }
 
-    template <typename Table>
-    void AssertionConcurrentMerge ( Table start_data, Table src_table, std::vector<Table> tables,
-                                    std::true_type) {
-        ASSERT( src_table.size() == start_data.size()*tables.size(),
+    template <typename SrcTableType, typename DestTableType>
+    void AssertionConcurrentMerge ( SrcTableType& start_data, DestTableType& dest_table,
+                                    std::vector<SrcTableType>& src_tables, std::true_type) {
+        ASSERT( dest_table.size() == start_data.size() * src_tables.size(),
                 "Merge: Incorrect merge for some elements" );
 
         for(auto it: start_data) {
-            ASSERT( src_table.count( Value<Table>::key( it ) ) ==
-                    start_data.count( Value<Table>::key( it ) )*tables.size(),
+            ASSERT( dest_table.count( Value<DestTableType>::key( it ) ) ==
+                    start_data.count( Value<SrcTableType>::key( it ) ) * src_tables.size(),
                                       "Merge: Incorrect merge for some element" );
         }
 
-        for (size_t i = 0; i < tables.size(); i++) {
-            ASSERT( tables[i].empty(), "Merge: Some elements was not merged" );
+        for (size_t i = 0; i < src_tables.size(); i++) {
+            ASSERT( src_tables[i].empty(), "Merge: Some elements were not merged" );
         }
     }
 
-    template <typename Table>
-    void AssertionConcurrentMerge ( Table start_data, Table src_table, std::vector<Table> tables,
-                                    std::false_type) {
-        Table expected_result;
-        for (auto table: tables)
+    template <typename SrcTableType, typename DestTableType>
+    void AssertionConcurrentMerge ( SrcTableType& start_data, DestTableType& dest_table,
+                                    std::vector<SrcTableType>& src_tables, std::false_type) {
+        SrcTableType expected_result;
+        for (auto table: src_tables)
             for (auto it: start_data) {
                 // If we cannot find some element in some table, then it has been moved
-                if (table.find( Value<Table>::key( it ) ) == table.end()){
+                if (table.find( Value<SrcTableType>::key( it ) ) == table.end()){
                     bool result = expected_result.insert( it ).second;
                     ASSERT( result, "Merge: Some element was merged twice or was not "
                                     "returned to his owner after unsuccessful merge");
                 }
             }
 
-        ASSERT( expected_result.size() == src_table.size() && start_data.size() == src_table.size(),
+        ASSERT( expected_result.size() == dest_table.size() && start_data.size() == dest_table.size(),
                 "Merge: wrong size of result table");
         for (auto it: expected_result) {
-            if ( src_table.find( Value<Table>::key( it ) ) != src_table.end() &&
-                 start_data.find( Value<Table>::key( it ) ) != start_data.end() ){
-                src_table.unsafe_extract(Value<Table>::key( it ));
-                start_data.unsafe_extract(Value<Table>::key( it ));
+            if ( dest_table.find( Value<SrcTableType>::key( it ) ) != dest_table.end() &&
+                 start_data.find( Value<DestTableType>::key( it ) ) != start_data.end() ){
+                dest_table.unsafe_extract(Value<SrcTableType>::key( it ));
+                start_data.unsafe_extract(Value<DestTableType>::key( it ));
             } else {
                 ASSERT( false, "Merge: Incorrect merge for some element" );
             }
         }
 
-        ASSERT( src_table.empty()&&start_data.empty(), "Merge: Some elements were not merged" );
+        ASSERT( dest_table.empty()&&start_data.empty(), "Merge: Some elements were not merged" );
     }
 
-    template <typename Table>
-    void TestConcurrentMerge (const Table& table_data) {
+    template <typename SrcTableType, typename DestTableType>
+    void TestConcurrentMerge (SrcTableType table_data) {
         for (auto num_threads = MinThread + 1; num_threads <= MaxThread; num_threads++){
-            std::vector<Table> tables;
-            Table src_table;
+            std::vector<SrcTableType> src_tables;
+            DestTableType dest_table;
 
             for (auto j = 0; j < num_threads; j++){
-                tables.push_back(table_data);
+                src_tables.push_back(table_data);
             }
 
-            NativeParallelFor( num_threads, [&](size_t index){ src_table.merge(tables[index]); } );
+            NativeParallelFor( num_threads, [&](size_t index){ dest_table.merge(src_tables[index]); } );
 
-            AssertionConcurrentMerge( table_data, src_table, tables,
-                                      std::integral_constant<bool,Table::allow_multimapping>{});
+            AssertionConcurrentMerge( table_data, dest_table, src_tables,
+                                      std::integral_constant<bool, DestTableType::allow_multimapping>{});
         }
     }
 
-
     template <typename Table>
     void TestNodeHandling(){
         Table table;
@@ -1476,13 +1506,13 @@ namespace node_handling{
         for (i = 0; i<size; ++i){
             table1_3.insert(Value<TableType1>::make(i));
         }
-        node_handling::TestConcurrentMerge(table1_3);
+        node_handling::TestConcurrentMerge<TableType1, TableType2>(table1_3);
 
         TableType2 table2_3;
         for (i = 0; i<size; ++i){
             table2_3.insert(Value<TableType2>::make(i));
         }
-        node_handling::TestConcurrentMerge(table2_3);
+        node_handling::TestConcurrentMerge<TableType2, TableType1>(table2_3);
 }
 }
 #endif // __TBB_UNORDERED_NODE_HANDLE_PRESENT || __TBB_CONCURRENT_ORDERED_CONTAINERS_PRESENT
index 8c05d1e..2ad7961 100644 (file)
@@ -147,11 +147,9 @@ void TestDeductionGuides() {
 }
 #endif
 
-void test_heterogenious_lookup() {
-    tbb::concurrent_map<int, int, transparent_compare> map = {{1,1}, {2, 2}};
-    tbb::concurrent_multimap<int, int, transparent_compare> mmap = {{1, 1}, {1, 10}, {2, 2}};
-    check_heterogenious_lookup(map);
-    check_heterogenious_lookup(mmap);
+void test_heterogeneous_functions() {
+    check_heterogeneous_functions<tbb::concurrent_map<int, int, transparent_less> >();
+    check_heterogeneous_functions<tbb::concurrent_multimap<int, int, transparent_less> >();
 }
 
 void multicontainer_specific_test() {
@@ -248,7 +246,7 @@ int TestMain() {
     node_handling::TestNodeHandling<MyMultiMap>();
     node_handling::TestMerge<MyMap, MyMultiMap>(1000);
 
-    test_heterogenious_lookup();
+    test_heterogeneous_functions();
 
     test_allocator_traits<tbb::concurrent_map, int, int, std::less<int>>();
     test_allocator_traits<tbb::concurrent_multimap, int, int, std::less<int>>();
index 89b28c0..23dec4c 100644 (file)
@@ -296,30 +296,56 @@ void TypeTester( const std::list<typename Table::value_type> &lst ) {
 struct int_key {
         int_key(int i) : my_item(i) {}
         int my_item;
-    };
+};
+
+bool operator<(const int_key& ik, int i) { return ik.my_item < i; }
+bool operator<(int i, const int_key& ik) { return i < ik.my_item; }
+bool operator<(const int_key& ik1, const int_key& ik2) { return ik1.my_item < ik2.my_item; }
 
-struct transparent_compare {
-    template <typename K, typename K2>
-    bool operator()(const K&, const K2&) const {
-        return false;
+struct transparent_less {
+    template <typename T, typename U>
+    auto operator()( T&& lhs, U&& rhs ) const
+    -> decltype(std::forward<T>(lhs) < std::forward<U>(rhs)){
+        return lhs < rhs;
     }
 
     using is_transparent = void;
 };
 
 template <typename Container>
-void check_heterogenious_lookup(const Container& c) {
+void check_heterogeneous_functions() {
     static_assert(std::is_same<typename Container::key_type, int>::value,
-                  "incorrect key_type for heterogenious lookup test");
-    int_key k(1);
-    int key = 1;
-
-    ASSERT(c.find(k) == c.find(key), "Incorrect heterogenious find return value");
-    ASSERT(c.lower_bound(k) == c.lower_bound(key), "Incorrect heterogenious lower_bound return value");
-    ASSERT(c.upper_bound(k) == c.upper_bound(key), "Incorrect heterogenious upper_bound return value");
-    ASSERT(c.equal_range(k) == c.equal_range(key), "Incorrect heterogenious equal_range return value");
-    ASSERT(c.count(k) == c.count(key), "Incorrect heterogenious count return value");
-    ASSERT(c.contains(k) == c.contains(key), "Incorrect heterogenious contains return value");
+                  "incorrect key_type for heterogeneous lookup test");
+    // Initialization
+    Container c;
+    int size = 10;
+    for (int i = 0; i < size; i++){
+        c.insert(Value<Container>::make(i));
+    }
+    // Insert first duplicated element for multicontainers
+    if (Container::allow_multimapping){
+        c.insert(Value<Container>::make(0));
+    }
+
+    // Look up testing
+    for (int i = 0; i < size; i++) {
+        int_key k(i);
+        int key = i;
+        ASSERT(c.find(k) == c.find(key), "Incorrect heterogeneous find return value");
+        ASSERT(c.lower_bound(k) == c.lower_bound(key), "Incorrect heterogeneous lower_bound return value");
+        ASSERT(c.upper_bound(k) == c.upper_bound(key), "Incorrect heterogeneous upper_bound return value");
+        ASSERT(c.equal_range(k) == c.equal_range(key), "Incorrect heterogeneous equal_range return value");
+        ASSERT(c.count(k) == c.count(key), "Incorrect heterogeneous count return value");
+        ASSERT(c.contains(k) == c.contains(key), "Incorrect heterogeneous contains return value");
+    }
+
+    // Erase testing
+    for (int i = 0; i < size; i++){
+        auto count_before_erase = c.count(i);
+        auto result = c.unsafe_erase(int_key(i));
+        ASSERT(count_before_erase==result,"Incorrent erased elements count");
+        ASSERT(c.count(i)==0, "Some elements was not erased");
+    }
 }
 
 template <template<typename...> class ContainerType, typename... ContainerArgs>
index 736aa20..18b27bf 100644 (file)
@@ -81,7 +81,10 @@ public:
     my_throwing_type() : my_data_type() {}
     my_throwing_type(const my_throwing_type& src) : my_data_type(src) {
         if (my_throwing_type::throw_flag) throw 42;
+    }
+    my_throwing_type& operator=(const my_throwing_type& src) {
         priority = src.priority;
+        return *this;
     }
 };
 int my_throwing_type::throw_flag = 0;
index 47478dd..f04664c 100644 (file)
@@ -484,11 +484,6 @@ class BarIterator
     Bar* bar_ptr;
     BarIterator(Bar* bp_) : bar_ptr(bp_) {}
 public:
-    ~BarIterator() {}
-    BarIterator& operator=( const BarIterator& other ) {
-        bar_ptr = other.bar_ptr;
-        return *this;
-    }
     Bar& operator*() const {
         return *bar_ptr;
     }
index c66d237..2be20b2 100644 (file)
@@ -125,11 +125,9 @@ void TestDeductionGuides() {
 }
 #endif /*__TBB_CPP17_DEDUCTION_GUIDES_PRESENT*/
 
-void test_heterogenious_lookup() {
-    tbb::concurrent_set<int, transparent_compare> set = {1, 2, 3};
-    tbb::concurrent_multiset<int, transparent_compare> mset = {1, 1, 2, 3};
-    check_heterogenious_lookup(set);
-    check_heterogenious_lookup(mset);
+void test_heterogeneous_functions() {
+    check_heterogeneous_functions<tbb::concurrent_set<int, transparent_less> >();
+    check_heterogeneous_functions<tbb::concurrent_multiset<int, transparent_less> >();
 }
 
 struct compare_keys_less {
@@ -236,7 +234,7 @@ int TestMain() {
     node_handling::TestNodeHandling<MyMultiSet>();
     node_handling::TestMerge<MySet, MyMultiSet>(1000);
 
-    test_heterogenious_lookup();
+    test_heterogeneous_functions();
 
     test_allocator_traits<tbb::concurrent_set, int, std::less<int>>();
     test_allocator_traits<tbb::concurrent_multiset, int, std::less<int>>();
index b7dd295..cf958d0 100644 (file)
 #define TBB_DEPRECATED_FLOW_NODE_EXTRACTION 1
 #endif
 
+#include "harness.h"
 #include "harness_graph.h"
 
 #include "tbb/flow_graph.h"
 #include "tbb/task_scheduler_init.h"
+#include "test_follows_and_precedes_api.h"
 
 #define N 1000
 #define MAX_NODES 4
@@ -394,6 +396,152 @@ void test_lightweight_policy() {
     ASSERT(body2.my_count == n, "Body of the second node needs to be executed N times");
 }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+#include <array>
+#include <vector>
+void test_follows_and_precedes_api() {
+    using msg_t = tbb::flow::continue_msg;
+
+    std::array<msg_t, 3> messages_for_follows = { msg_t(), msg_t(), msg_t() };
+    std::vector<msg_t> messages_for_precedes  = { msg_t() };
+
+    auto pass_through = [](const msg_t& msg) { return msg; };
+
+    follows_and_precedes_testing::test_follows
+        <msg_t, tbb::flow::continue_node<msg_t>>
+        (messages_for_follows, pass_through);
+
+    follows_and_precedes_testing::test_precedes
+        <msg_t, tbb::flow::continue_node<msg_t>>
+        (messages_for_precedes, pass_through);
+}
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+
+template <typename ExpectedType, typename Body>
+void test_deduction_guides_common(Body body) {
+    using namespace tbb::flow;
+    graph g;
+
+    continue_node c1(g, body);
+    static_assert(std::is_same_v<decltype(c1), continue_node<ExpectedType>>);
+
+    continue_node c2(g, body, lightweight());
+    static_assert(std::is_same_v<decltype(c2), continue_node<ExpectedType, lightweight>>);
+
+    continue_node c3(g, 5, body);
+    static_assert(std::is_same_v<decltype(c3), continue_node<ExpectedType>>);
+
+    continue_node c4(g, 5, body, lightweight());
+    static_assert(std::is_same_v<decltype(c4), continue_node<ExpectedType, lightweight>>);
+
+#if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
+    continue_node c5(g, body, node_priority_t(5));
+    static_assert(std::is_same_v<decltype(c5), continue_node<ExpectedType>>);
+
+    continue_node c6(g, body, lightweight(), node_priority_t(5));
+    static_assert(std::is_same_v<decltype(c6), continue_node<ExpectedType, lightweight>>);
+
+    continue_node c7(g, 5, body, node_priority_t(5));
+    static_assert(std::is_same_v<decltype(c7), continue_node<ExpectedType>>);
+
+    continue_node c8(g, 5, body, lightweight(), node_priority_t(5));
+    static_assert(std::is_same_v<decltype(c8), continue_node<ExpectedType, lightweight>>);
+#endif
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    broadcast_node<continue_msg> b(g);
+
+    continue_node c9(follows(b), body);
+    static_assert(std::is_same_v<decltype(c9), continue_node<ExpectedType>>);
+
+    continue_node c10(follows(b), body, lightweight());
+    static_assert(std::is_same_v<decltype(c10), continue_node<ExpectedType, lightweight>>);
+
+    continue_node c11(follows(b), 5, body);
+    static_assert(std::is_same_v<decltype(c11), continue_node<ExpectedType>>);
+
+    continue_node c12(follows(b), 5, body, lightweight());
+    static_assert(std::is_same_v<decltype(c12), continue_node<ExpectedType, lightweight>>);
+
+#if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
+    continue_node c13(follows(b), body, node_priority_t(5));
+    static_assert(std::is_same_v<decltype(c13), continue_node<ExpectedType>>);
+
+    continue_node c14(follows(b), body, lightweight(), node_priority_t(5));
+    static_assert(std::is_same_v<decltype(c14), continue_node<ExpectedType, lightweight>>);
+
+    continue_node c15(follows(b), 5, body, node_priority_t(5));
+    static_assert(std::is_same_v<decltype(c15), continue_node<ExpectedType>>);
+
+    continue_node c16(follows(b), 5, body, lightweight(), node_priority_t(5));
+    static_assert(std::is_same_v<decltype(c16), continue_node<ExpectedType, lightweight>>);
+#endif
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
+    continue_node c17(c1);
+    static_assert(std::is_same_v<decltype(c17), continue_node<ExpectedType>>);
+}
+
+int continue_body_f(const tbb::flow::continue_msg&) { return 1; }
+void continue_void_body_f(const tbb::flow::continue_msg&) {}
+
+void test_deduction_guides() {
+    using tbb::flow::continue_msg;
+    test_deduction_guides_common<int>([](const continue_msg&)->int { return 1; } );
+    test_deduction_guides_common<continue_msg>([](const continue_msg&) {});
+
+    test_deduction_guides_common<int>([](const continue_msg&) mutable ->int { return 1; });
+    test_deduction_guides_common<continue_msg>([](const continue_msg&) mutable {});
+
+    test_deduction_guides_common<int>(continue_body_f);
+    test_deduction_guides_common<continue_msg>(continue_void_body_f);
+}
+
+#endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+
+// TODO: use pass_through from test_function_node instead
+template<typename T>
+struct passing_body {
+    T operator()(const T& val) {
+        return val;
+    }
+};
+
+/*
+    The test covers the case when a node with non-default mutex type is a predecessor for continue_node,
+    because there used to be a bug when make_edge(node, continue_node)
+    did not update continue_node's predecesosor threshold
+    since the specialization of node's successor_cache for a continue_node was not chosen.
+*/
+void test_successor_cache_specialization() {
+    using namespace tbb::flow;
+
+    graph g;
+
+    broadcast_node<continue_msg> node_with_default_mutex_type(g);
+    buffer_node<continue_msg> node_with_non_default_mutex_type(g);
+
+    continue_node<continue_msg> node(g, passing_body<continue_msg>());
+
+    make_edge(node_with_default_mutex_type, node);
+    make_edge(node_with_non_default_mutex_type, node);
+
+    buffer_node<continue_msg> buf(g);
+
+    make_edge(node, buf);
+
+    node_with_default_mutex_type.try_put(continue_msg());
+    node_with_non_default_mutex_type.try_put(continue_msg());
+
+    g.wait_for_all();
+
+    continue_msg storage;
+    ASSERT((buf.try_get(storage) && !buf.try_get(storage)),
+            "Wrong number of messages is passed via continue_node");
+}
+
 int TestMain() {
     if( MinThread<1 ) {
         REPORT("number of threads must be positive\n");
@@ -409,6 +557,12 @@ int TestMain() {
 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
    test_extract();
 #endif
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    test_follows_and_precedes_api();
+#endif
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+    test_deduction_guides();
+#endif
+   test_successor_cache_specialization();
    return Harness::Done;
 }
-
index 70f0873..b259813 100644 (file)
@@ -304,7 +304,6 @@ class tag_func {
     TT my_mult;
 public:
     tag_func(TT multiplier) : my_mult(multiplier) { }
-    void operator=( const tag_func& other){my_mult = other.my_mult;}
     // operator() will return [0 .. Count)
     tbb::flow::tag_value operator()( TT v) {
         tbb::flow::tag_value t = tbb::flow::tag_value(v / my_mult);
index 55fe5a9..a49e1da 100644 (file)
@@ -16,7 +16,7 @@
 
 #define HARNESS_DEFAULT_MIN_THREADS 2
 #define HARNESS_DEFAULT_MAX_THREADS 4
-#define __TBB_SHUFFLE_PRESENT (_MSC_VER >= 1910 || __cplusplus >= 201103L && (__TBB_GLIBCXX_VERSION >= 40800 || _LIBCPP_VERSION))
+#define __TBB_SHUFFLE_PRESENT (_MSC_VER >= 1900 || __cplusplus >= 201103L && (__TBB_GLIBCXX_VERSION >= 40800 || _LIBCPP_VERSION))
 
 #include "harness.h"
 
index 2929455..c9cc851 100644 (file)
@@ -310,7 +310,6 @@ class tag_func {
     TT my_mult;
 public:
     tag_func(TT multiplier) : my_mult(multiplier) { }
-    void operator=( const tag_func& other){my_mult = other.my_mult;}
     // operator() will return [0 .. Count)
     tbb::flow::tag_value operator()( TT v) {
         tbb::flow::tag_value t = tbb::flow::tag_value(v / my_mult);
diff --git a/src/test/test_follows_and_precedes_api.h b/src/test/test_follows_and_precedes_api.h
new file mode 100644 (file)
index 0000000..e6e6c0d
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+    Copyright (c) 2019 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.
+*/
+
+#include "harness.h"
+#include "tbb/flow_graph.h"
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+#include <array>
+#include <vector>
+#include <type_traits>
+
+namespace follows_and_precedes_testing{
+
+template <typename NodeType>
+struct testing_method_follows: std::integral_constant<int, 0> {};
+
+template <typename... Args>
+struct testing_method_follows<tbb::flow::join_node<Args...>> : std::integral_constant<int, 1> {};
+template <typename... Args>
+struct testing_method_follows<tbb::flow::continue_node<Args...>> : std::integral_constant<int, 1> {};
+
+template <typename... Args>
+struct testing_method_follows<tbb::flow::overwrite_node<Args...>> : std::integral_constant<int, 2> {};
+template <typename... Args>
+struct testing_method_follows<tbb::flow::write_once_node<Args...>> : std::integral_constant<int, 2> {};
+
+template <typename... Args>
+struct testing_method_follows<tbb::flow::multifunction_node<Args...>> : std::integral_constant<int, 3> {};
+
+template <typename MessageType, typename NodeType, typename PredecessorType>
+class edge_checker_follows {
+public:
+    static void check(tbb::flow::graph& g,
+                      NodeType& node,
+                      std::array<PredecessorType, 3>& preds,
+                      std::array<MessageType, 3>& messages) {
+        check_impl(g, node, preds, messages, typename testing_method_follows<NodeType>::type());
+    }
+private:
+    // Test is applicable for: function_node, buffer_node, queue_node, priority_queue_node, limiter_node,
+    //                         broadcast_node, sequencer_node
+    static void check_impl(tbb::flow::graph& g,
+                           NodeType& node,
+                           std::array<PredecessorType, 3>& preds,
+                           std::array<MessageType, 3>& messages,
+                           std::integral_constant<int, 0>) {
+        tbb::flow::buffer_node<typename NodeType::output_type> buffer(g);
+        tbb::flow::make_edge(node, buffer);
+
+        for(size_t i = 0; i < 3; ++i) {
+            preds[i].try_put(messages[i]);
+            g.wait_for_all();
+
+            typename NodeType::output_type storage;
+            ASSERT((buffer.try_get(storage) && !buffer.try_get(storage)), "Not exact edge quantity was made");
+        }
+    }
+    // Test is applicable for: continue_node, join_node
+    static void check_impl(tbb::flow::graph& g,
+                           NodeType& node,
+                           std::array<PredecessorType, 3>& preds,
+                           std::array<MessageType, 3>& messages,
+                           std::integral_constant<int, 1>) {
+        tbb::flow::buffer_node<typename NodeType::output_type> buffer(g);
+        tbb::flow::make_edge(node, buffer);
+
+        for(size_t i = 0; i < 3; ++i) {
+            preds[i].try_put(messages[i]);
+            g.wait_for_all();
+        }
+
+        typename NodeType::output_type storage;
+        ASSERT((buffer.try_get(storage) && !buffer.try_get(storage)), "Not exact edge quantity was made");
+    }
+    // Test is applicable for: overwrite_node, write_once_node
+    static void check_impl(tbb::flow::graph& g,
+                           NodeType& node,
+                           std::array<PredecessorType, 3>& preds,
+                           std::array<MessageType, 3>& messages,
+                           std::integral_constant<int, 2>) {
+        for(size_t i = 0; i < 3; ++i) {
+            node.clear();
+            preds[i].try_put(messages[i]);
+            g.wait_for_all();
+
+            typename NodeType::output_type storage;
+            ASSERT((node.try_get(storage)), "Not exact edge quantity was made");
+        }
+   }
+    // Test is applicable for: multifunction_node
+    static void check_impl(tbb::flow::graph& g,
+                           NodeType& node,
+                           std::array<PredecessorType, 3>& preds,
+                           std::array<MessageType, 3>& messages,
+                           std::integral_constant<int, 3>) {
+        typedef typename std::remove_reference<decltype(tbb::flow::output_port<0>(node))>::type multioutput;
+        tbb::flow::buffer_node<typename multioutput::output_type> buf(tbb::flow::follows(tbb::flow::output_port<0>(node)));
+
+        for(size_t i = 0; i < 3; ++i) {
+            preds[i].try_put(messages[i]);
+            g.wait_for_all();
+
+            typename multioutput::output_type storage;
+            ASSERT((buf.try_get(storage) && ! buf.try_get(storage)), "Not exact edge quantity was made");
+        }
+   }
+};
+
+template <typename NodeType>
+struct testing_method_precedes: std::integral_constant<int, 0> {};
+
+template <typename... Args>
+struct testing_method_precedes<tbb::flow::buffer_node<Args...>> : std::integral_constant<int, 1> {};
+template <typename... Args>
+struct testing_method_precedes<tbb::flow::queue_node<Args...>> : std::integral_constant<int, 1> {};
+template <typename... Args>
+struct testing_method_precedes<tbb::flow::priority_queue_node<Args...>> : std::integral_constant<int, 1> {};
+template <typename... Args>
+struct testing_method_precedes<tbb::flow::sequencer_node<Args...>> : std::integral_constant<int, 1> {};
+
+template <typename... Args>
+struct testing_method_precedes<tbb::flow::join_node<Args...>> : std::integral_constant<int, 2> {};
+
+template <typename MessageType, typename NodeType>
+class edge_checker_precedes {
+    using NodeOutputType = typename NodeType::output_type;
+    using SuccessorOutputType = typename tbb::flow::buffer_node<NodeOutputType>::output_type;
+public:
+    static void check(tbb::flow::graph& g,
+                      NodeType& node,
+                      std::array<tbb::flow::buffer_node<NodeOutputType>, 3>& successors,
+                      std::vector<MessageType>& messages) {
+        check_impl(g, node, successors, messages, typename testing_method_precedes<NodeType>::type());
+    }
+private:
+    // Testing is applicable for: continue_node, function_node, overwrite_node, buffer_node,
+    //                            broadcast_node, write_once_node, limiter_node
+    static void check_impl(tbb::flow::graph& g,
+                           NodeType& node,
+                           std::array<tbb::flow::buffer_node<NodeOutputType>, 3>& successors,
+                           std::vector<MessageType>& messages,
+                           std::integral_constant<int, 0>) {
+        ASSERT((messages.size() == 1),
+               "messages.size() has to be 1 to test nodes what broadcast message to all the successors");
+
+        node.try_put(messages[0]);
+        g.wait_for_all();
+
+        SuccessorOutputType storage;
+        for(auto& successor: successors) {
+            ASSERT((successor.try_get(storage) && !successor.try_get(storage)),
+                    "Not exact edge quantity was made");
+        }
+    }
+    // Testing is applicable for: buffer_node, queue_node, priority_queue_node, sequencer_node
+    static void check_impl(tbb::flow::graph& g,
+                           NodeType& node,
+                           std::array<tbb::flow::buffer_node<typename NodeType::output_type>, 3>& successors,
+                           std::vector<MessageType>& messages,
+                           std::integral_constant<int, 1>) {
+        ASSERT((messages.size() == 3),
+               "messages.size() has to be 3 to test nodes what send a message to the first available successor");
+
+        tbb::flow::write_once_node<SuccessorOutputType>
+            buffer(tbb::flow::follows(successors[0], successors[1], successors[2]));
+
+        for(size_t i = 0; i < 3; ++i) {
+            node.try_put(messages[i]);
+            g.wait_for_all();
+
+            SuccessorOutputType storage;
+            ASSERT((buffer.try_get(storage)), "Not exact edge quantity was made");
+
+            buffer.clear();
+        }
+    }
+    // Testing is applicable for: join_node
+    static void check_impl(tbb::flow::graph& g,
+                           NodeType& node,
+                           std::array<tbb::flow::buffer_node<typename NodeType::output_type>, 3>& successors,
+                           std::vector<MessageType>& messages,
+                           std::integral_constant<int, 2>) {
+        ASSERT((messages.size() == 3),
+               "messages.size() has to be 3 to test nodes what send a message to the first available successor");
+        std::array<tbb::flow::buffer_node<MessageType>, 3> preds = {
+            tbb::flow::buffer_node<MessageType>(g),
+            tbb::flow::buffer_node<MessageType>(g),
+            tbb::flow::buffer_node<MessageType>(g)
+        };
+
+        make_edge(preds[0], tbb::flow::input_port<0>(node));
+        make_edge(preds[1], tbb::flow::input_port<1>(node));
+        make_edge(preds[2], tbb::flow::input_port<2>(node));
+
+        for(size_t i = 0; i < 3; ++i) {
+            preds[i].try_put(messages[i]);
+            g.wait_for_all();
+        }
+
+        typename NodeType::output_type storage;
+        for(auto& successor: successors) {
+            ASSERT((successor.try_get(storage) && !successor.try_get(storage)),
+            "Not exact edge quantity was made");
+        }
+    }
+};
+
+template<typename MessageType,
+         typename NodeType,
+         typename PredecessorType=tbb::flow::broadcast_node<MessageType>,
+         typename... ConstructorArgs>
+void test_follows(std::array<MessageType, 3>& messages, ConstructorArgs&&... args) {
+    using namespace tbb::flow;
+
+    graph g;
+    std::array<PredecessorType, 3> preds = {
+        PredecessorType(g),
+        PredecessorType(g),
+        PredecessorType(g)
+    };
+
+    NodeType node(follows(preds[0], preds[1], preds[2]), std::forward<ConstructorArgs>(args)...);
+
+    edge_checker_follows<MessageType, NodeType, PredecessorType>::check(g, node, preds, messages);
+}
+
+template<typename MessageType,
+         typename NodeType,
+         typename... ConstructorArgs>
+void test_precedes(std::vector<MessageType>& messages, ConstructorArgs&&... args) {
+    using namespace tbb::flow;
+
+    using SuccessorType = buffer_node<typename NodeType::output_type>;
+
+    graph g;
+
+    std::array<SuccessorType, 3> successors = { SuccessorType(g), SuccessorType(g), SuccessorType(g) };
+
+    NodeType node(precedes(successors[0], successors[1], successors[2]), std::forward<ConstructorArgs>(args)...);
+
+    edge_checker_precedes<MessageType, NodeType>::check(g, node, successors, messages);
+}
+
+} // follows_and_precedes_testing
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
index 68256af..7554bd6 100644 (file)
 #define TBB_DEPRECATED_FLOW_NODE_EXTRACTION 1
 #endif
 
+#include "harness.h"
 #include "harness_graph.h"
 
 #include "tbb/flow_graph.h"
 #include "tbb/task_scheduler_init.h"
 #include "tbb/spin_rw_mutex.h"
+#include "test_follows_and_precedes_api.h"
 
 #define N 100
 #define MAX_NODES 4
@@ -577,6 +579,77 @@ void test_extract() {
 }
 #endif
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+#include <array>
+#include <vector>
+void test_follows_and_precedes_api() {
+    using msg_t = tbb::flow::continue_msg;
+
+    std::array<msg_t, 3> messages_for_follows = { msg_t(), msg_t(), msg_t() };
+    std::vector<msg_t> messages_for_precedes = { msg_t() };
+
+    pass_through<msg_t> pass_msg;
+
+    follows_and_precedes_testing::test_follows
+        <msg_t, tbb::flow::function_node<msg_t, msg_t>>
+        (messages_for_follows, tbb::flow::unlimited, pass_msg);
+    follows_and_precedes_testing::test_precedes
+        <msg_t, tbb::flow::function_node<msg_t, msg_t>>
+        (messages_for_precedes, tbb::flow::unlimited, pass_msg);
+}
+#endif
+
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+
+int function_body_f(const int&) { return 1; }
+
+template <typename Body>
+void test_deduction_guides_common(Body body) {
+    using namespace tbb::flow;
+    graph g;
+
+    function_node f1(g, unlimited, body);
+    static_assert(std::is_same_v<decltype(f1), function_node<int, int>>);
+
+    function_node f2(g, unlimited, body, rejecting());
+    static_assert(std::is_same_v<decltype(f2), function_node<int, int, rejecting>>);
+
+#if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
+    function_node f3(g, unlimited, body, node_priority_t(5));
+    static_assert(std::is_same_v<decltype(f3), function_node<int, int>>);
+
+    function_node f4(g, unlimited, body, rejecting(), node_priority_t(5));
+    static_assert(std::is_same_v<decltype(f4), function_node<int, int, rejecting>>);
+#endif
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    function_node f5(follows(f2), unlimited, body);
+    static_assert(std::is_same_v<decltype(f5), function_node<int, int>>);
+
+    function_node f6(follows(f5), unlimited, body, rejecting());
+    static_assert(std::is_same_v<decltype(f6), function_node<int, int, rejecting>>);
+
+#if __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
+    function_node f7(follows(f6), unlimited, body, node_priority_t(5));
+    static_assert(std::is_same_v<decltype(f7), function_node<int, int>>);
+
+    function_node f8(follows(f7), unlimited, body, rejecting(), node_priority_t(5));
+    static_assert(std::is_same_v<decltype(f8), function_node<int, int, rejecting>>);
+#endif // __TBB_PREVIEW_FLOW_GRAPH_PRIORITIES
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
+    function_node f9(f1);
+    static_assert(std::is_same_v<decltype(f9), function_node<int, int>>);
+}
+
+void test_deduction_guides() {
+    test_deduction_guides_common([](const int&)->int { return 1; });
+    test_deduction_guides_common([](const int&) mutable ->int { return 1; });
+    test_deduction_guides_common(function_body_f);
+}
+
+#endif
+
 int TestMain() {
     if( MinThread<1 ) {
         REPORT("number of threads must be positive\n");
@@ -590,6 +663,11 @@ int TestMain() {
     test_extract<tbb::flow::rejecting>();
     test_extract<tbb::flow::queueing>();
 #endif
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    test_follows_and_precedes_api();
+#endif
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+    test_deduction_guides();
+#endif
    return Harness::Done;
 }
-
index 8c8c281..e28b0d8 100644 (file)
@@ -618,6 +618,7 @@ void TestParallelismRestored()
         const int P = 4;
         blocking_task_scheduler_init tsi(P);
         {
+            ASSERT(tbb::this_task_arena::max_concurrency() == P, NULL);
             tbb::global_control s(tbb::global_control::max_allowed_parallelism, 1);
             Harness::ExactConcurrencyLevel::check(1);
             // create enforced concurrency in the arena
@@ -625,7 +626,9 @@ void TestParallelismRestored()
                 FFTask* t = new( tbb::task::allocate_root() ) FFTask(&counter);
                 tbb::task::enqueue(*t);
             }
+            ASSERT(tbb::this_task_arena::max_concurrency() == P, NULL);
         }
+        ASSERT(tbb::this_task_arena::max_concurrency() == P, NULL);
         // global control is off, check that concurrency P is available
         Harness::ExactConcurrencyLevel::check(P);
     }
@@ -754,6 +757,7 @@ int TestMain()
     TestConcurrentArenas();
     TestMultipleControls();
     TestNoUnwantedEnforced();
+    TestParallelismRestored();
     const unsigned h_c = tbb::tbb_thread::hardware_concurrency();
     bool excessHC;
     {
index 2a02a4b..7ee63b2 100644 (file)
@@ -18,6 +18,7 @@
 #define TBB_DEPRECATED_FLOW_NODE_EXTRACTION 1
 #endif
 
+#include "harness.h"
 #include "harness_graph.h"
 #include "tbb/flow_graph.h"
 
@@ -841,6 +842,95 @@ public:
     }
 };
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+template<typename tagged_msg_t, typename input_t>
+void check_edge(tbb::flow::graph& g,
+                tbb::flow::broadcast_node<input_t>& start,
+                tbb::flow::buffer_node<tagged_msg_t>& buf,
+                input_t input_value) {
+    start.try_put(input_value);
+    g.wait_for_all();
+
+    tagged_msg_t msg;
+    bool is_get_succeeded = buf.try_get(msg);
+
+    ASSERT((is_get_succeeded), "There is no item in the buffer");
+    ASSERT((tbb::flow::cast_to<input_t>(msg) == input_value), "Wrong item value");
+}
+
+void test_follows() {
+    using namespace tbb::flow;
+    using indexer_output_t = indexer_node<int, float, double>::output_type;
+
+    graph g;
+    broadcast_node<continue_msg> start(g);
+
+    broadcast_node<int> start1(g);
+    broadcast_node<float> start2(g);
+    broadcast_node<double> start3(g);
+
+    indexer_node<int, float, double> my_indexer(follows(start1, start2, start3));
+
+    buffer_node<indexer_output_t> buf(g);
+    make_edge(my_indexer, buf);
+
+    check_edge<indexer_output_t, int>(g, start1, buf, 1);
+    check_edge<indexer_output_t, float>(g, start2, buf, 2.2f);
+    check_edge<indexer_output_t, double>(g, start3, buf, 3.3);
+}
+
+void test_precedes() {
+    using namespace tbb::flow;
+
+    using indexer_output_t = indexer_node<int, float, double>::output_type;
+
+    graph g;
+
+    broadcast_node<int> start1(g);
+    broadcast_node<float> start2(g);
+    broadcast_node<double> start3(g);
+
+    buffer_node<indexer_output_t> buf1(g);
+    buffer_node<indexer_output_t> buf2(g);
+    buffer_node<indexer_output_t> buf3(g);
+
+    indexer_node<int, float, double> node(precedes(buf1, buf2, buf3));
+
+    make_edge(start1, input_port<0>(node));
+    make_edge(start2, input_port<1>(node));
+    make_edge(start3, input_port<2>(node));
+
+    check_edge<indexer_output_t, int>(g, start1, buf1, 1);
+    check_edge<indexer_output_t, float>(g, start2, buf2, 2.2f);
+    check_edge<indexer_output_t, double>(g, start3, buf3, 3.3);
+}
+
+void test_follows_and_precedes_api() {
+    test_follows();
+    test_precedes();
+}
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+void test_deduction_guides() {
+    using namespace tbb::flow;
+    graph g;
+
+    broadcast_node<int> b1(g);
+    broadcast_node<double> b2(g);
+    indexer_node<int, double> i0(g);
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    indexer_node i1(follows(b1, b2));
+    static_assert(std::is_same_v<decltype(i1), indexer_node<int, double>>);
+#endif
+
+    indexer_node i2(i0);
+    static_assert(std::is_same_v<decltype(i2), indexer_node<int, double>>);
+}
+
+#endif
+
 int TestMain() {
     REMARK("Testing indexer_node, ");
 #if __TBB_USE_TBB_TUPLE
@@ -880,5 +970,11 @@ int TestMain() {
 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
    test_indexer_extract<int>().run_tests();
 #endif
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    test_follows_and_precedes_api();
+#endif
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+    test_deduction_guides();
+#endif
    return Harness::Done;
 }
index fb3a1e9..3c3337d 100644 (file)
@@ -36,9 +36,10 @@ void test_random_iterator(const RandomIt& it) {
     {
         auto t1 = typename RandomIt::difference_type{};
         auto t2 = typename RandomIt::value_type{};
+        auto t3 = typename RandomIt::pointer{};
+        tbb::internal::suppress_unused_warning(t1,t2,t3);
         typename RandomIt::reference ref = *it;
         tbb::internal::suppress_unused_warning(ref);
-        auto t3 = typename RandomIt::pointer{};
         typename RandomIt::iterator_category{};
     }
 
index 8857107..be65ee5 100644 (file)
@@ -17,7 +17,6 @@
 #if __TBB_CPF_BUILD
 #define TBB_DEPRECATED_FLOW_NODE_EXTRACTION 1
 #endif
-
 #include "test_join_node.h"
 
 static tbb::atomic<int> output_count;
@@ -115,13 +114,75 @@ public:
     }
 };
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+#include <array>
+#include <vector>
+void test_follows_and_precedes_api() {
+    using msg_t = tbb::flow::continue_msg;
+    using JoinOutputType = tbb::flow::tuple<msg_t, msg_t, msg_t>;
+
+    std::array<msg_t, 3> messages_for_follows = {msg_t(), msg_t(), msg_t()};
+    std::vector<msg_t> messages_for_precedes = {msg_t(), msg_t(), msg_t()};
+
+    follows_and_precedes_testing::test_follows
+        <msg_t, tbb::flow::join_node<JoinOutputType>, tbb::flow::buffer_node<msg_t>>(messages_for_follows);
+    follows_and_precedes_testing::test_follows
+        <msg_t, tbb::flow::join_node<JoinOutputType, tbb::flow::queueing>>(messages_for_follows);
+    follows_and_precedes_testing::test_follows
+        <msg_t, tbb::flow::join_node<JoinOutputType, tbb::flow::reserving>, tbb::flow::buffer_node<msg_t>>(messages_for_follows);
+    // TODO: add tests for key_matching and message based key matching
+
+    follows_and_precedes_testing::test_precedes
+        <msg_t, tbb::flow::join_node<JoinOutputType>>(messages_for_precedes);
+    follows_and_precedes_testing::test_precedes
+        <msg_t, tbb::flow::join_node<JoinOutputType, tbb::flow::queueing>>(messages_for_precedes);
+    follows_and_precedes_testing::test_precedes
+        <msg_t, tbb::flow::join_node<JoinOutputType, tbb::flow::reserving>>(messages_for_precedes);
+}
+#endif
+
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+void test_deduction_guides() {
+    using namespace tbb::flow;
+
+    graph g;
+    using tuple_type = std::tuple<int, int, int>;
+    broadcast_node<int> b1(g), b2(g), b3(g);
+    broadcast_node<tuple_type> b4(g);
+    join_node<tuple_type> j0(g);
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    join_node j1(follows(b1, b2, b3));
+    static_assert(std::is_same_v<decltype(j1), join_node<tuple_type>>);
+
+    join_node j2(follows(b1, b2, b3), reserving());
+    static_assert(std::is_same_v<decltype(j2), join_node<tuple_type, reserving>>);
+
+    join_node j3(precedes(b4));
+    static_assert(std::is_same_v<decltype(j3), join_node<tuple_type>>);
+
+    join_node j4(precedes(b4), reserving());
+    static_assert(std::is_same_v<decltype(j4), join_node<tuple_type, reserving>>);
+#endif
+
+    join_node j5(j0);
+    static_assert(std::is_same_v<decltype(j5), join_node<tuple_type>>);
+}
+
+#endif
+
 int TestMain() {
 #if __TBB_USE_TBB_TUPLE
     REMARK("  Using TBB tuple\n");
 #else
     REMARK("  Using platform tuple\n");
 #endif
-
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    test_follows_and_precedes_api();
+#endif
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+    test_deduction_guides();
+#endif
     TestTaggedBuffers();
     test_main<tbb::flow::queueing>();
     test_main<tbb::flow::reserving>();
index 2c7d1ac..f2f15d1 100644 (file)
 #endif
 #endif
 
+#include "harness.h"
 #include "harness_graph.h"
 #include "harness_checktype.h"
 
 #include "tbb/flow_graph.h"
 #include "tbb/task_scheduler_init.h"
+#include "test_follows_and_precedes_api.h"
 
 #define __TBB_MIC_OFFLOAD_TEST_COMPILATION_BROKEN __TBB_MIC_OFFLOAD
 
@@ -250,7 +252,7 @@ struct my_struct_key<K&, V> {
 using tbb::internal::is_ref;
 
 template<class K, class V> struct VtoKFB {
-    typedef tbb::flow::interface10::internal::type_to_key_function_body<V, K> type;
+    typedef tbb::flow::interface11::internal::type_to_key_function_body<V, K> type;
 };
 
 template<typename K> struct make_hash_compare { typedef typename tbb::tbb_hash_compare<K> type; };
@@ -258,14 +260,14 @@ template<typename K> struct make_hash_compare { typedef typename tbb::tbb_hash_c
 template<typename K, class V>
 void hash_buffer_test(const char *sname) {
     typedef typename K_deref<K>::type KnoR;
-    tbb::flow::interface10::internal::hash_buffer<
+    tbb::flow::interface11::internal::hash_buffer<
         K,
         V,
         typename VtoKFB<K, V>::type,
         tbb::tbb_hash_compare<KnoR>
     > my_hash_buffer;
     const bool k_is_ref = is_ref<K>::value;
-    typedef tbb::flow::interface10::internal::type_to_key_function_body_leaf<
+    typedef tbb::flow::interface11::internal::type_to_key_function_body_leaf<
         V, K, my_struct_key<K, V> > my_func_body_type;
     typename VtoKFB<K, V>::type *kp = new my_func_body_type(my_struct_key<K, V>());
     my_hash_buffer.set_key_func(kp);
@@ -2090,7 +2092,7 @@ template<typename Policy> struct policy_name {};
 
 template<> struct policy_name<tbb::flow::queueing> {
 const char* msg_beg() { return "queueing\n";}
-const char* msg_end() { return "test queueing extract\n";} 
+const char* msg_end() { return "test queueing extract\n";}
 };
 
 template<> struct policy_name<tbb::flow::reserving> {
index 758b904..4f1128b 100644 (file)
 #define TBB_DEPRECATED_FLOW_NODE_EXTRACTION 1
 #endif
 
+#define TBB_PREVIEW_FLOW_GRAPH_FEATURES 1
 #include "test_join_node.h"
 
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+void test_deduction_guides() {
+    using namespace tbb::flow;
+    using tuple_type = std::tuple<int, int, double>;
+
+    graph g;
+    auto body_int = [](const int&)->int { return 1; };
+    auto body_double = [](const double&)->int { return 1; };
+
+    join_node j1(g, body_int, body_int, body_double);
+    static_assert(std::is_same_v<decltype(j1), join_node<tuple_type, key_matching<int>>>);
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    broadcast_node<int> b1(g), b2(g);
+    broadcast_node<double> b3(g);
+    broadcast_node<tuple_type> b4(g);
+
+    join_node j2(follows(b1, b2, b3), body_int, body_int, body_double);
+    static_assert(std::is_same_v<decltype(j2), join_node<tuple_type, key_matching<int>>>);
+
+    join_node j3(precedes(b4), body_int, body_int, body_double);
+    static_assert(std::is_same_v<decltype(j3), join_node<tuple_type, key_matching<int>>>);
+#endif
+
+    join_node j4(j1);
+    static_assert(std::is_same_v<decltype(j4), join_node<tuple_type, key_matching<int>>>);
+}
+#endif
+
 int TestMain() {
 #if __TBB_USE_TBB_TUPLE
     REMARK("  Using TBB tuple\n");
@@ -45,9 +75,14 @@ int TestMain() {
     >, tbb::flow::key_matching<std::string&> >::do_test();
 #endif
 
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+    test_deduction_guides();
+#endif
+
     generate_test<parallel_test, tbb::flow::tuple<MyKeyFirst<int, double>, MyKeySecond<int, float> >, tbb::flow::key_matching<int> >::do_test();
     generate_test<parallel_test, tbb::flow::tuple<MyKeyFirst<int, double>, MyKeySecond<int, float> >, tbb::flow::key_matching<int&> >::do_test();
     generate_test<parallel_test, tbb::flow::tuple<MyKeyFirst<std::string, double>, MyKeySecond<std::string, float> >, tbb::flow::key_matching<std::string&> >::do_test();
+
 #if MAX_TUPLE_TEST_SIZE >= 10
     generate_test<parallel_test, tbb::flow::tuple<
         MyKeyFirst<std::string, double>,
index 54aa901..311f264 100644 (file)
 
 #include "test_join_node.h"
 
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+struct message_key {
+    int my_key;
+    double my_value;
+
+    int key() const { return my_key; }
+
+    operator size_t() const { return my_key; }
+
+    bool operator==(const message_key& rhs) { return my_value == rhs.my_value; }
+};
+
+void test_deduction_guides() {
+    using namespace tbb::flow;
+    using tuple_type = std::tuple<message_key, message_key>;
+
+    graph g;
+    broadcast_node<message_key> bm1(g), bm2(g);
+    broadcast_node<tuple_type> bm3(g);
+    join_node<tuple_type, key_matching<int> > j0(g);
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    join_node j1(follows(bm1, bm2), key_matching<int>());
+    static_assert(std::is_same_v<decltype(j1), join_node<tuple_type, key_matching<int>>>);
+
+    join_node j2(precedes(bm3), key_matching<int>());
+    static_assert(std::is_same_v<decltype(j2), join_node<tuple_type, key_matching<int>>>);
+#endif
+
+    join_node j3(j0);
+    static_assert(std::is_same_v<decltype(j3), join_node<tuple_type, key_matching<int>>>);
+}
+#endif
+
 int TestMain() {
 #if __TBB_USE_TBB_TUPLE
     REMARK("  Using TBB tuple\n");
@@ -53,6 +87,11 @@ int TestMain() {
     generate_test<parallel_test, tbb::flow::tuple<MyMessageKeyWithoutKeyMethod<int, double>, MyMessageKeyWithBrokenKey<int, float> >, message_based_key_matching<int&> >::do_test();
     generate_test<parallel_test, tbb::flow::tuple<MyMessageKeyWithoutKey<std::string, double>, MyMessageKeyWithoutKeyMethod<std::string, float> >, message_based_key_matching<std::string&> >::do_test();
 
+
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+    test_deduction_guides();
+#endif
+
 #if MAX_TUPLE_TEST_SIZE >= 10
     generate_test<parallel_test, tbb::flow::tuple<
         MyMessageKeyWithoutKeyMethod<std::string, double>,
index 322fc70..db9bfe9 100644 (file)
 */
 
 #include "harness.h"
+
 #if __TBB_CPF_BUILD
 #define TBB_DEPRECATED_FLOW_NODE_EXTRACTION 1
 #include "harness_graph.h"
 #endif
+
 #include "tbb/flow_graph.h"
 #include "tbb/atomic.h"
 #include "tbb/task_scheduler_init.h"
+#include "test_follows_and_precedes_api.h"
 
 const int L = 10;
 const int N = 1000;
@@ -40,7 +43,7 @@ struct serial_receiver : public tbb::flow::receiver<T>, NoAssign {
        return const_cast<tbb::task *>(SUCCESSFULLY_ENQUEUED);
    }
 
-    tbb::flow::graph& graph_reference() __TBB_override {
+    tbb::flow::graph& graph_reference() const __TBB_override {
         return my_graph;
     }
 
@@ -72,7 +75,7 @@ struct parallel_receiver : public tbb::flow::receiver<T>, NoAssign {
        return const_cast<tbb::task *>(tbb::flow::internal::SUCCESSFULLY_ENQUEUED);
     }
 
-    tbb::flow::graph& graph_reference() __TBB_override {
+    tbb::flow::graph& graph_reference() const __TBB_override {
         return my_graph;
     }
 
@@ -162,7 +165,7 @@ void test_puts_with_decrements( int num_threads, tbb::flow::limiter_node< T >& l
     ASSERT(lim.decrement.predecessor_count() == 1, NULL);
     ASSERT(lim.successor_count() == 1, NULL);
     ASSERT(lim.predecessor_count() == 0, NULL);
-    typename tbb::flow::interface10::internal::decrementer
+    typename tbb::flow::interface11::internal::decrementer
         <tbb::flow::limiter_node<T>, tbb::flow::continue_msg>::predecessor_list_type dec_preds;
     lim.decrement.copy_predecessors(dec_preds);
     ASSERT(dec_preds.size() == 1, NULL);
@@ -604,6 +607,44 @@ void test_extract() {
 }
 #endif  // TBB_DEPRECATED_FLOW_NODE_EXTRACTION
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+#include <array>
+#include <vector>
+void test_follows_and_precedes_api() {
+    using msg_t = tbb::flow::continue_msg;
+
+    std::array<msg_t, 3> messages_for_follows= {msg_t(), msg_t(), msg_t()};
+    std::vector<msg_t> messages_for_precedes = {msg_t()};
+
+    follows_and_precedes_testing::test_follows
+        <msg_t, tbb::flow::limiter_node<msg_t, msg_t>>(messages_for_follows, 1000);
+    follows_and_precedes_testing::test_precedes
+        <msg_t, tbb::flow::limiter_node<msg_t, msg_t>>(messages_for_precedes, 1000);
+
+}
+#endif
+
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+void test_deduction_guides() {
+    using namespace tbb::flow;
+
+    graph g;
+    broadcast_node<int> br(g);
+    limiter_node<int> l0(g, 100);
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    limiter_node l1(follows(br), 100);
+    static_assert(std::is_same_v<decltype(l1), limiter_node<int>>);
+
+    limiter_node l2(precedes(br), 100);
+    static_assert(std::is_same_v<decltype(l2), limiter_node<int>>);
+#endif
+
+    limiter_node l3(l0);
+    static_assert(std::is_same_v<decltype(l3), limiter_node<int>>);
+}
+#endif
+
 int TestMain() {
     for (int i = 1; i <= 8; ++i) {
         tbb::task_scheduler_init init(i);
@@ -623,5 +664,11 @@ int TestMain() {
 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
     test_extract();
 #endif
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    test_follows_and_precedes_api();
+#endif
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+    test_deduction_guides();
+#endif
    return Harness::Done;
 }
index 8591ab9..46aee33 100644 (file)
 #define TBB_DEPRECATED_FLOW_NODE_EXTRACTION 1
 #endif
 
+#include "harness.h"
 #include "harness_graph.h"
 
 #include "tbb/flow_graph.h"
 #include "tbb/task_scheduler_init.h"
 #include "tbb/spin_rw_mutex.h"
+#include "test_follows_and_precedes_api.h"
 
 #if TBB_USE_DEBUG
 #define N 16
@@ -683,6 +685,52 @@ void test_extract() {
 }
 #endif
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+#include <array>
+#include <vector>
+
+void test_precedes() {
+    using namespace tbb::flow;
+
+    using multinode = multifunction_node<int, std::tuple<int, int>>;
+
+    graph g;
+
+    buffer_node<int> b1(g);
+    buffer_node<int> b2(g);
+
+    multinode node(precedes(b1, b2), unlimited, [](const int& i, multinode::output_ports_type& op) -> void {
+            if (i % 2)
+                std::get<0>(op).try_put(i);
+            else
+                std::get<1>(op).try_put(i);
+        }
+    );
+
+    node.try_put(0);
+    node.try_put(1);
+    g.wait_for_all();
+
+    int storage;
+    ASSERT((b1.try_get(storage) && !b1.try_get(storage) && b2.try_get(storage) && !b2.try_get(storage)),
+            "Not exact edge quantity was made");
+}
+
+void test_follows_and_precedes_api() {
+    using multinode = tbb::flow::multifunction_node<int, std::tuple<int, int, int>>;
+
+    std::array<int, 3> messages_for_follows = {0, 1, 2};
+
+    follows_and_precedes_testing::test_follows
+        <int, tbb::flow::multifunction_node<int, std::tuple<int, int, int>>>
+        (messages_for_follows, tbb::flow::unlimited, [](const int& i, multinode::output_ports_type& op) -> void {
+            std::get<0>(op).try_put(i);
+        });
+
+    test_precedes();
+}
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
 int TestMain() {
     if( MinThread<1 ) {
         REPORT("number of threads must be positive\n");
@@ -698,5 +746,8 @@ int TestMain() {
     test_extract<tbb::flow::rejecting>();
     test_extract<tbb::flow::queueing>();
 #endif
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    test_follows_and_precedes_api();
+#endif
    return Harness::Done;
 }
index 4b06dc8..3570ab2 100644 (file)
@@ -152,7 +152,7 @@ void TestArgumentPassing() {
     ASSERT( std::all_of( b2.begin(), b2.end(), []( int c ) { return c == 1; } ), "Validation has failed" );
 
     // By default, the first device is used.
-    opencl_device d = *interface10::opencl_info::available_devices().begin();
+    opencl_device d = *interface11::opencl_info::available_devices().begin();
     std::array<size_t, 3> maxSizes = d.max_work_item_sizes();
 
     *err.data() = 0; ASSERT( err.data() != std::string( "Done" ), NULL );
@@ -645,7 +645,7 @@ void CustomFactoryTest() {
 
     REMARK( "  One device tests:\n" );
     graph g;
-    opencl_device_list all_devices = interface10::opencl_info::available_devices();
+    opencl_device_list all_devices = interface11::opencl_info::available_devices();
     for ( int i = 0; i < (int)all_devices.size(); ++i ) {
         opencl_device_list::const_iterator it = all_devices.begin();
         std::advance( it, i );
@@ -664,7 +664,7 @@ void CustomFactoryTest() {
 void DefaultConcurrencyTest() {
     REMARK( "DefaultConcurrencyTest: " );
     // By default, the first device is selected.
-    ConcurrencyTest( { *interface10::opencl_info::available_devices().begin() } );
+    ConcurrencyTest( { *interface11::opencl_info::available_devices().begin() } );
     REMARK( "done\n" );
 }
 
@@ -672,7 +672,7 @@ void DefaultConcurrencyTest() {
 void SpirKernelTest() {
     REMARK( "SpirKernelTest:\n" );
 
-    const opencl_device_list devices = interface10::opencl_info::available_devices();
+    const opencl_device_list devices = interface11::opencl_info::available_devices();
 
     for( auto d = devices.begin(); d != devices.end(); d++ ) {
         if( !(*d).extension_available( "cl_khr_spir" ) ) {
@@ -727,7 +727,7 @@ void PrecompiledKernelTest() {
     graph g;
     DefaultFactoryType factory;
 
-    const opencl_device_list devices = interface10::opencl_info::available_devices();
+    const opencl_device_list devices = interface11::opencl_info::available_devices();
     opencl_device_list::const_iterator it = std::find_if(
         devices.cbegin(), devices.cend(),
         []( const opencl_device &d ) {
index 3e3fe3c..d0a2589 100644 (file)
 #define TBB_DEPRECATED_FLOW_NODE_EXTRACTION 1
 #endif
 
+#include "harness.h"
 #include "harness_graph.h"
 
 #include "tbb/flow_graph.h"
 #include "tbb/task_scheduler_init.h"
+#include "test_follows_and_precedes_api.h"
 
 #define N 300
 #define T 4
@@ -139,6 +141,41 @@ void parallel_read_write_tests() {
     }
 }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+#include <array>
+#include <vector>
+void test_follows_and_precedes_api() {
+    using msg_t = tbb::flow::continue_msg;
+
+    std::array<msg_t, 3> messages_for_follows = {msg_t(), msg_t(), msg_t()};
+    std::vector<msg_t> messages_for_precedes = {msg_t()};
+
+    follows_and_precedes_testing::test_follows<msg_t, tbb::flow::overwrite_node<msg_t>>(messages_for_follows);
+    follows_and_precedes_testing::test_precedes<msg_t, tbb::flow::overwrite_node<msg_t>>(messages_for_precedes);
+}
+#endif
+
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+void test_deduction_guides() {
+    using namespace tbb::flow;
+
+    graph g;
+    broadcast_node<int> b1(g);
+    overwrite_node<int> o0(g);
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    overwrite_node o1(follows(b1));
+    static_assert(std::is_same_v<decltype(o1), overwrite_node<int>>);
+
+    overwrite_node o2(precedes(b1));
+    static_assert(std::is_same_v<decltype(o2), overwrite_node<int>>);
+#endif
+
+    overwrite_node o3(o0);
+    static_assert(std::is_same_v<decltype(o3), overwrite_node<int>>);
+}
+#endif
+
 int TestMain() {
     if( MinThread<1 ) {
         REPORT("number of threads must be positive\n");
@@ -156,6 +193,11 @@ int TestMain() {
     test_extract_on_node<tbb::flow::overwrite_node, int>();
     test_extract_on_node<tbb::flow::overwrite_node, float>();
 #endif
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    test_follows_and_precedes_api();
+#endif
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+    test_deduction_guides();
+#endif
     return Harness::Done;
 }
-
index 3e632ee..3adf265 100644 (file)
@@ -27,6 +27,10 @@ int filter_node_count = 0;
 #include "tbb/tbb_allocator.h"
 #include "tbb/spin_mutex.h"
 
+#if __TBB_CPP11_RVALUE_REF_PRESENT
+#include <memory> // std::unique_ptr
+#endif
+
 const unsigned n_tokens = 8;
 // we can conceivably have two buffers used in the middle filter for every token in flight, so
 // we must allocate two buffers for every token.  Unlikely, but possible.
@@ -632,12 +636,12 @@ void run_function(const char *l1, const char *l2) {
 int TestMain() {
 #if TBB_USE_DEBUG
     // size and copyability.
-    REMARK("is_large_object<int>::value=%d\n", tbb::interface6::internal::is_large_object<int>::value);
-    REMARK("is_large_object<double>::value=%d\n", tbb::interface6::internal::is_large_object<double>::value);
-    REMARK("is_large_object<int *>::value=%d\n", tbb::interface6::internal::is_large_object<int *>::value);
-    REMARK("is_large_object<check_type<int> >::value=%d\n", tbb::interface6::internal::is_large_object<check_type<int> >::value);
-    REMARK("is_large_object<check_type<int>* >::value=%d\n", tbb::interface6::internal::is_large_object<check_type<int>* >::value);
-    REMARK("is_large_object<check_type<short> >::value=%d\n\n", tbb::interface6::internal::is_large_object<check_type<short> >::value);
+    REMARK("use_allocator<int>::value=%d\n", tbb::interface6::internal::use_allocator<int>::value);
+    REMARK("use_allocator<double>::value=%d\n", tbb::interface6::internal::use_allocator<double>::value);
+    REMARK("use_allocator<int *>::value=%d\n", tbb::interface6::internal::use_allocator<int *>::value);
+    REMARK("use_allocator<check_type<int> >::value=%d\n", tbb::interface6::internal::use_allocator<check_type<int> >::value);
+    REMARK("use_allocator<check_type<int>* >::value=%d\n", tbb::interface6::internal::use_allocator<check_type<int>* >::value);
+    REMARK("use_allocator<check_type<short> >::value=%d\n\n", tbb::interface6::internal::use_allocator<check_type<short> >::value);
 #endif
     // Test with varying number of threads.
     for( int nthread=MinThread; nthread<=MaxThread; ++nthread ) {
@@ -647,17 +651,22 @@ int TestMain() {
 
         // Run test several times with different types
         run_function_spec();
-        run_function<size_t,int>("size_t", "int");
-        run_function<int,double>("int", "double");
-        run_function<size_t,double>("size_t", "double");
-        run_function<size_t,bool>("size_t", "bool");
-        run_function<int,int>("int","int");
-        run_function<check_type<unsigned int>,size_t>("check_type<unsigned int>", "size_t");
-        run_function<check_type<unsigned short>,size_t>("check_type<unsigned short>", "size_t");
-        run_function<check_type<unsigned int>, check_type<unsigned int> >("check_type<unsigned int>", "check_type<unsigned int>");
-        run_function<check_type<unsigned int>, check_type<unsigned short> >("check_type<unsigned int>", "check_type<unsigned short>");
-        run_function<check_type<unsigned short>, check_type<unsigned short> >("check_type<unsigned short>", "check_type<unsigned short>");
-        run_function<double, check_type<unsigned short> >("double", "check_type<unsigned short>");
+        #define RUN_FUNCTION(type1, type2) run_function<type1, type2>(#type1, #type2);
+        RUN_FUNCTION(size_t, int)
+        RUN_FUNCTION(int, double)
+        RUN_FUNCTION(size_t, double)
+        RUN_FUNCTION(size_t, bool)
+        RUN_FUNCTION(int, int)
+        RUN_FUNCTION(check_type<unsigned int>, size_t)
+        RUN_FUNCTION(check_type<unsigned short>, size_t)
+        RUN_FUNCTION(check_type<unsigned int>, check_type<unsigned int>)
+        RUN_FUNCTION(check_type<unsigned int>, check_type<unsigned short>)
+        RUN_FUNCTION(check_type<unsigned short>, check_type<unsigned short>)
+        RUN_FUNCTION(double, check_type<unsigned short>)
+#if __TBB_CPP11_RVALUE_REF_PRESENT
+        RUN_FUNCTION(std::unique_ptr<int>, std::unique_ptr<int>) // move-only type
+#endif
+        #undef RUN_FUNCTION
     }
     return Harness::Done;
 }
index 82455fc..0c5dc79 100644 (file)
@@ -19,8 +19,6 @@
 #include "tbb/atomic.h"
 #include "harness_assert.h"
 
-using namespace std;
-
 static tbb::atomic<long> ForkCount;
 static tbb::atomic<long> FooBodyCount;
 
@@ -95,7 +93,6 @@ public:
     }
 };
 
-#include <cstdio>
 #include "harness.h"
 #include "tbb/tick_count.h"
 
index a731106..495ecc8 100644 (file)
@@ -18,9 +18,6 @@
 
 #include <typeinfo>
 
-#include "tbb/tbb_thread.h"
-#include "tbb/enumerable_thread_specific.h"
-
 #include "string.h"
 #include "harness_assert.h"
 #include "test_partitioner.h"
@@ -33,10 +30,6 @@ const size_t max_simulated_threads = 256;
 const size_t max_simulated_threads = 640;
 #endif
 
-typedef tbb::enumerable_thread_specific<size_t> ThreadNumsType;
-size_t g_threadNumInitialValue = 10;
-ThreadNumsType g_threadNums(g_threadNumInitialValue);
-
 namespace whitebox_simulation {
 size_t whitebox_thread_index = 0;
 test_partitioner_utils::BinaryTree reference_tree;
@@ -46,9 +39,11 @@ test_partitioner_utils::BinaryTree reference_tree;
 namespace tbb {
 namespace internal {
 typedef unsigned short affinity_id;
+void* internal_current_suspend_point() { return NULL; }
 }
 class fake_task {
 public:
+    typedef void* suspend_point;
     typedef internal::affinity_id affinity_id;
     void set_affinity(affinity_id a) { my_affinity = a; }
     affinity_id affinity() const { return my_affinity; }
@@ -79,6 +74,8 @@ inline int current_thread_index() { return (int)whitebox_simulation::whitebox_th
 #define get_initial_auto_partitioner_divisor my_get_initial_auto_partitioner_divisor
 #define affinity_partitioner_base_v3 my_affinity_partitioner_base_v3
 #define task fake_task
+#include "tbb/tbb_thread.h"
+#include "tbb/enumerable_thread_specific.h"
 #define __TBB_STATIC_THRESHOLD 0
 #include "tbb/partitioner.h"
 #undef __TBB_STATIC_THRESHOLD
@@ -86,6 +83,10 @@ inline int current_thread_index() { return (int)whitebox_simulation::whitebox_th
 #undef affinity_partitioner_base_v3
 #undef get_initial_auto_partitioner_divisor
 
+typedef tbb::enumerable_thread_specific<size_t> ThreadNumsType;
+size_t g_threadNumInitialValue = 10;
+ThreadNumsType g_threadNums(g_threadNumInitialValue);
+
 // replace library functions to simulate concurrency
 namespace tbb {
 namespace internal {
index d3b3f54..081fea7 100644 (file)
 
 // TO DO: Add overlapping put / receive tests
 
-#include "harness.h"
-
 #if __TBB_CPF_BUILD
 #define TBB_DEPRECATED_FLOW_NODE_EXTRACTION 1
 #endif
 
+#include "harness.h"
+
 #include "tbb/flow_graph.h"
 #include "harness_checktype.h"
 #include "tbb/task_scheduler_init.h"
 #include "tbb/tick_count.h"
 #include "harness_graph.h"
+#include "test_follows_and_precedes_api.h"
 
 #include <cstdio>
 
@@ -332,6 +333,47 @@ int test_serial() {
     return 0;
 }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+#include <array>
+#include <vector>
+void test_follows_and_precedes_api() {
+    std::array<int, 3> messages_for_follows = {0, 1, 2};
+    std::vector<int> messages_for_precedes = {0, 1, 2};
+
+    follows_and_precedes_testing::test_follows <int, tbb::flow::priority_queue_node<int>>(messages_for_follows);
+    follows_and_precedes_testing::test_precedes <int, tbb::flow::priority_queue_node<int>>(messages_for_precedes);
+}
+#endif
+
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+void test_deduction_guides() {
+    using namespace tbb::flow;
+
+    graph g;
+    broadcast_node<int> br(g);
+    priority_queue_node<int> pq0(g);
+    using compare_type = std::greater<void>;
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    priority_queue_node pq1(follows(br));
+    static_assert(std::is_same_v<decltype(pq1), priority_queue_node<int>>);
+
+    priority_queue_node pq2(follows(br), compare_type());
+    static_assert(std::is_same_v<decltype(pq2), priority_queue_node<int, compare_type>>);
+
+    priority_queue_node pq3(precedes(br));
+    static_assert(std::is_same_v<decltype(pq3), priority_queue_node<int>>);
+
+    priority_queue_node pq4(precedes(br), compare_type());
+    static_assert(std::is_same_v<decltype(pq4), priority_queue_node<int, compare_type>>);
+#endif
+
+    priority_queue_node pq5(pq0);
+    static_assert(std::is_same_v<decltype(pq5), priority_queue_node<int>>);
+    g.wait_for_all();
+}
+#endif
+
 int TestMain() {
     tbb::tick_count start = tbb::tick_count::now(), stop;
     for (int p = 2; p <= 4; ++p) {
@@ -349,5 +391,11 @@ int TestMain() {
 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
     test_buffer_extract<tbb::flow::priority_queue_node<int> >().run_tests();
 #endif
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    test_follows_and_precedes_api();
+#endif
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+    test_deduction_guides();
+#endif
     return Harness::Done;
 }
index de688dc..9862ea8 100644 (file)
 
 // TO DO: Add overlapping put / receive tests
 
-#include "harness.h"
-
 #if __TBB_CPF_BUILD
 #define TBB_DEPRECATED_FLOW_NODE_EXTRACTION 1
 #endif
 
+#include "harness.h"
+
 #include "tbb/flow_graph.h"
 #include "tbb/task_scheduler_init.h"
 #include "tbb/tick_count.h"
 #include "harness_checktype.h"
 #include "harness_graph.h"
+#include "test_follows_and_precedes_api.h"
 
 #include <cstdio>
 
@@ -447,6 +448,39 @@ int test_serial() {
     return 0;
 }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+#include <array>
+#include <vector>
+void test_follows_and_precedes_api() {
+    std::array<int, 3> messages_for_follows = {0, 1, 2};
+    std::vector<int> messages_for_precedes = {0, 1, 2};
+
+    follows_and_precedes_testing::test_follows <int, tbb::flow::queue_node<int>>(messages_for_follows);
+    follows_and_precedes_testing::test_precedes <int, tbb::flow::queue_node<int>>(messages_for_precedes);
+}
+#endif
+
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+void test_deduction_guides() {
+    using namespace tbb::flow;
+    graph g;
+    broadcast_node<int> br(g);
+    queue_node<int> q0(g);
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    queue_node q1(follows(br));
+    static_assert(std::is_same_v<decltype(q1), queue_node<int>>);
+
+    queue_node q2(precedes(br));
+    static_assert(std::is_same_v<decltype(q2), queue_node<int>>);
+#endif
+
+    queue_node q3(q0);
+    static_assert(std::is_same_v<decltype(q3), queue_node<int>>);
+    g.wait_for_all();
+}
+#endif
+
 int TestMain() {
     tbb::tick_count start = tbb::tick_count::now(), stop;
     for (int p = 2; p <= 4; ++p) {
@@ -464,5 +498,11 @@ int TestMain() {
 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
     test_buffer_extract<tbb::flow::queue_node<int> >().run_tests();
 #endif
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    test_follows_and_precedes_api();
+#endif
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+    test_deduction_guides();
+#endif
     return Harness::Done;
 }
diff --git a/src/test/test_resumable_tasks.cpp b/src/test/test_resumable_tasks.cpp
new file mode 100644 (file)
index 0000000..d1840fa
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+    Copyright (c) 2005-2019 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.
+*/
+
+#include "tbb/tbb_config.h"
+
+#include "harness.h"
+
+#if !__TBB_PREVIEW_RESUMABLE_TASKS
+int TestMain() {
+    return Harness::Skipped;
+}
+#else // __TBB_PREVIEW_RESUMABLE_TASKS
+
+#include "tbb/task.h"
+#include "tbb/concurrent_queue.h"
+#include "tbb/atomic.h"
+#include "tbb/parallel_for.h"
+#include "tbb/task_scheduler_init.h"
+#include "tbb/enumerable_thread_specific.h"
+#include "tbb/task_arena.h"
+#include "tbb/task_group.h"
+#include "tbb/tbb_thread.h"
+
+#include <vector>
+
+typedef tbb::enumerable_thread_specific<int, tbb::cache_aligned_allocator<int> > ets_int_t;
+const int N = 10;
+
+// External activity used in all tests, which resumes suspended execution point
+class AsyncActivity {
+public:
+    AsyncActivity(int num_) : m_numAsyncThreads(num_) {
+        for (int i = 0; i < m_numAsyncThreads ; ++i) {
+            m_asyncThreads.push_back( new tbb::tbb_thread(AsyncActivity::asyncLoop, this) );
+        }
+    }
+    ~AsyncActivity() {
+        for (int i = 0; i < m_numAsyncThreads; ++i) {
+            m_tagQueue.push(NULL);
+        }
+        for (int i = 0; i < m_numAsyncThreads; ++i) {
+            m_asyncThreads[i]->join();
+            delete m_asyncThreads[i];
+        }
+        ASSERT(m_tagQueue.empty(), NULL);
+    }
+    void submit(void* ctx) {
+        m_tagQueue.push(ctx);
+    }
+
+private:
+    static void asyncLoop(AsyncActivity* async) {
+        tbb::task::suspend_point tag;
+        async->m_tagQueue.pop(tag);
+        while (tag) {
+            tbb::task::resume(tag);
+            async->m_tagQueue.pop(tag);
+        }
+    }
+
+    const int m_numAsyncThreads;
+    tbb::concurrent_bounded_queue<void*> m_tagQueue;
+    std::vector<tbb::tbb_thread*> m_asyncThreads;
+};
+
+struct SuspendBody {
+    SuspendBody(AsyncActivity& a_) :
+        m_asyncActivity(a_) {}
+    void operator()(tbb::task::suspend_point tag) {
+        m_asyncActivity.submit(tag);
+    }
+
+private:
+    AsyncActivity& m_asyncActivity;
+};
+
+class InnermostArenaBody {
+public:
+    InnermostArenaBody(AsyncActivity& a_) : m_asyncActivity(a_) {}
+
+    void operator()() {
+        InnermostOuterParFor inner_outer_body(m_asyncActivity);
+        tbb::parallel_for(0, N, inner_outer_body );
+    }
+
+private:
+    struct InnermostInnerParFor {
+        InnermostInnerParFor(AsyncActivity& a_) : m_asyncActivity(a_) {}
+        void operator()(int) const {
+            tbb::task::suspend(SuspendBody(m_asyncActivity));
+        }
+        AsyncActivity& m_asyncActivity;
+    };
+    struct InnermostOuterParFor {
+        InnermostOuterParFor(AsyncActivity& a_) : m_asyncActivity(a_) {}
+        void operator()(int) const {
+            tbb::task::suspend(SuspendBody(m_asyncActivity));
+            InnermostInnerParFor inner_inner_body(m_asyncActivity);
+            tbb::parallel_for(0, N, inner_inner_body);
+        }
+        AsyncActivity& m_asyncActivity;
+    };
+    AsyncActivity& m_asyncActivity;
+};
+
+class OutermostArenaBody {
+public:
+    OutermostArenaBody(AsyncActivity& a_, tbb::task_arena& o_, tbb::task_arena& i_, tbb::task_arena& id_, ets_int_t& ets_) :
+        m_asyncActivity(a_), m_outermostArena(o_), m_innermostArena(i_), m_innermostArenaDefault(id_), m_etsInner(ets_) {}
+
+    void operator()() {
+        tbb::parallel_for(0, 32, *this);
+    }
+
+    void operator()(int i) const {
+        tbb::task::suspend(SuspendBody(m_asyncActivity));
+
+        tbb::task_arena& nested_arena = (i % 3 == 0) ?
+            m_outermostArena : (i % 3 == 1 ? m_innermostArena : m_innermostArenaDefault);
+
+        if (i % 3 != 0) {
+            // We can only guarantee recall coorectness for "not-same" nested arenas entry
+            m_etsInner.local() = i;
+        }
+        InnermostArenaBody innermost_arena_body(m_asyncActivity);
+        nested_arena.execute(innermost_arena_body);
+        if (i % 3 != 0) {
+            ASSERT(i == m_etsInner.local(), "Original thread wasn't recalled for innermost nested arena.");
+        }
+    }
+
+private:
+    AsyncActivity& m_asyncActivity;
+    tbb::task_arena& m_outermostArena;
+    tbb::task_arena& m_innermostArena;
+    tbb::task_arena& m_innermostArenaDefault;
+    ets_int_t& m_etsInner;
+};
+
+void TestNestedArena() {
+    AsyncActivity asyncActivity(4);
+
+    ets_int_t ets_outer;
+    ets_int_t ets_inner;
+
+    tbb::task_arena outermost_arena;
+    tbb::task_arena innermost_arena(2,2);
+    tbb::task_arena innermost_arena_default;
+
+    outermost_arena.initialize();
+    innermost_arena_default.initialize();
+    innermost_arena.initialize();
+
+    ets_outer.local() = 42;
+    OutermostArenaBody outer_arena_body(asyncActivity, outermost_arena, innermost_arena, innermost_arena_default, ets_inner);
+    outermost_arena.execute(outer_arena_body);
+    ASSERT(ets_outer.local() == 42, "Original/main thread wasn't recalled.");
+}
+
+#if __TBB_CPP11_LAMBDAS_PRESENT
+
+#include <thread>
+
+// External activity used in all tests, which resumes suspended execution point
+class EpochAsyncActivity {
+public:
+    EpochAsyncActivity(int num_, tbb::atomic<int>& e_) : m_numAsyncThreads(num_), m_globalEpoch(e_) {
+        for (int i = 0; i < m_numAsyncThreads ; ++i) {
+            m_asyncThreads.push_back( new tbb::tbb_thread(EpochAsyncActivity::asyncLoop, this) );
+        }
+    }
+    ~EpochAsyncActivity() {
+        for (int i = 0; i < m_numAsyncThreads; ++i) {
+            m_ctxQueue.push(NULL);
+        }
+        for (int i = 0; i < m_numAsyncThreads; ++i) {
+            m_asyncThreads[i]->join();
+            delete m_asyncThreads[i];
+        }
+        ASSERT(m_ctxQueue.empty(), NULL);
+    }
+    void submit(void* ctx) {
+        m_ctxQueue.push(ctx);
+    }
+
+private:
+    static void asyncLoop(EpochAsyncActivity* async) {
+        tbb::task::suspend_point ctx;
+        async->m_ctxQueue.pop(ctx);
+        while (ctx) {
+            // Track the global epoch
+            async->m_globalEpoch++;
+            // Continue execution from suspended ctx
+            tbb::task::resume(ctx);
+            async->m_ctxQueue.pop(ctx);
+        }
+    }
+
+    const int m_numAsyncThreads;
+    tbb::atomic<int>& m_globalEpoch;
+    tbb::concurrent_bounded_queue<void*> m_ctxQueue;
+    std::vector<tbb::tbb_thread*> m_asyncThreads;
+};
+
+struct EpochSuspendBody {
+    EpochSuspendBody(EpochAsyncActivity& a_, tbb::atomic<int>& e_, int& le_) :
+        m_asyncActivity(a_), m_globalEpoch(e_), m_localEpoch(le_) {}
+
+    void operator()(tbb::task::suspend_point ctx) {
+        m_localEpoch = m_globalEpoch;
+        m_asyncActivity.submit(ctx);
+    }
+
+private:
+    EpochAsyncActivity& m_asyncActivity;
+    tbb::atomic<int>& m_globalEpoch;
+    int& m_localEpoch;
+};
+
+// Simple test for basic resumable tasks functionality
+void TestSuspendResume() {
+    tbb::atomic<int> global_epoch; global_epoch = 0;
+    EpochAsyncActivity async(4, global_epoch);
+
+    tbb::enumerable_thread_specific<int, tbb::cache_aligned_allocator<int>, tbb::ets_suspend_aware> ets_fiber;
+    tbb::atomic<int> inner_par_iters, outer_par_iters;
+    inner_par_iters = outer_par_iters = 0;
+
+    tbb::parallel_for(0, N, [&](int) {
+        for (int i = 0; i < 100; ++i) {
+            ets_fiber.local() = i;
+
+            int local_epoch;
+            tbb::task::suspend(EpochSuspendBody(async, global_epoch, local_epoch));
+            ASSERT(local_epoch < global_epoch, NULL);
+            ASSERT(ets_fiber.local() == i, NULL);
+
+            tbb::parallel_for(0, N, [&](int) {
+                int local_epoch2;
+                tbb::task::suspend(EpochSuspendBody(async, global_epoch, local_epoch2));
+                ASSERT(local_epoch2 < global_epoch, NULL);
+                ++inner_par_iters;
+            });
+
+            ets_fiber.local() = i;
+            tbb::task::suspend(EpochSuspendBody(async, global_epoch, local_epoch));
+            ASSERT(local_epoch < global_epoch, NULL);
+            ASSERT(ets_fiber.local() == i, NULL);
+        }
+        ++outer_par_iters;
+    });
+    ASSERT(outer_par_iters == N, NULL);
+    ASSERT(inner_par_iters == N*N*100, NULL);
+}
+
+// During cleanup master's local task pool may
+// e.g. contain proxies of affinitized tasks, but can be recalled
+void TestCleanupMaster() {
+    AsyncActivity asyncActivity(4);
+    tbb::task_group tg;
+    tbb::enumerable_thread_specific<int> ets;
+    tbb::atomic<int> iter_spawned;
+    tbb::atomic<int> iter_executed;
+
+    for (int i = 0; i < 100; i++) {
+        ets.local() = i;
+        iter_spawned = 0;
+        iter_executed = 0;
+
+        NativeParallelFor(N, [&asyncActivity, &tg, &iter_spawned, &iter_executed](int j) {
+            tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred);
+            if (tbb::task_scheduler_init::default_num_threads() == 1) {
+                init.initialize(2);
+            }
+            for (int k = 0; k < j*10 + 1; ++k) {
+                tg.run([&asyncActivity, j, &iter_executed] {
+                    for (volatile int l = 0; l < j*10; ++l) {}
+                    tbb::task::suspend(SuspendBody(asyncActivity));
+                    iter_executed++;
+                });
+                iter_spawned++;
+            }
+        });
+        ASSERT(iter_spawned == 460, NULL);
+        tg.wait();
+        ASSERT(iter_executed == 460, NULL);
+        ASSERT(ets.local() == i, NULL);
+    }
+}
+
+class ParForSuspendBody {
+    AsyncActivity& asyncActivity;
+    int m_numIters;
+public:
+    ParForSuspendBody(AsyncActivity& a_, int iters) : asyncActivity(a_), m_numIters(iters) {}
+    void operator()(int) const {
+        for (volatile int i = 0; i < m_numIters; ++i) {}
+        tbb::task::suspend(SuspendBody(asyncActivity));
+    }
+};
+
+class InnerParFor {
+    AsyncActivity& asyncActivity;
+public:
+    InnerParFor(AsyncActivity& a_) : asyncActivity(a_) {}
+    void operator()(int) const {
+        tbb::affinity_partitioner ap;
+        tbb::task_group_context ctx;
+        ctx.set_priority(tbb::priority_high);
+        tbb::parallel_for(0, 10, ParForSuspendBody(asyncActivity, 1000), ap, ctx);
+    }
+};
+
+void TestPriorities() {
+    AsyncActivity asyncActivity(4);
+
+    tbb::task_scheduler_init init;
+    tbb::affinity_partitioner ap;
+    tbb::enumerable_thread_specific<int> ets;
+    for (int i = 0; i < 10; ++i) {
+        ets.local() = i;
+        tbb::parallel_for(0, 10, InnerParFor(asyncActivity), ap);
+        ASSERT(ets.local() == i, NULL);
+    }
+}
+
+void TestNativeThread() {
+    AsyncActivity asyncActivity(4);
+
+    int num_threads = tbb::task_scheduler_init::default_num_threads();
+    tbb::task_arena arena(num_threads);
+    tbb::task_group tg;
+    tbb::atomic<int> iter = 0;
+    NativeParallelFor(num_threads / 2, [&arena, &tg, &asyncActivity, &iter](int){
+        for (int i = 0; i < 10; i++) {
+            arena.execute([&tg, &asyncActivity, &iter]() {
+                tg.run([&asyncActivity]() {
+                    tbb::task::suspend(SuspendBody(asyncActivity));
+                });
+                iter++;
+            });
+        }
+    });
+
+    tbb::enumerable_thread_specific<bool> ets;
+    ets.local() = true;
+    ASSERT(iter == (num_threads / 2) * 10, NULL);
+    arena.execute([&tg](){
+        tg.wait();
+    });
+    ASSERT(ets.local() == true, NULL);
+}
+#endif
+
+int TestMain() {
+    tbb::enumerable_thread_specific<bool> ets;
+    ets.local() = true;
+
+    tbb::task_scheduler_init init(max(tbb::task_scheduler_init::default_num_threads(), 16));
+
+    TestNestedArena();
+#if __TBB_CPP11_LAMBDAS_PRESENT
+    // Using functors would make this test much bigger and with
+    // unnecessary complexity, one C++03 TestNestedArena is enough
+    TestSuspendResume();
+    TestCleanupMaster();
+    TestPriorities();
+    TestNativeThread();
+#endif
+    ASSERT(ets.local() == true, NULL);
+    return Harness::Done;
+}
+
+#endif // !__TBB_PREVIEW_RESUMABLE_TASKS
+
index 4d40bed..3be1f56 100644 (file)
     limitations under the License.
 */
 
-#include "harness.h"
-
 #if __TBB_CPF_BUILD
 #define TBB_DEPRECATED_FLOW_NODE_EXTRACTION 1
 #endif
 
+#include "harness.h"
+#include "harness_graph.h"
+
 #include "tbb/flow_graph.h"
 #include "tbb/task_scheduler_init.h"
 #include "tbb/tick_count.h"
 #include "tbb/atomic.h"
-#if TBB_PREVIEW_FLOW_GRAPH_FEATURES
-#include "harness_graph.h"
-#endif
+#include "test_follows_and_precedes_api.h"
 
 #include <cstdio>
 
@@ -389,6 +388,51 @@ int test_serial() {
     return 0;
 }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+#include <array>
+#include <vector>
+void test_follows_and_precedes_api() {
+    std::array<int, 3> messages_for_follows = {0, 1, 2};
+    std::vector<int> messages_for_precedes = {0, 1, 2};
+
+    follows_and_precedes_testing::test_follows
+        <int, tbb::flow::sequencer_node<int>>
+        (messages_for_follows, [](const int& i) { return i; });
+
+    follows_and_precedes_testing::test_precedes
+        <int, tbb::flow::sequencer_node<int>>
+        (messages_for_precedes, [](const int& i) { return i; });
+}
+#endif
+
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+template <typename Body>
+void test_deduction_guides_common(Body body) {
+    using namespace tbb::flow;
+    graph g;
+    broadcast_node<int> br(g);
+
+    sequencer_node s1(g, body);
+    static_assert(std::is_same_v<decltype(s1), sequencer_node<int>>);
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    sequencer_node s2(follows(br), body);
+    static_assert(std::is_same_v<decltype(s2), sequencer_node<int>>);
+#endif
+
+    sequencer_node s3(s1);
+    static_assert(std::is_same_v<decltype(s3), sequencer_node<int>>);
+}
+
+int sequencer_body_f(const int&) { return 1; }
+
+void test_deduction_guides() {
+    test_deduction_guides_common([](const int&)->int { return 1; });
+    test_deduction_guides_common([](const int&) mutable ->int { return 1; });
+    test_deduction_guides_common(sequencer_body_f);
+}
+#endif
+
 int TestMain() {
     tbb::tick_count start = tbb::tick_count::now(), stop;
     for (int p = 2; p <= 4; ++p) {
@@ -399,6 +443,12 @@ int TestMain() {
 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
     test_buffer_extract<tbb::flow::sequencer_node<int> >().run_tests();
 #endif
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    test_follows_and_precedes_api();
+#endif
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+    test_deduction_guides();
+#endif
     stop = tbb::tick_count::now();
     REMARK("Sequencer_Node Time=%6.6f\n", (stop-start).seconds());
     return Harness::Done;
index 896c1af..2f064f6 100644 (file)
@@ -15,6 +15,7 @@
 */
 
 // have to expose the reset_node method to be able to reset a function_body
+
 #include "harness.h"
 
 #if __TBB_CPF_BUILD
@@ -65,7 +66,7 @@ public:
        return const_cast<tbb::task *>(SUCCESSFULLY_ENQUEUED);
     }
 
-    tbb::flow::graph& graph_reference() __TBB_override {
+    tbb::flow::graph& graph_reference() const __TBB_override {
         return my_graph;
     }
 
@@ -401,6 +402,83 @@ void test_extract() {
 }
 #endif  /* TBB_DEPRECATED_FLOW_NODE_EXTRACTION */
 
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+bool source_body_f(int& i) { return i > 5; }
+
+void test_deduction_guides() {
+    using namespace tbb::flow;
+    graph g;
+
+    auto lambda = [](int& i) { return i > 5; };
+    auto non_const_lambda = [](int& i) mutable { return i > 5; };
+
+    // Tests for source_node(graph&, Body)
+    source_node s1(g, lambda);
+    static_assert(std::is_same_v<decltype(s1), source_node<int>>);
+
+    source_node s2(g, non_const_lambda);
+    static_assert(std::is_same_v<decltype(s2), source_node<int>>);
+
+    source_node s3(g, source_body_f);
+    static_assert(std::is_same_v<decltype(s3), source_node<int>>);
+
+    source_node s4(s3);
+    static_assert(std::is_same_v<decltype(s4), source_node<int>>);
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    broadcast_node<int> bc(g);
+
+    // Tests for source_node(const node_set<Args...>&, Body)
+    source_node s5(precedes(bc), lambda);
+    static_assert(std::is_same_v<decltype(s5), source_node<int>>);
+
+    source_node s6(precedes(bc), non_const_lambda);
+    static_assert(std::is_same_v<decltype(s6), source_node<int>>);
+
+    source_node s7(precedes(bc), source_body_f);
+    static_assert(std::is_same_v<decltype(s7), source_node<int>>);
+#endif
+    g.wait_for_all();
+}
+
+#endif // __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+#include <array>
+void test_follows_and_precedes_api() {
+    using namespace tbb::flow;
+
+    graph g;
+
+    std::array<buffer_node<bool>, 3> successors {
+        buffer_node<bool>(g),
+        buffer_node<bool>(g),
+        buffer_node<bool>(g)
+    };
+
+    bool do_try_put = true;
+    source_node<bool> src(precedes(successors[0], successors[1], successors[2]), [&](bool& v) -> bool {
+        if(do_try_put) {
+            v = do_try_put;
+            do_try_put = false;
+            return true;
+        }
+        else {
+            return false;
+        }
+    }, false);
+
+    src.activate();
+    g.wait_for_all();
+
+    bool storage;
+    for(auto& successor: successors) {
+        ASSERT((successor.try_get(storage) && !successor.try_get(storage)),
+            "Not exact edge quantity was made");
+    }
+}
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
 int TestMain() {
     if( MinThread<1 ) {
         REPORT("number of threads must be positive\n");
@@ -415,6 +493,12 @@ int TestMain() {
 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
     test_extract();
 #endif
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    test_follows_and_precedes_api();
+#endif
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+    test_deduction_guides();
+#endif
     return Harness::Done;
 }
 
index 5a152ce..3750297 100644 (file)
@@ -98,7 +98,6 @@ class source_body {
     int addend;
 public:
     source_body(int init_val, int addto) : my_count(init_val), addend(addto) { }
-    void operator=( const source_body& other) { my_count = other.my_count; addend = other.addend; }
     bool operator()( TT &v) {
         if(my_count >= Count) return false;
         tuple_helper<N>::set_element(v, my_count);
@@ -279,6 +278,45 @@ void test_one_serial( SType &my_split, tbb::flow::graph &g) {
 
 }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+void test_follow_and_precedes_api() {
+    using namespace tbb::flow;
+    using msg_t = tuple<int, float, double>;
+
+    graph g;
+
+    function_node<msg_t, msg_t> f1(g, unlimited, [](msg_t msg) { return msg; } );
+    auto f2(f1);
+    auto f3(f1);
+
+    tbb::atomic<int> body_calls = 0;
+
+    function_node<int, int> f4(g, unlimited, [&](int val) { ++body_calls; return val; } );
+    function_node<float, float> f5(g, unlimited, [&](float val) { ++body_calls; return val; } );
+    function_node<double, double> f6(g, unlimited, [&](double val) { ++body_calls; return val; } );
+
+    split_node<msg_t> following_node(follows(f1, f2, f3));
+    make_edge(output_port<0>(following_node), f4);
+    make_edge(output_port<1>(following_node), f5);
+    make_edge(output_port<2>(following_node), f6);
+
+    split_node<msg_t> preceding_node(precedes(f4, f5, f6));
+    make_edge(f1, preceding_node);
+    make_edge(f2, preceding_node);
+    make_edge(f3, preceding_node);
+
+    msg_t msg(1, 2.2, 3.3);
+    f1.try_put(msg);
+    f2.try_put(msg);
+    f3.try_put(msg);
+
+    g.wait_for_all();
+
+    // <number of try puts> * <number of splits by a source node> * <number of source nodes>
+    ASSERT((body_calls == 3*3*2), "Not exact edge quantity was made");
+}
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
 template<typename SType>
 class serial_test {
     typedef typename SType::input_type TType;
@@ -317,39 +355,71 @@ struct generate_test {
     }
 }; // generate_test
 
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+
+void test_deduction_guides() {
+    using namespace tbb::flow;
+    using tuple_type = std::tuple<int, int>;
+
+    graph g;
+    split_node<tuple_type> s0(g);
+
+    split_node s1(s0);
+    static_assert(std::is_same_v<decltype(s1), split_node<tuple_type>>);
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    broadcast_node<tuple_type> b1(g), b2(g);
+    broadcast_node<int> b3(g), b4(g);
+
+    split_node s2(follows(b1, b2));
+    static_assert(std::is_same_v<decltype(s2), split_node<tuple_type>>);
+
+    split_node s3(precedes(b3, b4));
+    static_assert(std::is_same_v<decltype(s3), split_node<tuple_type>>);
+#endif
+}
+
+#endif
+
 int TestMain() {
 #if __TBB_USE_TBB_TUPLE
     REMARK("  Using TBB tuple\n");
 #else
     REMARK("  Using platform tuple\n");
 #endif
-   for (int p = 0; p < 2; ++p) {
-       generate_test<serial_test, tbb::flow::tuple<float, double> >::do_test();
+    for (int p = 0; p < 2; ++p) {
+        generate_test<serial_test, tbb::flow::tuple<float, double> >::do_test();
 #if MAX_TUPLE_TEST_SIZE >= 4
-       generate_test<serial_test, tbb::flow::tuple<float, double, int, long> >::do_test();
+        generate_test<serial_test, tbb::flow::tuple<float, double, int, long> >::do_test();
 #endif
 #if MAX_TUPLE_TEST_SIZE >= 6
-       generate_test<serial_test, tbb::flow::tuple<double, double, int, long, int, short> >::do_test();
+        generate_test<serial_test, tbb::flow::tuple<double, double, int, long, int, short> >::do_test();
 #endif
 #if MAX_TUPLE_TEST_SIZE >= 8
-       generate_test<serial_test, tbb::flow::tuple<float, double, double, double, float, int, float, long> >::do_test();
+        generate_test<serial_test, tbb::flow::tuple<float, double, double, double, float, int, float, long> >::do_test();
 #endif
 #if MAX_TUPLE_TEST_SIZE >= 10
-       generate_test<serial_test, tbb::flow::tuple<float, double, int, double, double, float, long, int, float, long> >::do_test();
+        generate_test<serial_test, tbb::flow::tuple<float, double, int, double, double, float, long, int, float, long> >::do_test();
 #endif
-       generate_test<parallel_test, tbb::flow::tuple<float, double> >::do_test();
+        generate_test<parallel_test, tbb::flow::tuple<float, double> >::do_test();
 #if MAX_TUPLE_TEST_SIZE >= 3
-       generate_test<parallel_test, tbb::flow::tuple<float, int, long> >::do_test();
+        generate_test<parallel_test, tbb::flow::tuple<float, int, long> >::do_test();
 #endif
 #if MAX_TUPLE_TEST_SIZE >= 5
-       generate_test<parallel_test, tbb::flow::tuple<double, double, int, int, short> >::do_test();
+        generate_test<parallel_test, tbb::flow::tuple<double, double, int, int, short> >::do_test();
 #endif
 #if MAX_TUPLE_TEST_SIZE >= 7
-       generate_test<parallel_test, tbb::flow::tuple<float, int, double, float, long, float, long> >::do_test();
+        generate_test<parallel_test, tbb::flow::tuple<float, int, double, float, long, float, long> >::do_test();
 #endif
 #if MAX_TUPLE_TEST_SIZE >= 9
-       generate_test<parallel_test, tbb::flow::tuple<float, double, int, double, double, long, int, float, long> >::do_test();
+        generate_test<parallel_test, tbb::flow::tuple<float, double, int, double, double, long, int, float, long> >::do_test();
+#endif
+    }
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    test_follow_and_precedes_api();
+#endif
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+    test_deduction_guides();
 #endif
-   }
-   return Harness::Done;
+    return Harness::Done;
 }
index e035312..68cb181 100644 (file)
@@ -433,7 +433,7 @@ private:
 void TestSendData_withoutSetArgs() {
     graph g;
 
-    typedef send_data_factory< tbb::flow::interface10::internal::port_ref_impl<0, 1> > device_factory;
+    typedef send_data_factory< tbb::flow::interface11::internal::port_ref_impl<0, 1> > device_factory;
 
     device_factory factory;
     device_selector<device_factory> device_selector;
@@ -470,7 +470,7 @@ void TestSendData_setArgsOnly() {
 void TestSendData_portRefOnly() {
     graph g;
 
-    typedef send_data_factory< tbb::flow::interface10::internal::port_ref_impl<0,1> > device_factory;
+    typedef send_data_factory< tbb::flow::interface11::internal::port_ref_impl<0,1> > device_factory;
 
     device_factory factory;
     device_selector<device_factory> device_selector;
@@ -489,7 +489,7 @@ void TestSendData_portRefOnly() {
 void TestSendData_setArgsAndPortRef1() {
     graph g;
 
-    typedef send_data_factory< factory_msg<int>, tbb::flow::interface10::internal::port_ref_impl<0, 1> > device_factory;
+    typedef send_data_factory< factory_msg<int>, tbb::flow::interface11::internal::port_ref_impl<0, 1> > device_factory;
 
     device_factory factory;
     device_selector<device_factory> device_selector;
@@ -508,8 +508,8 @@ void TestSendData_setArgsAndPortRef1() {
 void TestSendData_setArgsAndPortRef2() {
     graph g;
 
-    typedef send_data_factory< factory_msg<int>, tbb::flow::interface10::internal::port_ref_impl<0,0>,
-                               factory_msg<int>, tbb::flow::interface10::internal::port_ref_impl<1,1> > device_factory;
+    typedef send_data_factory< factory_msg<int>, tbb::flow::interface11::internal::port_ref_impl<0,0>,
+                               factory_msg<int>, tbb::flow::interface11::internal::port_ref_impl<1,1> > device_factory;
 
     device_factory factory;
     device_selector<device_factory> device_selector;
index d177879..6a94a46 100644 (file)
@@ -48,7 +48,7 @@ typedef tbb::flow::tagged_msg<size_t, int, char, double, odd_array_type, odder_a
 
 // test base of tagged_msg
 void TestWrapper() {
-    using tbb::flow::interface10::internal::Wrapper;
+    using tbb::flow::interface11::internal::Wrapper;
     Wrapper<int> wi(42);
     Wrapper<int> wic(23);
 
index fc8ce38..c0fe785 100644 (file)
@@ -1120,13 +1120,13 @@ void TestSchedulerTaskSelectionWhenEnqueue() {
 
     ASSERT( g_execution_profile[idx].size() == task_num + num_critical_tasks,
             "Incorrect number of tasks executed" );
-    ASSERT( g_execution_profile[idx][0] == outer_critical_task,
-            "Critical task was executed in wrong order." );
+    ASSERT( *(g_execution_profile[idx].end() - 1) == outer_critical_task,
+            "Critical task was executed in wrong order. It should be the last one." );
     bool all_regular = true;
-    for( std::vector<task_marker_t>::const_iterator it = g_execution_profile[idx].begin() + 1;
-         it != g_execution_profile[idx].end(); ++it )
+    for( std::vector<task_marker_t>::const_iterator it = g_execution_profile[idx].begin();
+         it != g_execution_profile[idx].end() - 1; ++it )
         all_regular &= regular_task == *it;
-    ASSERT( all_regular, "Critical task was executed in wrong order." );
+    ASSERT( all_regular, "Critical task was executed in wrong order. It should be the last one." );
 }
 
 enum ways_to_cancel_t {
index 4e10617..a22960b 100644 (file)
@@ -89,14 +89,15 @@ enum SharingMode {
     ParallelWait = 2
 };
 
-class  SharedGroupBodyImpl : NoCopy, Harness::NoAfterlife {
+template<typename task_group_type>
+class SharedGroupBodyImpl : NoCopy, Harness::NoAfterlife {
     static const uint_t c_numTasks0 = 4096,
                         c_numTasks1 = 1024;
 
     const uint_t m_numThreads;
     const uint_t m_sharingMode;
 
-    Concurrency::task_group *m_taskGroup;
+    task_group_type *m_taskGroup;
     atomic_t m_tasksSpawned,
              m_threadsReady;
     Harness::SpinBarrier m_barrier;
@@ -175,7 +176,7 @@ public:
         AssertLive();
         if ( idx == 0 ) {
             ASSERT ( !m_taskGroup && !m_tasksSpawned, "SharedGroupBody must be reset before reuse");
-            m_taskGroup = new Concurrency::task_group;
+            m_taskGroup = new task_group_type;
             Spawn( c_numTasks0 );
             Wait();
             if ( m_sharingMode & VagabondGroup )
@@ -200,15 +201,19 @@ public:
     }
 };
 
-atomic_t SharedGroupBodyImpl::s_tasksExecuted;
+template<typename task_group_type>
+atomic_t SharedGroupBodyImpl<task_group_type>::s_tasksExecuted;
 
+template<typename task_group_type>
 class  SharedGroupBody : NoAssign, Harness::NoAfterlife {
     bool m_bOwner;
-    SharedGroupBodyImpl *m_pImpl;
+    SharedGroupBodyImpl<task_group_type> *m_pImpl;
 public:
     SharedGroupBody ( uint_t numThreads, uint_t sharingMode = 0 )
-        : m_bOwner(true)
-        , m_pImpl( new SharedGroupBodyImpl(numThreads, sharingMode) )
+        : NoAssign()
+        , Harness::NoAfterlife()
+        , m_bOwner(true)
+        , m_pImpl( new SharedGroupBodyImpl<task_group_type>(numThreads, sharingMode) )
     {}
     SharedGroupBody ( const SharedGroupBody& src )
         : NoAssign()
@@ -223,12 +228,13 @@ public:
     void operator() ( uint_t idx ) const { m_pImpl->Run(idx); }
 };
 
+template<typename task_group_type>
 class RunAndWaitSyncronizationTestBody : NoAssign {
     Harness::SpinBarrier& m_barrier;
     tbb::atomic<bool>& m_completed;
-    tbb::task_group& m_tg;
+    task_group_type& m_tg;
 public:
-    RunAndWaitSyncronizationTestBody(Harness::SpinBarrier& barrier, tbb::atomic<bool>& completed, tbb::task_group& tg)
+    RunAndWaitSyncronizationTestBody(Harness::SpinBarrier& barrier, tbb::atomic<bool>& completed, task_group_type& tg)
         : m_barrier(barrier), m_completed(completed), m_tg(tg) {}
 
     void operator()() const {
@@ -248,24 +254,38 @@ public:
     }
 };
 
+
+
+template<typename task_group_type>
 void TestParallelSpawn () {
-    NativeParallelFor( g_MaxConcurrency, SharedGroupBody(g_MaxConcurrency) );
+    NativeParallelFor( g_MaxConcurrency, SharedGroupBody<task_group_type>(g_MaxConcurrency) );
 }
 
+template<typename task_group_type>
 void TestParallelWait () {
-    NativeParallelFor( g_MaxConcurrency, SharedGroupBody(g_MaxConcurrency, ParallelWait) );
+    NativeParallelFor( g_MaxConcurrency, SharedGroupBody<task_group_type>(g_MaxConcurrency, ParallelWait) );
 
     Harness::SpinBarrier barrier(g_MaxConcurrency);
     tbb::atomic<bool> completed;
     completed = false;
-    tbb::task_group tg;
-    RunAndWaitSyncronizationTestBody b(barrier, completed, tg);
+    task_group_type tg;
+    RunAndWaitSyncronizationTestBody<task_group_type> b(barrier, completed, tg);
     NativeParallelFor( g_MaxConcurrency, b );
 }
 
 // Tests non-stack-bound task group (the group that is allocated by one thread and destroyed by the other)
+template<typename task_group_type>
 void TestVagabondGroup () {
-    NativeParallelFor( 2, SharedGroupBody(2, VagabondGroup) );
+    NativeParallelFor( 2, SharedGroupBody<task_group_type>(2, VagabondGroup) );
+}
+
+
+
+template<typename task_group_type>
+void TestThreadSafety() {
+    TestParallelSpawn<task_group_type>();
+    TestParallelWait<task_group_type>();
+    TestVagabondGroup<task_group_type>();
 }
 
 //------------------------------------------------------------------------
@@ -285,175 +305,171 @@ atomic_t g_Sum;
     ASSERT( sum == numRepeats * F, NULL ); \
     REMARK("Realized parallelism in Fib test is %u out of %u\n", Harness::ConcurrencyTracker::PeakParallelism(), g_MaxConcurrency)
 
-//------------------------------------------------------------------------
-// Test for a complex tree of task groups
-//
-// The test executes a tree of task groups of the same sort with asymmetric
-// descendant nodes distribution at each level at each level.
-//
-// The chores are specified as functor objects. Each task group contains only one chore.
-//------------------------------------------------------------------------
-
-template<uint_t Func(uint_t)>
-struct FibTask : NoAssign, Harness::NoAfterlife {
+// Fibonacci tasks specified as functors
+template<class task_group_type>
+class FibTaskBase : NoAssign, Harness::NoAfterlife {
+protected:
     uint_t* m_pRes;
-    const uint_t m_Num;
-    FibTask( uint_t* y, uint_t n ) : m_pRes(y), m_Num(n) {}
-    void operator() () const {
-        *m_pRes = Func(m_Num);
+    mutable uint_t m_Num;
+    virtual void impl() const = 0;
+public:
+    FibTaskBase( uint_t* y, uint_t n ) : m_pRes(y), m_Num(n) {}
+    void operator()() const {
+        Harness::ConcurrencyTracker ct;
+        AssertLive();
+        if( m_Num < 2 ) {
+            *m_pRes = m_Num;
+        } else {
+            impl();
+        }
     }
+    virtual ~FibTaskBase() {}
 };
 
-uint_t Fib_SpawnRightChildOnly ( uint_t n ) {
-    Harness::ConcurrencyTracker ct;
-    if( n<2 ) {
-        return n;
-    } else {
-        uint_t y = ~0u;
-        Concurrency::task_group tg;
-        tg.run( FibTask<Fib_SpawnRightChildOnly>(&y, n-1) );
-        uint_t x = Fib_SpawnRightChildOnly(n-2);
+template<class task_group_type>
+class FibTaskAsymmetricTreeWithTaskHandle : public FibTaskBase<task_group_type> {
+public:
+    FibTaskAsymmetricTreeWithTaskHandle( uint_t* y, uint_t n ) : FibTaskBase<task_group_type>(y, n) {}
+    virtual void impl() const __TBB_override {
+        uint_t x = ~0u;
+        task_group_type tg;
+        Concurrency::task_handle<FibTaskAsymmetricTreeWithTaskHandle>
+            h = FibTaskAsymmetricTreeWithTaskHandle(&x, this->m_Num-1);
+        tg.run( h );
+        this->m_Num -= 2; (*this)();
         tg.wait();
-        return y+x;
+        *(this->m_pRes) += x;
     }
-}
-
-void TestFib1 () {
-    FIB_TEST_PROLOGUE();
-    uint_t sum = 0;
-    for( unsigned i = 0; i < numRepeats; ++i )
-        sum += Fib_SpawnRightChildOnly(N);
-    FIB_TEST_EPILOGUE(sum);
-}
+};
 
+template<class task_group_type>
+class FibTaskSymmetricTreeWithTaskHandle : public FibTaskBase<task_group_type> {
+public:
+    FibTaskSymmetricTreeWithTaskHandle( uint_t* y, uint_t n ) : FibTaskBase<task_group_type>(y, n) {}
+    virtual void impl() const __TBB_override {
+        uint_t x = ~0u,
+               y = ~0u;
+        task_group_type tg;
+        Concurrency::task_handle<FibTaskSymmetricTreeWithTaskHandle>
+            h1 = FibTaskSymmetricTreeWithTaskHandle(&x, this->m_Num-1),
+            h2 = FibTaskSymmetricTreeWithTaskHandle(&y, this->m_Num-2);
+        tg.run( h1 );
+        tg.run( h2 );
+        tg.wait();
+        *(this->m_pRes) = x + y;
+    }
+};
 
-//------------------------------------------------------------------------
-// Test for a mixed tree of task groups.
-//
-// The test executes a tree with multiple task of one sort at the first level,
-// each of which originates in its turn a binary tree of descendant task groups.
-//
-// The chores are specified both as functor objects and as function pointers
-//------------------------------------------------------------------------
+template<class task_group_type>
+class FibTaskAsymmetricTreeWithFunctor : public FibTaskBase<task_group_type> {
+public:
+    FibTaskAsymmetricTreeWithFunctor( uint_t* y, uint_t n ) : FibTaskBase<task_group_type>(y, n) {}
+    virtual void impl() const __TBB_override {
+        uint_t x = ~0u;
+        task_group_type tg;
+        tg.run( FibTaskAsymmetricTreeWithFunctor(&x, this->m_Num-1) );
+        this->m_Num -= 2; tg.run_and_wait( *this );
+        *(this->m_pRes) += x;
+    }
+};
 
-uint_t Fib_SpawnBothChildren( uint_t n ) {
-    Harness::ConcurrencyTracker ct;
-    if( n<2 ) {
-        return n;
-    } else {
-        uint_t  y = ~0u,
-                x = ~0u;
-        Concurrency::task_group tg;
-        tg.run( FibTask<Fib_SpawnBothChildren>(&x, n-2) );
-        tg.run( FibTask<Fib_SpawnBothChildren>(&y, n-1) );
+template<class task_group_type>
+class FibTaskSymmetricTreeWithFunctor : public FibTaskBase<task_group_type> {
+public:
+    FibTaskSymmetricTreeWithFunctor( uint_t* y, uint_t n ) : FibTaskBase<task_group_type>(y, n) {}
+    virtual void impl() const __TBB_override {
+        uint_t x = ~0u,
+               y = ~0u;
+        task_group_type tg;
+        tg.run( FibTaskSymmetricTreeWithFunctor(&x, this->m_Num-1) );
+        tg.run( FibTaskSymmetricTreeWithFunctor(&y, this->m_Num-2) );
         tg.wait();
-        return y + x;
+        *(this->m_pRes) = x + y;
     }
-}
+};
+
+
 
-void RunFib2 () {
-    g_Sum += Fib_SpawnBothChildren(N);
+// Helper functions
+template<class fib_task>
+uint_t RunFibTask(uint_t n) {
+    uint_t res = ~0u;
+    fib_task(&res, n)();
+    return res;
 }
 
-void TestFib2 () {
+template<typename fib_task>
+void RunFibTest() {
     FIB_TEST_PROLOGUE();
-    g_Sum = 0;
-    Concurrency::task_group rg;
-    for( unsigned i = 0; i < numRepeats - 1; ++i )
-        rg.run( &RunFib2 );
-    rg.wait();
-    rg.run( &RunFib2 );
-    rg.wait();
-    FIB_TEST_EPILOGUE(g_Sum);
+    uint_t sum = 0;
+    for( unsigned i = 0; i < numRepeats; ++i )
+        sum += RunFibTask<fib_task>(N);
+    FIB_TEST_EPILOGUE(sum);
 }
 
+template<typename fib_task>
+void FibFunctionNoArgs() {
+    g_Sum += RunFibTask<fib_task>(N);
+}
 
-//------------------------------------------------------------------------
-// Test for a complex tree of task groups
-// The chores are specified as task handles for recursive functor objects.
-//------------------------------------------------------------------------
 
-class FibTask_SpawnRightChildOnly : NoAssign, Harness::NoAfterlife {
-    uint_t* m_pRes;
-    mutable uint_t m_Num;
 
-public:
-    FibTask_SpawnRightChildOnly( uint_t* y, uint_t n ) : m_pRes(y), m_Num(n) {}
-    void operator() () const {
-        Harness::ConcurrencyTracker ct;
-        AssertLive();
-        if( m_Num < 2 ) {
-            *m_pRes = m_Num;
-        } else {
-            uint_t y = ~0u;
-            Concurrency::task_group tg;
-            Concurrency::task_handle<FibTask_SpawnRightChildOnly> h = FibTask_SpawnRightChildOnly(&y, m_Num-1);
-            tg.run( h );
-            m_Num -= 2;
-            tg.run_and_wait( *this );
-            *m_pRes += y;
-        }
-    }
-};
+template<typename task_group_type>
+void TestFibWithTaskHandle() {
+    RunFibTest<FibTaskAsymmetricTreeWithTaskHandle<task_group_type> >();
+    RunFibTest< FibTaskSymmetricTreeWithTaskHandle<task_group_type> >();
+}
 
-uint_t RunFib3 ( uint_t n ) {
-    uint_t res = ~0u;
-    FibTask_SpawnRightChildOnly func(&res, n);
-    func();
-    return res;
+#if __TBB_CPP11_LAMBDAS_PRESENT
+template<typename task_group_type>
+void TestFibWithMakeTask() {
+    REMARK ("make_task test\n");
+    atomic_t sum;
+    sum = 0;
+    task_group_type tg;
+    auto h1 = Concurrency::make_task( [&](){sum += RunFibTask<FibTaskSymmetricTreeWithTaskHandle<task_group_type> >(N);} );
+    auto h2 = Concurrency::make_task( [&](){sum += RunFibTask<FibTaskSymmetricTreeWithTaskHandle<task_group_type> >(N);} );
+    tg.run( h1 );
+    tg.run_and_wait( h2 );
+    ASSERT( sum == 2 * F, NULL );
 }
 
-void TestTaskHandle () {
+template<typename task_group_type>
+void TestFibWithLambdas() {
+    REMARK ("Lambdas test");
     FIB_TEST_PROLOGUE();
-    uint_t sum = 0;
+    atomic_t sum;
+    sum = 0;
+    task_group_type tg;
     for( unsigned i = 0; i < numRepeats; ++i )
-        sum += RunFib3(N);
+        tg.run( [&](){sum += RunFibTask<FibTaskSymmetricTreeWithFunctor<task_group_type> >(N);} );
+    tg.wait();
     FIB_TEST_EPILOGUE(sum);
 }
+#endif //__TBB_CPP11_LAMBDAS_PRESENT
 
-//------------------------------------------------------------------------
-// Test for a mixed tree of task groups.
-// The chores are specified as task handles for both functor objects and function pointers
-//------------------------------------------------------------------------
-
-template<class task_group_type>
-class FibTask_SpawnBothChildren : NoAssign, Harness::NoAfterlife {
-    uint_t* m_pRes;
-    uint_t m_Num;
-public:
-    FibTask_SpawnBothChildren( uint_t* y, uint_t n ) : m_pRes(y), m_Num(n) {}
-    void operator() () const {
-        Harness::ConcurrencyTracker ct;
-        AssertLive();
-        if( m_Num < 2 ) {
-            *m_pRes = m_Num;
-        } else {
-            uint_t  x = ~0u, // initialized only to suppress warning
-                    y = ~0u;
-            task_group_type tg;
-            Concurrency::task_handle<FibTask_SpawnBothChildren> h1 = FibTask_SpawnBothChildren(&y, m_Num-1),
-                                                                h2 = FibTask_SpawnBothChildren(&x, m_Num-2);
-            tg.run( h1 );
-            tg.run( h2 );
-            tg.wait();
-            *m_pRes = x + y;
-        }
-    }
-};
+template<typename task_group_type>
+void TestFibWithFunctor() {
+    RunFibTest<FibTaskAsymmetricTreeWithFunctor<task_group_type> >();
+    RunFibTest< FibTaskSymmetricTreeWithFunctor<task_group_type> >();
+}
 
-template<class task_group_type>
-void RunFib4 () {
-    uint_t res = ~0u;
-    FibTask_SpawnBothChildren<task_group_type> func(&res, N);
-    func();
-    g_Sum += res;
+template<typename task_group_type>
+void TestFibWithFunctionPtr() {
+    FIB_TEST_PROLOGUE();
+    g_Sum = 0;
+    task_group_type tg;
+    for( unsigned i = 0; i < numRepeats; ++i )
+        tg.run( &FibFunctionNoArgs<FibTaskSymmetricTreeWithFunctor<task_group_type> > );
+    tg.wait();
+    FIB_TEST_EPILOGUE(g_Sum);
 }
 
-template<class task_group_type>
-void TestTaskHandle2 () {
+template<typename task_group_type>
+void TestFibInvalidMultipleScheduling() {
     FIB_TEST_PROLOGUE();
     g_Sum = 0;
-    task_group_type rg;
+    task_group_type tg;
     typedef tbb::aligned_space<handle_type> handle_space_t;
     handle_space_t *handles = new handle_space_t[numRepeats];
     handle_type *h = NULL;
@@ -464,18 +480,18 @@ void TestTaskHandle2 () {
     for( ;; ++i ) {
         h = handles[i].begin();
 #if __TBB_FUNC_PTR_AS_TEMPL_PARAM_BROKEN
-        new ( h ) handle_type((void(*)())RunFib4<task_group_type>);
+        new ( h ) handle_type((void(*)())FibFunctionNoArgs<FibTaskSymmetricTreeWithTaskHandle<task_group_type> >);
 #else
-        new ( h ) handle_type(RunFib4<task_group_type>);
+        new ( h ) handle_type(FibFunctionNoArgs<FibTaskSymmetricTreeWithTaskHandle<task_group_type> >);
 #endif
         if ( i == numRepeats - 1 )
             break;
-        rg.run( *h );
+        tg.run( *h );
 #if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN
         bool caught = false;
         try {
-            if( i&1 ) rg.run( *h );
-            else rg.run_and_wait( *h );
+            if( i&1 ) tg.run( *h );
+            else tg.run_and_wait( *h );
         }
         catch ( Concurrency::invalid_multiple_scheduling& e ) {
             ASSERT( e.what(), "Error message is absent" );
@@ -488,7 +504,7 @@ void TestTaskHandle2 () {
 #endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */
     }
     ASSERT( i == numRepeats - 1, "unexpected exit from the loop" );
-    rg.run_and_wait( *h );
+    tg.run_and_wait( *h );
 
     for( i = 0; i < numRepeats; ++i )
 #if __TBB_UNQUALIFIED_CALL_OF_DTOR_BROKEN
@@ -500,46 +516,30 @@ void TestTaskHandle2 () {
     FIB_TEST_EPILOGUE(g_Sum);
 }
 
-#if __TBB_CPP11_LAMBDAS_PRESENT
-//------------------------------------------------------------------------
-// Test for a mixed tree of task groups.
-// The chores are specified as lambdas
-//------------------------------------------------------------------------
 
-void TestFibWithLambdas () {
-    REMARK ("Lambdas test");
-    FIB_TEST_PROLOGUE();
-    atomic_t sum;
-    sum = 0;
-    Concurrency::task_group rg;
-    for( unsigned i = 0; i < numRepeats; ++i )
-        rg.run( [&](){sum += Fib_SpawnBothChildren(N);} );
-    rg.wait();
-    FIB_TEST_EPILOGUE(sum);
-}
 
-//------------------------------------------------------------------------
-// Test for make_task.
-// The chores are specified as lambdas converted to task_handles.
-//------------------------------------------------------------------------
+template<typename task_group_type>
+void RunFibonacciTests() {
+    TestFibWithTaskHandle<task_group_type>();
+#if __TBB_CPP11_LAMBDAS_PRESENT
+    TestFibWithMakeTask<task_group_type>();
+    TestFibWithLambdas<task_group_type>();
+#endif
+    TestFibWithFunctor<task_group_type>();
+    TestFibWithFunctionPtr<task_group_type>();
+    TestFibInvalidMultipleScheduling<task_group_type>();
+}
 
-void TestFibWithMakeTask () {
-    REMARK ("Make_task test\n");
-    atomic_t sum;
-    sum = 0;
-    Concurrency::task_group rg;
-    const auto &h1 = Concurrency::make_task( [&](){sum += Fib_SpawnBothChildren(N);} );
-    const auto &h2 = Concurrency::make_task( [&](){sum += Fib_SpawnBothChildren(N);} );
-    rg.run( h1 );
-    rg.run_and_wait( h2 );
-    ASSERT( sum == 2 * F, NULL );
+// tbb::structured_task_group accepts tasks only as task_handle object
+template<> void RunFibonacciTests<Concurrency::structured_task_group>() {
+    TestFibWithTaskHandle<Concurrency::structured_task_group>();
+#if __TBB_CPP11_LAMBDAS_PRESENT
+    TestFibWithMakeTask<Concurrency::structured_task_group>();
+#endif
+    TestFibInvalidMultipleScheduling<Concurrency::structured_task_group>();
 }
-#endif /* __TBB_CPP11_LAMBDAS_PRESENT */
 
 
-//------------------------------------------------------------------------
-// Tests for exception handling and cancellation behavior.
-//------------------------------------------------------------------------
 
 class test_exception : public std::exception
 {
@@ -587,18 +587,6 @@ bool g_Throw;
     #define CATCH_ANY()  __TBB_CATCH( ... ) { ASSERT( __TBB_EXCEPTION_TYPE_INFO_BROKEN, "Unknown exception" ); }
 #endif
 
-inline
-void ResetGlobals ( bool bThrow, bool bRethrow ) {
-    g_Throw = bThrow;
-    g_Rethrow = bRethrow;
-#if __TBB_SILENT_CANCELLATION_BROKEN
-    g_CancellationPropagationInProgress = false;
-#endif
-    g_ExceptionCount = 0;
-    g_TaskCount = 0;
-    Harness::ConcurrencyTracker::Reset();
-}
-
 class ThrowingTask : NoAssign, Harness::NoAfterlife {
     atomic_t &m_TaskCount;
 public:
@@ -619,10 +607,22 @@ public:
     }
 };
 
-void LaunchChildren () {
+inline void ResetGlobals ( bool bThrow, bool bRethrow ) {
+    g_Throw = bThrow;
+    g_Rethrow = bRethrow;
+#if __TBB_SILENT_CANCELLATION_BROKEN
+    g_CancellationPropagationInProgress = false;
+#endif
+    g_ExceptionCount = 0;
+    g_TaskCount = 0;
+    Harness::ConcurrencyTracker::Reset();
+}
+
+template<typename task_group_type>
+void LaunchChildrenWithFunctor () {
     atomic_t count;
     count = 0;
-    Concurrency::task_group g;
+    task_group_type g;
     bool exceptionCaught = false;
     for( unsigned i = 0; i < NUM_CHORES; ++i )
         g.run( ThrowingTask(count) );
@@ -646,78 +646,11 @@ void LaunchChildren () {
     }
 }
 
-#if TBB_USE_EXCEPTIONS
-void TestEh1 () {
-    ResetGlobals( true, false );
-    Concurrency::task_group rg;
-    for( unsigned i = 0; i < NUM_GROUPS; ++i )
-        // TBB version does not require taking function address
-        rg.run( &LaunchChildren );
-    try {
-        rg.wait();
-    } catch ( ... ) {
-        ASSERT( false, "Unexpected exception" );
-    }
-    ASSERT( g_ExceptionCount <= NUM_GROUPS, "Too many exceptions from the child groups. The test is broken" );
-    ASSERT( g_ExceptionCount == NUM_GROUPS, "Not all child groups threw the exception" );
-}
-
-void TestEh2 () {
-    ResetGlobals( true, true );
-    Concurrency::task_group rg;
-    bool exceptionCaught = false;
-    for( unsigned i = 0; i < NUM_GROUPS; ++i )
-        // TBB version does not require taking function address
-        rg.run( &LaunchChildren );
-    try {
-        rg.wait();
-    } catch ( TestException& e ) {
-        ASSERT( e.what(), "Empty what() string" );
-        ASSERT( __TBB_EXCEPTION_TYPE_INFO_BROKEN || strcmp(e.what(), EXCEPTION_DESCR2) == 0, "Unknown exception" );
-        ASSERT ( !rg.is_canceling(), "wait() has not reset cancellation state" );
-        exceptionCaught = true;
-    } CATCH_ANY();
-    ASSERT( exceptionCaught, "No exception thrown from the root task group" );
-    ASSERT( g_ExceptionCount >= SKIP_GROUPS, "Too few exceptions from the child groups. The test is broken" );
-    ASSERT( g_ExceptionCount <= NUM_GROUPS - SKIP_GROUPS, "Too many exceptions from the child groups. The test is broken" );
-    ASSERT( g_ExceptionCount < NUM_GROUPS - SKIP_GROUPS, "None of the child groups was cancelled" );
-}
-#endif /* TBB_USE_EXCEPTIONS */
-
-//------------------------------------------------------------------------
-// Tests for manual cancellation of the task_group hierarchy
-//------------------------------------------------------------------------
-
-void TestCancellation1 () {
-    ResetGlobals( false, false );
-    Concurrency::task_group rg;
-    for( unsigned i = 0; i < NUM_GROUPS; ++i )
-        // TBB version does not require taking function address
-        rg.run( &LaunchChildren );
-    ASSERT ( !Concurrency::is_current_task_group_canceling(), "Unexpected cancellation" );
-    ASSERT ( !rg.is_canceling(), "Unexpected cancellation" );
-#if __TBB_SILENT_CANCELLATION_BROKEN
-    g_CancellationPropagationInProgress = true;
-#endif
-    while ( g_MaxConcurrency > 1 && g_TaskCount == 0 )
-        __TBB_Yield();
-    rg.cancel();
-    g_ExecutedAtCancellation = g_TaskCount;
-    ASSERT ( rg.is_canceling(), "No cancellation reported" );
-    rg.wait();
-    ASSERT( g_TaskCount <= NUM_GROUPS * NUM_CHORES, "Too many tasks reported. The test is broken" );
-    ASSERT( g_TaskCount < NUM_GROUPS * NUM_CHORES, "No tasks were cancelled. Cancellation model changed?" );
-    ASSERT( g_TaskCount <= g_ExecutedAtCancellation + Harness::ConcurrencyTracker::PeakParallelism(), "Too many tasks survived cancellation" );
-}
-
-//------------------------------------------------------------------------
-// Tests for manual cancellation of the structured_task_group hierarchy
-//------------------------------------------------------------------------
-
-void StructuredLaunchChildren () {
+template<typename task_group_type>
+void LaunchChildrenWithTaskHandle () {
     atomic_t count;
     count = 0;
-    Concurrency::structured_task_group g;
+    task_group_type g;
     bool exceptionCaught = false;
     typedef Concurrency::task_handle<ThrowingTask> throwing_handle_type;
     tbb::aligned_space<throwing_handle_type,NUM_CHORES> handles;
@@ -752,19 +685,20 @@ void StructuredLaunchChildren () {
     }
 }
 
-class StructuredCancellationTestDriver {
+template<typename task_group_type>
+class LaunchChildrenWithTaskHandleDriver {
     tbb::aligned_space<handle_type,NUM_CHORES> m_handles;
 
 public:
-    void Launch ( Concurrency::structured_task_group& rg ) {
+    void Launch ( task_group_type& tg ) {
         ResetGlobals( false, false );
         for( unsigned i = 0; i < NUM_GROUPS; ++i ) {
             handle_type *h = m_handles.begin()+i;
-            new ( h ) handle_type( StructuredLaunchChildren );
-            rg.run( *h );
+            new ( h ) handle_type( LaunchChildrenWithTaskHandle<task_group_type> );
+            tg.run( *h );
         }
         ASSERT ( !Concurrency::is_current_task_group_canceling(), "Unexpected cancellation" );
-        ASSERT ( !rg.is_canceling(), "Unexpected cancellation" );
+        ASSERT ( !tg.is_canceling(), "Unexpected cancellation" );
 #if __TBB_SILENT_CANCELLATION_BROKEN
         g_CancellationPropagationInProgress = true;
 #endif
@@ -779,31 +713,96 @@ public:
         ASSERT( g_TaskCount < NUM_GROUPS * NUM_CHORES, "No tasks were cancelled. Cancellation model changed?" );
         ASSERT( g_TaskCount <= g_ExecutedAtCancellation + g_MaxConcurrency, "Too many tasks survived cancellation" );
     }
-}; // StructuredCancellationTestDriver
+}; // LaunchChildrenWithTaskHandleDriver
 
-void TestStructuredCancellation1 () {
-    StructuredCancellationTestDriver driver;
-    Concurrency::structured_task_group sg;
-    driver.Launch( sg );
-    sg.cancel();
+
+
+// Tests for cancellation and exception handling behavior
+template<typename task_group_type>
+void TestManualCancellationWithFunctor () {
+    ResetGlobals( false, false );
+    task_group_type tg;
+    for( unsigned i = 0; i < NUM_GROUPS; ++i )
+        // TBB version does not require taking function address
+        tg.run( &LaunchChildrenWithFunctor<task_group_type> );
+    ASSERT ( !Concurrency::is_current_task_group_canceling(), "Unexpected cancellation" );
+    ASSERT ( !tg.is_canceling(), "Unexpected cancellation" );
+#if __TBB_SILENT_CANCELLATION_BROKEN
+    g_CancellationPropagationInProgress = true;
+#endif
+    while ( g_MaxConcurrency > 1 && g_TaskCount == 0 )
+        __TBB_Yield();
+    tg.cancel();
     g_ExecutedAtCancellation = g_TaskCount;
-    ASSERT ( sg.is_canceling(), "No cancellation reported" );
-    sg.wait();
+    ASSERT ( tg.is_canceling(), "No cancellation reported" );
+    tg.wait();
+    ASSERT( g_TaskCount <= NUM_GROUPS * NUM_CHORES, "Too many tasks reported. The test is broken" );
+    ASSERT( g_TaskCount < NUM_GROUPS * NUM_CHORES, "No tasks were cancelled. Cancellation model changed?" );
+    ASSERT( g_TaskCount <= g_ExecutedAtCancellation + Harness::ConcurrencyTracker::PeakParallelism(), "Too many tasks survived cancellation" );
+}
+
+template<typename task_group_type>
+void TestManualCancellationWithTaskHandle () {
+    LaunchChildrenWithTaskHandleDriver<task_group_type> driver;
+    task_group_type tg;
+    driver.Launch( tg );
+    tg.cancel();
+    g_ExecutedAtCancellation = g_TaskCount;
+    ASSERT ( tg.is_canceling(), "No cancellation reported" );
+    tg.wait();
     driver.Finish();
 }
 
 #if TBB_USE_EXCEPTIONS
+template<typename task_group_type>
+void TestExceptionHandling1 () {
+    ResetGlobals( true, false );
+    task_group_type tg;
+    for( unsigned i = 0; i < NUM_GROUPS; ++i )
+        // TBB version does not require taking function address
+        tg.run( &LaunchChildrenWithFunctor<task_group_type> );
+    try {
+        tg.wait();
+    } catch ( ... ) {
+        ASSERT( false, "Unexpected exception" );
+    }
+    ASSERT( g_ExceptionCount <= NUM_GROUPS, "Too many exceptions from the child groups. The test is broken" );
+    ASSERT( g_ExceptionCount == NUM_GROUPS, "Not all child groups threw the exception" );
+}
+
+template<typename task_group_type>
+void TestExceptionHandling2 () {
+    ResetGlobals( true, true );
+    task_group_type tg;
+    bool exceptionCaught = false;
+    for( unsigned i = 0; i < NUM_GROUPS; ++i )
+        // TBB version does not require taking function address
+        tg.run( &LaunchChildrenWithFunctor<task_group_type> );
+    try {
+        tg.wait();
+    } catch ( TestException& e ) {
+        ASSERT( e.what(), "Empty what() string" );
+        ASSERT( __TBB_EXCEPTION_TYPE_INFO_BROKEN || strcmp(e.what(), EXCEPTION_DESCR2) == 0, "Unknown exception" );
+        ASSERT ( !tg.is_canceling(), "wait() has not reset cancellation state" );
+        exceptionCaught = true;
+    } CATCH_ANY();
+    ASSERT( exceptionCaught, "No exception thrown from the root task group" );
+    ASSERT( g_ExceptionCount >= SKIP_GROUPS, "Too few exceptions from the child groups. The test is broken" );
+    ASSERT( g_ExceptionCount <= NUM_GROUPS - SKIP_GROUPS, "Too many exceptions from the child groups. The test is broken" );
+    ASSERT( g_ExceptionCount < NUM_GROUPS - SKIP_GROUPS, "None of the child groups was cancelled" );
+}
+
 #if defined(_MSC_VER)
     #pragma warning (disable: 4127)
 #endif
 
-template<bool Throw>
-void TestStructuredCancellation2 () {
+template<typename task_group_type, bool Throw>
+void TestMissingWait () {
     bool exception_occurred = false,
          unexpected_exception = false;
-    StructuredCancellationTestDriver driver;
+    LaunchChildrenWithTaskHandleDriver<task_group_type> driver;
     try {
-        Concurrency::structured_task_group tg;
+        task_group_type tg;
         driver.Launch( tg );
         if ( Throw )
             throw int(); // Initiate stack unwinding
@@ -826,6 +825,37 @@ void TestStructuredCancellation2 () {
 }
 #endif /* TBB_USE_EXCEPTIONS */
 
+template<typename task_group_type>
+void RunCancellationAndExceptionHandlingTests() {
+    TestManualCancellationWithFunctor              <Concurrency::task_group>();
+    TestManualCancellationWithTaskHandle<Concurrency::task_group>();
+#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN
+    TestExceptionHandling1<Concurrency::task_group>();
+    TestExceptionHandling2<Concurrency::task_group>();
+
+    TestMissingWait<Concurrency::task_group, true>();
+#if !(__TBB_THROW_FROM_DTOR_BROKEN || __TBB_STD_UNCAUGHT_EXCEPTION_BROKEN)
+    TestMissingWait<Concurrency::task_group, false>();
+#else
+    REPORT("Known issue: TestMissingWait<task_group_type, false>() is skipped.\n");
+#endif
+#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */
+}
+
+template<> void RunCancellationAndExceptionHandlingTests<Concurrency::structured_task_group>() {
+    TestManualCancellationWithTaskHandle<Concurrency::structured_task_group>();
+#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN
+    TestMissingWait<Concurrency::structured_task_group, true>();
+#if !(__TBB_THROW_FROM_DTOR_BROKEN || __TBB_STD_UNCAUGHT_EXCEPTION_BROKEN)
+    TestMissingWait<Concurrency::structured_task_group, false>();
+#else
+    REPORT("Known issue: TestMissingWait<task_group_type, false>() is skipped.\n");
+#endif
+#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */
+}
+
+
+
 void EmptyFunction () {}
 
 void TestStructuredWait () {
@@ -843,12 +873,16 @@ struct TestFunctor {
     void operator()() const { /* library requires this overload only */ }
 };
 
+template<typename task_group_type>
 void TestConstantFunctorRequirement() {
-    tbb::task_group g;
+    task_group_type g;
     TestFunctor tf;
     g.run( tf ); g.wait();
     g.run_and_wait( tf );
 }
+
+
+
 //------------------------------------------------------------------------
 #if __TBB_CPP11_RVALUE_REF_PRESENT
 namespace TestMoveSemanticsNS {
@@ -874,10 +908,11 @@ namespace TestMoveSemanticsNS {
         NoMoveNoCopyFunctor(NoMoveNoCopyFunctor&&);
     };
 
+    template<typename task_group_type>
     void TestFunctorsWithinTaskHandles() {
         // working with task_handle rvalues is not supported in task_group
 
-        tbb::task_group tg;
+        task_group_type tg;
         MovePreferableFunctor mpf;
         typedef tbb::task_handle<MoveOnlyFunctor> th_mv_only_type;
         typedef tbb::task_handle<MovePreferableFunctor> th_mv_pref_type;
@@ -912,8 +947,9 @@ namespace TestMoveSemanticsNS {
         mpf.Reset();
     }
 
+    template<typename task_group_type>
     void TestBareFunctors() {
-        tbb::task_group tg;
+        task_group_type tg;
         MovePreferableFunctor mpf;
         // run_and_wait() doesn't have any copies or moves of arguments inside the impl
         tg.run_and_wait( NoMoveNoCopyFunctor() );
@@ -948,10 +984,11 @@ namespace TestMoveSemanticsNS {
 }
 #endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
 
+template<typename task_group_type>
 void TestMoveSemantics() {
 #if __TBB_CPP11_RVALUE_REF_PRESENT
-    TestMoveSemanticsNS::TestBareFunctors();
-    TestMoveSemanticsNS::TestFunctorsWithinTaskHandles();
+    TestMoveSemanticsNS::TestBareFunctors<task_group_type>();
+    TestMoveSemanticsNS::TestFunctorsWithinTaskHandles<task_group_type>();
     TestMoveSemanticsNS::TestMakeTask();
 #else
     REPORT("Known issue: move support tests are skipped.\n");
@@ -960,6 +997,64 @@ void TestMoveSemantics() {
 //------------------------------------------------------------------------
 
 
+#if TBBTEST_USE_TBB && TBB_PREVIEW_ISOLATED_TASK_GROUP
+namespace TestIsolationNS {
+    class DummyFunctor {
+    public:
+        DummyFunctor() {}
+        void operator()() const {
+            for ( volatile int j = 0; j < 10; ++j ) {}
+        }
+    };
+
+    template<typename task_group_type>
+    class ParForBody {
+        task_group_type& m_tg;
+        tbb::atomic<bool>& m_preserved;
+        tbb::enumerable_thread_specific<int>& m_ets;
+    public:
+        ParForBody(
+            task_group_type& tg,
+            tbb::atomic<bool>& preserved,
+            tbb::enumerable_thread_specific<int>& ets
+        ) : m_tg(tg), m_preserved(preserved), m_ets(ets) {}
+
+        void operator()(int) const {
+            if (++m_ets.local() > 1) m_preserved = false;
+
+            for (int i = 0; i < 1000; ++i)
+                m_tg.run(DummyFunctor());
+            m_tg.wait();
+            m_tg.run_and_wait(DummyFunctor());
+
+            --m_ets.local();
+        }
+    };
+
+    template<typename task_group_type>
+    void CheckIsolation(bool isolation_is_expected) {
+        task_group_type tg;
+        tbb::atomic<bool> isolation_is_preserved;
+        isolation_is_preserved = true;
+        tbb::enumerable_thread_specific<int> ets(0);
+
+        tbb::parallel_for(0, 100, ParForBody<task_group_type>(tg, isolation_is_preserved, ets));
+
+        ASSERT(
+            isolation_is_expected == isolation_is_preserved,
+            "Actual and expected isolation-related behaviours are different"
+        );
+    }
+
+    // Should be called only when > 1 thread is used, because otherwise isolation is guaranteed to take place
+    void TestIsolation() {
+        CheckIsolation<tbb::task_group>(false);
+        CheckIsolation<tbb::isolated_task_group>(true);
+    }
+}
+#endif
+
+
 int TestMain () {
     REMARK ("Testing %s task_group functionality\n", TBBTEST_USE_TBB ? "TBB" : "PPL");
     for( int p=MinThread; p<=MaxThread; ++p ) {
@@ -974,42 +1069,38 @@ int TestMain () {
                                 Concurrency::TargetOversubscriptionFactor, 1);
         Concurrency::Scheduler  *s = Concurrency::Scheduler::Create( sp );
 #endif /* !TBBTEST_USE_TBB */
+        if ( p > 1 )
+            TestThreadSafety<Concurrency::task_group>();
+
+        RunFibonacciTests<Concurrency::task_group>();
+        RunFibonacciTests<Concurrency::structured_task_group>();
+
+        RunCancellationAndExceptionHandlingTests<Concurrency::task_group>();
+        RunCancellationAndExceptionHandlingTests<Concurrency::structured_task_group>();
+
+#if TBBTEST_USE_TBB && TBB_PREVIEW_ISOLATED_TASK_GROUP
         if ( p > 1 ) {
-            TestParallelSpawn();
-            TestParallelWait();
-            TestVagabondGroup();
+            TestThreadSafety<tbb::isolated_task_group>();
+            TestIsolationNS::TestIsolation();
         }
-        TestFib1();
-        TestFib2();
-        TestTaskHandle();
-        TestTaskHandle2<Concurrency::task_group>();
-        TestTaskHandle2<Concurrency::structured_task_group>();
-#if __TBB_CPP11_LAMBDAS_PRESENT
-        TestFibWithLambdas();
-        TestFibWithMakeTask();
-#endif
-        TestCancellation1();
-        TestStructuredCancellation1();
-#if TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN
-        TestEh1();
-        TestEh2();
-        TestStructuredWait();
-        TestStructuredCancellation2<true>();
-#if !(__TBB_THROW_FROM_DTOR_BROKEN || __TBB_STD_UNCAUGHT_EXCEPTION_BROKEN)
-        TestStructuredCancellation2<false>();
+        RunFibonacciTests<tbb::isolated_task_group>();
+        RunCancellationAndExceptionHandlingTests<tbb::isolated_task_group>();
+        TestConstantFunctorRequirement<tbb::isolated_task_group>();
+        TestMoveSemantics<tbb::isolated_task_group>();
 #else
-        REPORT("Known issue: TestStructuredCancellation2<false>() is skipped.\n");
+        REPORT ("Known issue: tests for tbb::isolated_task_group are skipped.\n");
 #endif
-#endif /* TBB_USE_EXCEPTIONS && !__TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN */
+
 #if !TBBTEST_USE_TBB
         s->Release();
 #endif
     }
-    TestConstantFunctorRequirement();
+    TestStructuredWait();
+    TestConstantFunctorRequirement<Concurrency::task_group>();
+    TestMoveSemantics<Concurrency::task_group>();
 #if __TBB_THROW_ACROSS_MODULE_BOUNDARY_BROKEN
     REPORT("Known issue: exception handling tests are skipped.\n");
 #endif
-    TestMoveSemantics();
     return Harness::Done;
 }
 
index 4ed3763..cccf72b 100644 (file)
@@ -29,6 +29,7 @@
 #define TBB_PREVIEW_BLOCKED_RANGE_ND 1
 #define TBB_PREVIEW_WAITING_FOR_WORKERS 1
 #define TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS 1
+#define TBB_PREVIEW_ISOLATED_TASK_GROUP 1
 #endif
 
 #if __TBB_TEST_SECONDARY
@@ -191,6 +192,7 @@ static void TestPreviewNames() {
     TestTypeDefinitionPresence2(blocked_rangeNd<int,4> );
 #endif
     TestTypeDefinitionPresence2(concurrent_lru_cache<int, int> );
+    TestTypeDefinitionPresence( isolated_task_group );
 #if !__TBB_TEST_SECONDARY
     TestExceptionClassExports( std::runtime_error("test"), tbb::internal::eid_blocking_thread_join_impossible );
 #endif
index 3793349..b98ce3d 100644 (file)
@@ -224,8 +224,8 @@ int main(int argc, char *argv[] ) {
 // Fill dictionary with version strings for platforms
 void initialize_strings_vector(std::vector <string_pair>* vector)
 {
-    vector->push_back(string_pair("TBB: VERSION\t\t2019.0", required));       // check TBB_VERSION
-    vector->push_back(string_pair("TBB: INTERFACE VERSION\t11008", required)); // check TBB_INTERFACE_VERSION
+    vector->push_back(string_pair("TBB: VERSION\t\t2019.9", required));       // check TBB_VERSION
+    vector->push_back(string_pair("TBB: INTERFACE VERSION\t11009", required)); // check TBB_INTERFACE_VERSION
     vector->push_back(string_pair("TBB: BUILD_DATE", required));
     vector->push_back(string_pair("TBB: BUILD_HOST", required));
     vector->push_back(string_pair("TBB: BUILD_OS", required));
index e5e9c8d..a219953 100644 (file)
 #define TBB_DEPRECATED_FLOW_NODE_EXTRACTION 1
 #endif
 
+#include "harness.h"
 #include "harness_graph.h"
 
 #include "tbb/flow_graph.h"
 #include "tbb/task_scheduler_init.h"
+#include "test_follows_and_precedes_api.h"
 
 #define N 300
 #define T 4
@@ -153,6 +155,41 @@ void parallel_read_write_tests() {
     }
 }
 
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+#include <array>
+#include <vector>
+void test_follows_and_precedes_api() {
+    using msg_t = tbb::flow::continue_msg;
+
+    std::array<msg_t, 3> messages_for_follows= {msg_t(), msg_t(), msg_t()};
+    std::vector<msg_t> messages_for_precedes = {msg_t()};
+
+    follows_and_precedes_testing::test_follows<msg_t, tbb::flow::write_once_node<msg_t>>(messages_for_follows);
+    follows_and_precedes_testing::test_precedes<msg_t, tbb::flow::write_once_node<msg_t>>(messages_for_precedes);
+}
+#endif // __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+void test_deduction_guides() {
+    using namespace tbb::flow;
+
+    graph g;
+    broadcast_node<int> b1(g);
+    write_once_node<int> wo0(g);
+
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    write_once_node wo1(follows(b1));
+    static_assert(std::is_same_v<decltype(wo1), write_once_node<int>>);
+
+    write_once_node wo2(precedes(b1));
+    static_assert(std::is_same_v<decltype(wo2), write_once_node<int>>);
+#endif
+
+    write_once_node wo3(wo0);
+    static_assert(std::is_same_v<decltype(wo3), write_once_node<int>>);
+}
+#endif
+
 int TestMain() {
     simple_read_write_tests<int>();
     simple_read_write_tests<float>();
@@ -165,6 +202,11 @@ int TestMain() {
 #if TBB_DEPRECATED_FLOW_NODE_EXTRACTION
     test_extract_on_node<tbb::flow::write_once_node, int>();
 #endif
+#if __TBB_PREVIEW_FLOW_GRAPH_NODE_SET
+    test_follows_and_precedes_api();
+#endif
+#if __TBB_CPP17_DEDUCTION_GUIDES_PRESENT
+    test_deduction_guides();
+#endif
     return Harness::Done;
 }
-