24 #ifndef PXR_BASE_WORK_DISPATCHER_H
25 #define PXR_BASE_WORK_DISPATCHER_H
31 #include "pxr/base/work/api.h"
36 #include <tbb/concurrent_vector.h>
40 #include <type_traits>
43 PXR_NAMESPACE_OPEN_SCOPE
81 WorkDispatcher &operator=(WorkDispatcher
const &) =
delete;
95 template <
class Callable,
class A1,
class A2, ...
class AN>
96 void Run(Callable &&c, A1 &&a1, A2 &&a2, ... AN &&aN);
100 template <
class Callable>
101 inline void Run(Callable &&c) {
102 _rootTask->spawn(_MakeInvokerTask(std::forward<Callable>(c)));
105 template <
class Callable,
class A0,
class ... Args>
106 inline void Run(Callable &&c, A0 &&a0, Args&&... args) {
107 Run(std::bind(std::forward<Callable>(c),
108 std::forward<A0>(a0),
109 std::forward<Args>(args)...));
115 WORK_API
void Wait();
130 typedef tbb::concurrent_vector<TfErrorTransport> _ErrorTransports;
136 struct _InvokerTask :
public tbb::task {
137 explicit _InvokerTask(Fn &&fn, _ErrorTransports *err)
138 : _fn(std::move(fn)), _errors(err) {}
140 explicit _InvokerTask(Fn
const &fn, _ErrorTransports *err)
141 : _fn(fn), _errors(err) {}
143 virtual tbb::task* execute() {
147 WorkDispatcher::_TransportErrors(m, _errors);
152 _ErrorTransports *_errors;
157 _InvokerTask<typename std::remove_reference<Fn>::type>&
158 _MakeInvokerTask(Fn &&fn) {
159 return *
new( _rootTask->allocate_additional_child_of(*_rootTask) )
160 _InvokerTask<
typename std::remove_reference<Fn>::type>(
161 std::forward<Fn>(fn), &_errors);
167 _TransportErrors(
const TfErrorMark &m, _ErrorTransports *errors);
171 tbb::task_group_context _context;
172 tbb::empty_task* _rootTask;
176 _ErrorTransports _errors;
181 PXR_NAMESPACE_CLOSE_SCOPE
183 #endif // PXR_BASE_WORK_DISPATCHER_H
WORK_API void Cancel()
Cancel remaining work and return immediately.
A work dispatcher runs concurrent tasks.
Class used to record the end of the error-list.
bool IsClean() const
Return true if no new errors were posted in this thread since the last call to SetMark(), false otherwise.
WORK_API WorkDispatcher()
Construct a new dispatcher.
WORK_API ~WorkDispatcher()
Wait() for any pending tasks to complete, then destroy the dispatcher.
WORK_API void Wait()
Block until the work started by Run() completes.
void Run(Callable &&c, A1 &&a1, A2 &&a2,...AN &&aN)
Add work for the dispatcher to run.