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), &_diagnostics));
69 }
70 else {
71 _dispatcher.Run(
72 _InvokerTask<typename std::remove_reference<Callable>::type>(
73 std::forward<Callable>(c), &_diagnostics));
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<TfDiagnosticTransport> _DiagnosticTransports;
107
108 // Function invoker helper that wraps the invocation with a DiagnosticTrap
109 // so we can transmit diagnostics that occur back to the thread that calls
110 // Wait() for tasks to complete.
111 template <class Fn>
112 struct _InvokerTask {
113 explicit _InvokerTask(Fn &&fn, _DiagnosticTransports *diag)
114 : _fn(std::move(fn))
115 , _diagnostics(diag) {}
116
117 explicit _InvokerTask(Fn const &fn, _DiagnosticTransports *diag)
118 : _fn(fn)
119 , _diagnostics(diag) {}
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 TfDiagnosticTrap trap;
128 _fn();
129 if (!trap.IsClean()) {
130 Work_Dispatcher::_TransportDiagnostics(&trap, _diagnostics);
131 }
132 }
133 private:
134 Fn _fn;
135 _DiagnosticTransports *_diagnostics;
136 };
137
138 // Function invoker helper that wraps the invocation with a TfDiagnosticTrap
139 // so we can transmit diagnostics that occur back to the thread that Wait()
140 // s for tasks to complete. This version also duplicates the caller's
141 // malloc tag stack to the callee's thread.
142 template <class Fn>
143 struct _MallocTagsInvokerTask {
144 explicit
145 _MallocTagsInvokerTask(Fn &&fn, _DiagnosticTransports *diag)
146 : _fn(std::move(fn))
147 , _diagnostics(diag)
148 , _mallocTagStack(TfMallocTag::GetCurrentStackState())
149 {}
150
151 explicit
152 _MallocTagsInvokerTask(Fn const &fn, _DiagnosticTransports *diag)
153 : _fn(fn)
154 , _diagnostics(diag)
155 , _mallocTagStack(TfMallocTag::GetCurrentStackState()) {}
156
157 // Ensure only moves happen, no copies.
158 _MallocTagsInvokerTask(_MallocTagsInvokerTask &&other) = default;
159 _MallocTagsInvokerTask(const _MallocTagsInvokerTask &other) = delete;
160 _MallocTagsInvokerTask &
161 operator=(const _MallocTagsInvokerTask &other) = delete;
162
163 void operator()() const {
164 TfDiagnosticTrap trap;
165 TfMallocTag::StackOverride ovr(_mallocTagStack);
166 _fn();
167 if (!trap.IsClean()) {
168 Work_Dispatcher::_TransportDiagnostics(&trap, _diagnostics);
169 }
170 }
171 private:
172 Fn _fn;
173 _DiagnosticTransports *_diagnostics;
174 TfMallocTag::StackState _mallocTagStack;
175 };
176
177 // Helper function that removes diagnostics from \p trap and stores them in
178 // a new entry in \p diagnostics.
179 WORK_API static void
180 _TransportDiagnostics(TfDiagnosticTrap *trap,
181 _DiagnosticTransports *diagnostics);
182
183 // WorkDispatcher implementation
184 Impl _dispatcher;
185 std::atomic<bool> _isCancelled;
186
187 // The diagnostic transports we use to transmit those issued in other
188 // threads back to this thread.
189 _DiagnosticTransports _diagnostics;
190
191 // Concurrent calls to Wait() have to serialize certain cleanup operations.
192 std::atomic_flag _waitCleanupFlag;
193};
194
227 : public Work_Dispatcher<PXR_WORK_IMPL_NS::WorkImpl_Dispatcher>
228{};
229
230// Wrapper class for non-const tasks.
231template <class Fn>
232struct Work_DeprecatedMutableTask {
233 explicit Work_DeprecatedMutableTask(Fn &&fn)
234 : _fn(std::move(fn)) {}
235
236 explicit Work_DeprecatedMutableTask(Fn const &fn)
237 : _fn(fn) {}
238
239 // Ensure only moves happen, no copies.
240 Work_DeprecatedMutableTask
241 (Work_DeprecatedMutableTask &&other) = default;
242 Work_DeprecatedMutableTask
243 (const Work_DeprecatedMutableTask &other) = delete;
244 Work_DeprecatedMutableTask
245 &operator= (const Work_DeprecatedMutableTask &other) = delete;
246
247 void operator()() const {
248 _fn();
249 }
250private:
251 mutable Fn _fn;
252};
253
254// Wrapper function to convert non-const tasks to a Work_DeprecatedMutableTask.
255// When adding new tasks refrain from using this wrapper, instead ensure the
256// call operator of the task is const such that it is compatible with oneTBB.
257template <typename Fn>
258Work_DeprecatedMutableTask<typename std::remove_reference_t<Fn>>
259WorkMakeDeprecatedMutableTask(Fn &&fn) {
260 return Work_DeprecatedMutableTask<typename std::remove_reference_t<Fn>>
261 (std::forward<Fn>(fn));
262}
263
265
266PXR_NAMESPACE_CLOSE_SCOPE
267
268#endif // PXR_BASE_WORK_DISPATCHER_H
A scoped, stack-based mechanism for intercepting and examining diagnostics issued on the current thre...
TF_API bool IsClean() const
Return true if no diagnostics have been captured.
An object that represents a snapshot of a thread's TfMallocTag stack state.
Definition mallocTag.h:337
Top-down memory tagging system.
Definition mallocTag.h:35
static bool IsInitialized()
Return true if the tagging system is active.
Definition mallocTag.h:190
A work dispatcher runs concurrent tasks.
Definition dispatcher.h:228
STL namespace.