Lightweight 0.20260617.0
Loading...
Searching...
No Matches
Executor.hpp
1// SPDX-License-Identifier: Apache-2.0
2#pragma once
3
4#include <coroutine>
5#include <functional>
6
7namespace Lightweight::Async
8{
9
10/// A unit of deferred work scheduled on an @ref IExecutor.
11///
12/// @c std::function (rather than @c std::move_only_function) is used so the async layer builds
13/// with standard libraries that do not yet provide the latter; every work item the library posts
14/// is a small, copyable closure.
15using Work = std::function<void()>;
16
17/// Interface for an executor that runs posted work items.
18///
19/// Executors are injected (dependency injection) and owned by the caller; the async layer
20/// only ever holds references to them. Every implementation's @ref Post is thread-safe.
22{
23 public:
24 IExecutor() = default;
25 IExecutor(IExecutor const&) = delete;
26 IExecutor& operator=(IExecutor const&) = delete;
27 IExecutor(IExecutor&&) = delete;
28 IExecutor& operator=(IExecutor&&) = delete;
29 virtual ~IExecutor() = default;
30
31 /// Schedules @p work to run on the executor. Thread-safe.
32 ///
33 /// @param work The work item to enqueue (consumed).
34 virtual void Post(Work work) = 0;
35};
36
37/// Interface for scheduling the resumption of a suspended coroutine.
38///
39/// Kept separate from @ref IExecutor::Post so resumption can be expressed as a bare
40/// coroutine handle, which lets implementations avoid wrapping every resume in a
41/// @c Work allocation on hot paths.
43{
44 public:
45 IResumeScheduler() = default;
46 IResumeScheduler(IResumeScheduler const&) = delete;
47 IResumeScheduler& operator=(IResumeScheduler const&) = delete;
49 IResumeScheduler& operator=(IResumeScheduler&&) = delete;
50 virtual ~IResumeScheduler() = default;
51
52 /// Schedules @p handle to be resumed. Thread-safe.
53 ///
54 /// @param handle The coroutine to resume.
55 virtual void Resume(std::coroutine_handle<> handle) = 0;
56};
57
58/// An executor that runs work synchronously on the calling thread.
59///
60/// Useful for tests and for degenerate single-threaded configurations where no thread
61/// hand-off is desired. Note that with synchronous ODBC drivers an @ref InlineExecutor
62/// used as the offload target will block the calling thread for the duration of the call.
63class InlineExecutor final: public IExecutor, public IResumeScheduler
64{
65 public:
66 void Post(Work work) override
67 {
68 if (work)
69 work();
70 }
71
72 void Resume(std::coroutine_handle<> handle) override
73 {
74 if (handle)
75 handle.resume();
76 }
77};
78
79} // namespace Lightweight::Async
virtual void Post(Work work)=0
virtual void Resume(std::coroutine_handle<> handle)=0
void Post(Work work) override
Definition Executor.hpp:66
void Resume(std::coroutine_handle<> handle) override
Definition Executor.hpp:72