HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
dispatcher_impl.h
Go to the documentation of this file.
1 //
2 // Copyright 2025 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_BASE_WORK_TBB_DISPATCHER_IMPL_H
8 #define PXR_BASE_WORK_TBB_DISPATCHER_IMPL_H
9 
10 #include "pxr/pxr.h"
11 #include "pxr/base/work/api.h"
12 
13 // Blocked range is not used in this file, but this header happens to pull in
14 // the TBB version header in a way that works in all TBB versions.
15 #include <tbb/blocked_range.h>
16 #include <tbb/concurrent_vector.h>
17 #if TBB_INTERFACE_VERSION_MAJOR >= 12
18 #include <tbb/task_group.h>
19 #else
20 #include <tbb/task.h>
21 #endif
22 
23 #include <functional>
24 #include <type_traits>
25 #include <utility>
26 
28 
30 {
31 public:
32  /// Construct a new dispatcher.
34 
35  /// Wait() for any pending tasks to complete, then destroy the dispatcher.
36  WORK_API ~WorkImpl_Dispatcher() noexcept;
37 
38  WorkImpl_Dispatcher(WorkImpl_Dispatcher const &) = delete;
39  WorkImpl_Dispatcher &operator=(WorkImpl_Dispatcher const &) = delete;
40 
41  template <class Callable>
42  inline void Run(Callable &&c) {
43 #if TBB_INTERFACE_VERSION_MAJOR >= 12
44  _taskGroup.run(std::forward<Callable>(c));
45 #else
46  _rootTask->spawn(
47  *new(_rootTask->allocate_additional_child_of(*_rootTask))
49  std::forward<Callable>(c)));
50 #endif
51  }
52 
53  /// Reinitialize context for WorkImpl_Dispatcher if it has one.
54  WORK_API void Reset();
55 
56  /// Block until the work started by Run() completes.
57  WORK_API void Wait();
58 
59  /// Cancel remaining work and return immediately.
60  ///
61  /// Calling this function affects task that are being run directly
62  /// by this dispatcher. If any of these tasks are using their own
63  /// dispatchers to run tasks, these dispatchers will not be affected
64  /// and these tasks will run to completion, unless they are also
65  /// explicitly cancelled.
66  ///
67  /// This call does not block. Call Wait() after Cancel() to wait for
68  /// pending tasks to complete.
69  WORK_API void Cancel();
70 
71 #if TBB_INTERFACE_VERSION_MAJOR < 12
72  template <class Fn>
73  struct _InvokerTaskWrapper : public tbb::task {
74  explicit _InvokerTaskWrapper(Fn &&fn)
75  : _fn(std::move(fn)) {}
76 
77  explicit _InvokerTaskWrapper(Fn const &fn)
78  : _fn(fn) {}
79 
80  virtual tbb::task* execute() {
81  // In anticipation of OneTBB, ensure that _fn meets OneTBB's
82  // requirement that a task's call operator must be const.
83  const_cast<_InvokerTaskWrapper const *>(this)->_fn();
84  return NULL;
85  }
86  private:
87  Fn _fn;
88  };
89 #endif
90  // Task group context to run tasks in.
91  tbb::task_group_context _context;
92 #if TBB_INTERFACE_VERSION_MAJOR >= 12
93  // Custom task group that lets us implement thread safe concurrent wait.
94  class _TaskGroup : public tbb::task_group {
95  public:
96  _TaskGroup(tbb::task_group_context& ctx) : tbb::task_group(ctx) {}
97  inline tbb::detail::d1::wait_context& _GetInternalWaitContext();
98  };
99 
100  _TaskGroup _taskGroup;
101 #else
102  // Root task that allows us to cancel tasks invoked directly by this
103  // dispatcher.
104  tbb::empty_task* _rootTask;
105 #endif
106 
107 };
108 
110 
111 ///////////////////////////////////////////////////////////////////////////////
112 
113 #endif // PXR_BASE_WORK_TBB_DISPATCHER_IMPL_H
WORK_API ~WorkImpl_Dispatcher() noexcept
Wait() for any pending tasks to complete, then destroy the dispatcher.
type
Definition: core.h:556
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
#define WORK_API
Definition: api.h:23
void Run(Callable &&c)
tbb::task_group_context _context
WorkImpl_Dispatcher & operator=(WorkImpl_Dispatcher const &)=delete
WORK_API WorkImpl_Dispatcher()
Construct a new dispatcher.
WORK_API void Cancel()
WORK_API void Wait()
Block until the work started by Run() completes.
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
WORK_API void Reset()
Reinitialize context for WorkImpl_Dispatcher if it has one.
tbb::empty_task * _rootTask