Loading...
Searching...
No Matches
dispatcher.h
Go to the documentation of this file.
1//
2// Copyright 2016 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_DISPATCHER_H
8#define PXR_BASE_WORK_DISPATCHER_H
9
11
12#include "pxr/pxr.h"
13#include "pxr/base/work/api.h"
14#include "pxr/base/work/impl.h"
16
20
21#include <functional>
22#include <type_traits>
23#include <utility>
24
25PXR_NAMESPACE_OPEN_SCOPE
26
27// The Work_Dispatcher interface, specialized with a dispatcher impl template
28// argument.
29//
30// Clients expected to use the WorkDispatcher type instead.
31template <class Impl>
32class Work_Dispatcher
33{
34protected:
35 // Prevent construction of the work dispatcher base class.
36 WORK_API Work_Dispatcher();
37
38public:
40 WORK_API ~Work_Dispatcher() noexcept;
41
42 Work_Dispatcher(Work_Dispatcher const &) = delete;
43 Work_Dispatcher &operator=(Work_Dispatcher const &) = delete;
44
45#ifdef doxygen
46
57 template <class Callable, class A1, class A2, ... class AN>
58 void Run(Callable &&c, A1 &&a1, A2 &&a2, ... AN &&aN);
59
60#else // doxygen
61
62 template <class Callable>
63 inline void Run(Callable &&c) {
65 _dispatcher.Run(
66 _MallocTagsInvokerTask<
67 typename std::remove_reference<Callable>::type>(
68 std::forward<Callable>(c), &_errors));
69 }
70 else {
71 _dispatcher.Run(
72 _InvokerTask<typename std::remove_reference<Callable>::type>(
73 std::forward<Callable>(c), &_errors));
74 }
75 }
76
77 template <class Callable, class A0, class ... Args>
78 inline void Run(Callable &&c, A0 &&a0, Args&&... args) {
79 Run(std::bind(std::forward<Callable>(c),
80 std::forward<A0>(a0),
81 std::forward<Args>(args)...));
82 }
83
84#endif // doxygen
85
87 WORK_API void Wait();
88
99 WORK_API void Cancel();
100
103 WORK_API bool IsCancelled() const;
104
105private:
106 typedef tbb::concurrent_vector<TfErrorTransport> _ErrorTransports;
107
108 // Function invoker helper that wraps the invocation with an ErrorMark so we
109 // can transmit errors that occur back to the thread that Wait() s for tasks
110 // to complete.
111 template <class Fn>
112 struct _InvokerTask {
113 explicit _InvokerTask(Fn &&fn, _ErrorTransports *err)
114 : _fn(std::move(fn))
115 , _errors(err) {}
116
117 explicit _InvokerTask(Fn const &fn, _ErrorTransports *err)
118 : _fn(fn)
119 , _errors(err) {}
120
121 // Ensure only moves happen, no copies.
122 _InvokerTask(_InvokerTask &&other) = default;
123 _InvokerTask(const _InvokerTask &other) = delete;
124 _InvokerTask &operator=(const _InvokerTask &other) = delete;
125
126 void operator()() const {
127 TfErrorMark m;
128 _fn();
129 if (!m.IsClean())
130 Work_Dispatcher::_TransportErrors(m, _errors);
131 }
132 private:
133 Fn _fn;
134 _ErrorTransports *_errors;
135 };
136
137 // Function invoker helper that wraps the invocation with an ErrorMark so we
138 // can transmit errors that occur back to the thread that Wait() s for tasks
139 // to complete. This version also duplicates the caller's malloc tag stack
140 // to the callee's thread.
141 template <class Fn>
142 struct _MallocTagsInvokerTask {
143 explicit _MallocTagsInvokerTask(Fn &&fn, _ErrorTransports *err)
144 : _fn(std::move(fn))
145 , _errors(err)
146 , _mallocTagStack(TfMallocTag::GetCurrentStackState())
147 {}
148
149 explicit _MallocTagsInvokerTask(Fn const &fn, _ErrorTransports *err)
150 : _fn(fn)
151 , _errors(err)
152 , _mallocTagStack(TfMallocTag::GetCurrentStackState()) {}
153
154 // Ensure only moves happen, no copies.
155 _MallocTagsInvokerTask(_MallocTagsInvokerTask &&other) = default;
156 _MallocTagsInvokerTask(const _MallocTagsInvokerTask &other) = delete;
157 _MallocTagsInvokerTask &
158 operator=(const _MallocTagsInvokerTask &other) = delete;
159
160 void operator()() const {
161 TfErrorMark m;
162 TfMallocTag::StackOverride ovr(_mallocTagStack);
163 _fn();
164 if (!m.IsClean())
165 Work_Dispatcher::_TransportErrors(m, _errors);
166 }
167 private:
168 Fn _fn;
169 _ErrorTransports *_errors;
170 TfMallocTag::StackState _mallocTagStack;
171 };
172
173 // Helper function that removes errors from \p m and stores them in a new
174 // entry in \p errors.
175 WORK_API static void
176 _TransportErrors(const TfErrorMark &m, _ErrorTransports *errors);
177
178 // WorkDispatcher implementation
179 Impl _dispatcher;
180 std::atomic<bool> _isCancelled;
181
182 // The error transports we use to transmit errors in other threads back to
183 // this thread.
184 _ErrorTransports _errors;
185
186 // Concurrent calls to Wait() have to serialize certain cleanup operations.
187 std::atomic_flag _waitCleanupFlag;
188};
189
222 : public Work_Dispatcher<PXR_WORK_IMPL_NS::WorkImpl_Dispatcher>
223{};
224
225// Wrapper class for non-const tasks.
226template <class Fn>
227struct Work_DeprecatedMutableTask {
228 explicit Work_DeprecatedMutableTask(Fn &&fn)
229 : _fn(std::move(fn)) {}
230
231 explicit Work_DeprecatedMutableTask(Fn const &fn)
232 : _fn(fn) {}
233
234 // Ensure only moves happen, no copies.
235 Work_DeprecatedMutableTask
236 (Work_DeprecatedMutableTask &&other) = default;
237 Work_DeprecatedMutableTask
238 (const Work_DeprecatedMutableTask &other) = delete;
239 Work_DeprecatedMutableTask
240 &operator= (const Work_DeprecatedMutableTask &other) = delete;
241
242 void operator()() const {
243 _fn();
244 }
245private:
246 mutable Fn _fn;
247};
248
249// Wrapper function to convert non-const tasks to a Work_DeprecatedMutableTask.
250// When adding new tasks refrain from using this wrapper, instead ensure the
251// call operator of the task is const such that it is compatible with oneTBB.
252template <typename Fn>
253Work_DeprecatedMutableTask<typename std::remove_reference_t<Fn>>
254WorkMakeDeprecatedMutableTask(Fn &&fn) {
255 return Work_DeprecatedMutableTask<typename std::remove_reference_t<Fn>>
256 (std::forward<Fn>(fn));
257}
258
260
261PXR_NAMESPACE_CLOSE_SCOPE
262
263#endif // PXR_BASE_WORK_DISPATCHER_H
Class used to record the end of the error-list.
Definition: errorMark.h:48
bool IsClean() const
Return true if no new errors were posted in this thread since the last call to SetMark(),...
Definition: errorMark.h:82
An object that represents a snapshot of a thread's TfMallocTag stack state.
Definition: mallocTag.h:336
Top-down memory tagging system.
Definition: mallocTag.h:34
static bool IsInitialized()
Return true if the tagging system is active.
Definition: mallocTag.h:189
A work dispatcher runs concurrent tasks.
Definition: dispatcher.h:223
STL namespace.