Skip to content

Commit b2650bf

Browse files
committed
Synced the interfaces of Sequencer & SequencerLite. Updated comments
Signed-off-by: Denis Mindolin <[email protected]>
1 parent 2ed48cf commit b2650bf

File tree

4 files changed

+234
-37
lines changed

4 files changed

+234
-37
lines changed

quantum/util/impl/quantum_sequencer_lite_impl.h

Lines changed: 105 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -190,29 +190,68 @@ SequencerLite<SequenceKey, Hash, KeyEqual, Allocator>::scheduleTask(
190190
}
191191
_taskStats->decrementPendingTaskCount();
192192

193-
_dispatcher.post(task->_queueId, task->_isHighPriority, bsl::move(taskWrapper));
193+
_dispatcher.post(task->_queueId, task->_isHighPriority, std::move(taskWrapper));
194194
}
195195

196196
template <class SequenceKey, class Hash, class KeyEqual, class Allocator>
197+
template<class FUNC, class ...ARGS>
198+
std::function<int(VoidContextPtr)>
199+
SequencerLite<SequenceKey, Hash, KeyEqual, Allocator>::wrap(
200+
FUNC&& func, ARGS&&... args)
201+
{
202+
return [f = func, a = std::make_tuple(std::forward<ARGS>(args)...)](VoidContextPtr ctx) -> int {
203+
return std::apply(
204+
[f, ctx](auto&&... args) { return f(ctx, std::forward<decltype(args)>(args)...); },
205+
std::move(a));
206+
};
207+
}
208+
209+
template <class SequenceKey, class Hash, class KeyEqual, class Allocator>
210+
template <class FUNC, class ... ARGS>
197211
void
198212
SequencerLite<SequenceKey, Hash, KeyEqual, Allocator>::enqueue(
199-
const SequenceKey& sequenceKey,
200-
std::function<int(VoidContextPtr)>&& func,
201-
void* opaque,
202-
int queueId,
203-
bool isHighPriority)
213+
const SequenceKey& sequenceKey, FUNC&& func, ARGS&&... args)
214+
{
215+
enqueueSingle(nullptr, (int)IQueue::QueueId::Any, false, sequenceKey, std::move(func), std::forward<ARGS>(args)...);
216+
}
217+
218+
template <class SequenceKey, class Hash, class KeyEqual, class Allocator>
219+
template <class FUNC, class ... ARGS>
220+
void
221+
SequencerLite<SequenceKey, Hash, KeyEqual, Allocator>::enqueue(
222+
void* opaque,
223+
int queueId,
224+
bool isHighPriority,
225+
const SequenceKey& sequenceKey,
226+
FUNC&& func,
227+
ARGS&&... args)
228+
{
229+
enqueueSingle(opaque, queueId, isHighPriority, sequenceKey, std::move(func), std::forward<ARGS>(args)...);
230+
}
231+
232+
template <class SequenceKey, class Hash, class KeyEqual, class Allocator>
233+
template <class FUNC, class ... ARGS>
234+
void
235+
SequencerLite<SequenceKey, Hash, KeyEqual, Allocator>::enqueueSingle(
236+
void* opaque,
237+
int queueId,
238+
bool isHighPriority,
239+
const SequenceKey& sequenceKey,
240+
FUNC&& func,
241+
ARGS&&... args)
204242
{
205243
if (_drain)
206244
{
207245
throw std::runtime_error("SequencerLite is disabled");
208246
}
247+
209248
if (queueId < (int)IQueue::QueueId::Any)
210249
{
211250
throw std::out_of_range(std::string{"Invalid IO queue id: "} + std::to_string(queueId));
212251
}
213252

214253
auto task = std::make_shared<SequencerLiteTask<SequenceKey>>(
215-
std::move(func),
254+
wrap(std::move(func), std::forward<ARGS>(args)...),
216255
false,
217256
opaque,
218257
queueId,
@@ -230,13 +269,40 @@ SequencerLite<SequenceKey, Hash, KeyEqual, Allocator>::enqueue(
230269
}
231270

232271
template <class SequenceKey, class Hash, class KeyEqual, class Allocator>
272+
template <class FUNC, class ... ARGS>
233273
void
234274
SequencerLite<SequenceKey, Hash, KeyEqual, Allocator>::enqueue(
275+
const std::vector<SequenceKey>& sequenceKeys,
276+
FUNC&& func,
277+
ARGS&&... args)
278+
{
279+
enqueueMultiple(nullptr, (int)IQueue::QueueId::Any, false, sequenceKeys, std::move(func), std::forward<ARGS>(args)...);
280+
}
281+
282+
template <class SequenceKey, class Hash, class KeyEqual, class Allocator>
283+
template <class FUNC, class ... ARGS>
284+
void
285+
SequencerLite<SequenceKey, Hash, KeyEqual, Allocator>::enqueue(
286+
void* opaque,
287+
int queueId,
288+
bool isHighPriority,
235289
const std::vector<SequenceKey>& sequenceKeys,
236-
std::function<int(VoidContextPtr)>&& func,
290+
FUNC&& func,
291+
ARGS&&... args)
292+
{
293+
enqueueMultiple(opaque, queueId, isHighPriority, sequenceKeys, std::move(func), std::forward<ARGS>(args)...);
294+
}
295+
296+
template <class SequenceKey, class Hash, class KeyEqual, class Allocator>
297+
template <class FUNC, class ... ARGS>
298+
void
299+
SequencerLite<SequenceKey, Hash, KeyEqual, Allocator>::enqueueMultiple(
237300
void* opaque,
238301
int queueId,
239-
bool isHighPriority)
302+
bool isHighPriority,
303+
const std::vector<SequenceKey>& sequenceKeys,
304+
FUNC&& func,
305+
ARGS&&... args)
240306
{
241307
if (_drain)
242308
{
@@ -248,7 +314,7 @@ SequencerLite<SequenceKey, Hash, KeyEqual, Allocator>::enqueue(
248314
}
249315

250316
auto task = std::make_shared<SequencerLiteTask<SequenceKey>>(
251-
std::move(func),
317+
wrap(std::move(func), std::forward<ARGS>(args)...),
252318
false,
253319
opaque,
254320
queueId,
@@ -274,11 +340,35 @@ SequencerLite<SequenceKey, Hash, KeyEqual, Allocator>::enqueue(
274340
}
275341

276342
template <class SequenceKey, class Hash, class KeyEqual, class Allocator>
343+
template <class FUNC, class ... ARGS>
344+
void
345+
SequencerLite<SequenceKey, Hash, KeyEqual, Allocator>::enqueueAll(FUNC&& func, ARGS&&... args)
346+
{
347+
enqueueAllImpl(nullptr, (int)IQueue::QueueId::Any, false, std::move(func), std::forward<ARGS>(args)...);
348+
}
349+
350+
template <class SequenceKey, class Hash, class KeyEqual, class Allocator>
351+
template <class FUNC, class ... ARGS>
277352
void
278353
SequencerLite<SequenceKey, Hash, KeyEqual, Allocator>::enqueueAll(
279-
std::function<int(VoidContextPtr)>&& func,
280-
void* opaque,
281-
int queueId)
354+
void* opaque,
355+
int queueId,
356+
bool isHighPriority,
357+
FUNC&& func,
358+
ARGS&&... args)
359+
{
360+
enqueueAllImpl(opaque, queueId, isHighPriority, std::move(func), std::forward<ARGS>(args)...);
361+
}
362+
363+
template <class SequenceKey, class Hash, class KeyEqual, class Allocator>
364+
template <class FUNC, class ... ARGS>
365+
void
366+
SequencerLite<SequenceKey, Hash, KeyEqual, Allocator>::enqueueAllImpl(
367+
void* opaque,
368+
int queueId,
369+
bool isHighPriority,
370+
FUNC&& func,
371+
ARGS&&... args)
282372
{
283373
if (_drain)
284374
{
@@ -290,11 +380,11 @@ SequencerLite<SequenceKey, Hash, KeyEqual, Allocator>::enqueueAll(
290380
}
291381

292382
auto task = std::make_shared<SequencerLiteTask<SequenceKey>>(
293-
std::move(func),
383+
wrap(std::move(func), std::forward<ARGS>(args)...),
294384
true,
295385
opaque,
296386
queueId,
297-
false);
387+
isHighPriority);
298388

299389
std::lock_guard<std::mutex> lock(_mutex);
300390

quantum/util/quantum_sequencer.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,14 @@ namespace quantum {
3535
/// @tparam Hash Hash-function used for storing instances of SequenceKey in hash maps
3636
/// @tparam KeyEqual The equal-function used for storing instances of SequenceKey in hash maps
3737
/// @tparam Allocator The allocator used for storing instances of SequenceKey in hash maps
38-
38+
/// @note quantum::Sequencer heavily relies on quantum::Dispatcher to track task interdependence
39+
/// and finding pending tasks ready to be executed (i.e. those having no pending dependents). Because
40+
/// quantum::Dispatcher is not optimized for this particular task, the performance of task scheduling
41+
/// via quantum::Sequencer and the overall CPU usage may be suboptimal. In particular, this may become
42+
/// noticable when quantum::Dispatcher has a lot of coroutine threads configured and long chains of dependent tasks
43+
/// are enqueued to quantum::Sequencer. If this becomes an issue, it's suggested to use quantum::SequencerLite
44+
/// instead. quantum::SequencerLite manages task ordering ourside of quantum::Dispatcher.
45+
3946
template <class SequenceKey,
4047
class Hash = std::hash<SequenceKey>,
4148
class KeyEqual = std::equal_to<SequenceKey>,

0 commit comments

Comments
 (0)