All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
dispatcher.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef WORK_DISPATCHER_H
25 #define WORK_DISPATCHER_H
26 
28 
29 #include "pxr/pxr.h"
30 #include "pxr/base/work/threadLimits.h"
31 #include "pxr/base/work/api.h"
32 
33 #include "pxr/base/tf/errorMark.h"
34 #include "pxr/base/tf/errorTransport.h"
35 
36 #include <tbb/concurrent_vector.h>
37 #include <tbb/task.h>
38 
39 #include <functional>
40 #include <type_traits>
41 #include <utility>
42 
43 PXR_NAMESPACE_OPEN_SCOPE
44 
72 {
73 public:
75  WORK_API WorkDispatcher();
76 
78  WORK_API ~WorkDispatcher();
79 
80  WorkDispatcher(WorkDispatcher const &) = delete;
81  WorkDispatcher &operator=(WorkDispatcher const &) = delete;
82 
83 #ifdef doxygen
84 
95  template <class Callable, class A1, class A2, ... class AN>
96  void Run(Callable &&c, A1 &&a1, A2 &&a2, ... AN &&aN);
97 
98 #else // doxygen
99 
100  template <class Callable>
101  inline void Run(Callable &&c) {
102  _rootTask->spawn(_MakeInvokerTask(std::forward<Callable>(c)));
103  }
104 
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)...));
110  }
111 
112 #endif // doxygen
113 
115  WORK_API void Wait();
116 
127  WORK_API void Cancel();
128 
129 private:
130  typedef tbb::concurrent_vector<TfErrorTransport> _ErrorTransports;
131 
132  // Function invoker helper that wraps the invocation with an ErrorMark so we
133  // can transmit errors that occur back to the thread that Wait() s for tasks
134  // to complete.
135  template <class Fn>
136  struct _InvokerTask : public tbb::task {
137  explicit _InvokerTask(Fn &&fn, _ErrorTransports *err)
138  : _fn(std::move(fn)), _errors(err) {}
139 
140  explicit _InvokerTask(Fn const &fn, _ErrorTransports *err)
141  : _fn(fn), _errors(err) {}
142 
143  virtual tbb::task* execute() {
144  TfErrorMark m;
145  _fn();
146  if (!m.IsClean())
147  WorkDispatcher::_TransportErrors(m, _errors);
148  return NULL;
149  }
150  private:
151  Fn _fn;
152  _ErrorTransports *_errors;
153  };
154 
155  // Make an _InvokerTask instance, letting the function template deduce Fn.
156  template <class Fn>
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);
162  }
163 
164  // Helper function that removes errors from \p m and stores them in a new
165  // entry in \p errors.
166  WORK_API static void
167  _TransportErrors(const TfErrorMark &m, _ErrorTransports *errors);
168 
169  // Task group context and associated root task that allows us to cancel
170  // tasks invoked directly by this dispatcher.
171  tbb::task_group_context _context;
172  tbb::empty_task* _rootTask;
173 
174  // The error transports we use to transmit errors in other threads back to
175  // this thread.
176  _ErrorTransports _errors;
177 };
178 
180 
181 PXR_NAMESPACE_CLOSE_SCOPE
182 
183 #endif // WORK_DISPATCHER_H
WORK_API void Cancel()
Cancel remaining work and return immediately.
A work dispatcher runs concurrent tasks.
Definition: dispatcher.h:71
Class used to record the end of the error-list.
Definition: errorMark.h:66
bool IsClean() const
Return true if no new errors were posted in this thread since the last call to SetMark(), false otherwise.
Definition: errorMark.h:99
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.