OpenVDB  12.0.0
Invoke.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: Apache-2.0
3 
4 /*!
5  \file nanovdb/util/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_UTIL_INVOKE_H_HAS_BEEN_INCLUDED
20 #define NANOVDB_UTIL_INVOKE_H_HAS_BEEN_INCLUDED
21 
22 #include <nanovdb/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 util {
35 
36 namespace {
37 #ifndef NANOVDB_USE_TBB
38 // Base case
39 template<typename Func>
40 void parallel_invoke(std::vector<std::thread> &threadPool, const Func &taskFunc) {
41  threadPool.emplace_back(taskFunc);
42 }
43 
44 // Iterative call
45 template<typename Func, typename... Rest>
46 void parallel_invoke(std::vector<std::thread> &threadPool, const Func &taskFunc1, Rest... taskFuncN) {
47  threadPool.emplace_back(taskFunc1);
48  parallel_invoke(threadPool, taskFuncN...);
49 }
50 
51 // Base case
52 template<typename Func>
53 void serial_invoke(const Func &taskFunc) {taskFunc();}
54 
55 // Iterative call
56 template<typename Func, typename... Rest>
57 void serial_invoke(const Func &taskFunc1, Rest... taskFuncN) {
58  taskFunc1();
59  serial_invoke(taskFuncN...);
60 }
61 #endif
62 }// unnamed namespace
63 
64 /// @return 1 for serial, 2 for tbb multi-threading, and 3 for std multi-threading
65 template<typename Func, typename... Rest>
66 int invoke(const Func &taskFunc1, Rest... taskFuncN) {
67 #ifdef NANOVDB_USE_TBB
68  tbb::parallel_invoke(taskFunc1, taskFuncN...);
69  return 2;
70 #else
71  const auto threadCount = std::thread::hardware_concurrency()>>1;
72  if (1 + sizeof...(Rest) <= threadCount) {
73  std::vector<std::thread> threadPool;
74  threadPool.emplace_back(taskFunc1);
75  parallel_invoke(threadPool, taskFuncN...);
76  for (auto &t : threadPool) t.join();
77  return 3;// std multi-threading
78  } else {
79  taskFunc1();
80  serial_invoke(taskFuncN...);
81  return 1;// serial
82  }
83 #endif
84  return -1;// should never happen
85 }
86 
87 }// namespace util
88 
89 template<typename Func, typename... Rest>
90 [[deprecated("Use nanovdb::util::invoke instead")]]
91 int invoke(const Func &taskFunc1, Rest... taskFuncN) {
92  return util::invoke<Func, Rest...>(taskFunc1, taskFuncN...);
93 }
94 
95 }// namespace nanovdb
96 
97 #endif // NANOVDB_UTIL_INVOKE_H_HAS_BEEN_INCLUDED
Implements a light-weight self-contained VDB data-structure in a single file! In other words...
Definition: GridHandle.h:27
int invoke(const Func &taskFunc1, Rest...taskFuncN)
Definition: Invoke.h:66