OpenVDB  9.0.1
Invoke.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
4 /*!
5  \file Invoke.h
6 
7  \author Ken Museth
8 
9  \date August 24, 2020
10 
11  \brief A unified wrapper for tbb::parallel_invoke and a naive std::thread analog
12 
13  @code
14  template<typename Func0, typename Func1, ..., typename FuncN>
15  int invoke(const Func0& f0, const Func1& f1, ..., const FuncN& fN);
16  @endcode
17 */
18 
19 #ifndef NANOVDB_INVOKE_H_HAS_BEEN_INCLUDED
20 #define NANOVDB_INVOKE_H_HAS_BEEN_INCLUDED
21 
22 #include "../NanoVDB.h"// for nanovdb::CoordBBox
23 
24 #ifdef NANOVDB_USE_TBB
25 #include <tbb/parallel_invoke.h>
26 #endif
27 
28 #include <thread>
29 #include <mutex>
30 #include <vector>
31 
32 namespace nanovdb {
33 
34 namespace {
35 #ifndef NANOVDB_USE_TBB
36 // Base case
37 template<typename Func>
38 void parallel_invoke(std::vector<std::thread> &threadPool, const Func &taskFunc) {
39  threadPool.emplace_back(taskFunc);
40 }
41 
42 // Iterative call
43 template<typename Func, typename... Rest>
44 void parallel_invoke(std::vector<std::thread> &threadPool, const Func &taskFunc1, Rest... taskFuncN) {
45  threadPool.emplace_back(taskFunc1);
46  parallel_invoke(threadPool, taskFuncN...);
47 }
48 
49 // Base case
50 template<typename Func>
51 void serial_invoke(const Func &taskFunc) {taskFunc();}
52 
53 // Iterative call
54 template<typename Func, typename... Rest>
55 void serial_invoke(const Func &taskFunc1, Rest... taskFuncN) {
56  taskFunc1();
57  serial_invoke(taskFuncN...);
58 }
59 #endif
60 }// unnamed namespace
61 
62 /// @return 1 for serial, 2 for tbb multi-threading, and 3 for std multi-threading
63 template<typename Func, typename... Rest>
64 int invoke(const Func &taskFunc1, Rest... taskFuncN) {
65 #ifdef NANOVDB_USE_TBB
66  tbb::parallel_invoke(taskFunc1, taskFuncN...);
67  return 2;
68 #else
69  const auto threadCount = std::thread::hardware_concurrency()>>1;
70  if (1 + sizeof...(Rest) <= threadCount) {
71  std::vector<std::thread> threadPool;
72  threadPool.emplace_back(taskFunc1);
73  parallel_invoke(threadPool, taskFuncN...);
74  for (auto &t : threadPool) t.join();
75  return 3;// std multi-threading
76  } else {
77  taskFunc1();
78  serial_invoke(taskFuncN...);
79  return 1;// serial
80  }
81 #endif
82  return -1;// should never happen
83 }
84 
85 }// namespace nanovdb
86 
87 #endif // NANOVDB_INVOKE_H_HAS_BEEN_INCLUDED
Definition: NanoVDB.h:184
int invoke(const Func &taskFunc1, Rest...taskFuncN)
Definition: Invoke.h:64