Lightweight 0.20260921.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/// @ingroup Async
18/// Interface for an executor that runs posted work items.
19///
20/// Executors are injected (dependency injection) and owned by the caller; the async layer
21/// only ever holds references to them. Every implementation's @ref Post is thread-safe.
23{
24 public:
25 IExecutor() = default;
26 IExecutor(IExecutor const&) = delete;
27 IExecutor& operator=(IExecutor const&) = delete;
28 IExecutor(IExecutor&&) = delete;
29 IExecutor& operator=(IExecutor&&) = delete;
30 virtual ~IExecutor() = default;
31
32 /// Schedules @p work to run on the executor. Thread-safe.
33 ///
34 /// @param work The work item to enqueue (consumed).
35 virtual void Post(Work work) = 0;
36};
37
38/// @ingroup Async
39/// Interface for scheduling the resumption of a suspended coroutine.
40///
41/// Kept separate from @ref IExecutor::Post so resumption can be expressed as a bare
42/// coroutine handle, which lets implementations avoid wrapping every resume in a
43/// @c Work allocation on hot paths.
45{
46 public:
47 IResumeScheduler() = default;
48 IResumeScheduler(IResumeScheduler const&) = delete;
49 IResumeScheduler& operator=(IResumeScheduler const&) = delete;
51 IResumeScheduler& operator=(IResumeScheduler&&) = delete;
52 virtual ~IResumeScheduler() = default;
53
54 /// Schedules @p handle to be resumed. Thread-safe.
55 ///
56 /// @param handle The coroutine to resume.
57 virtual void Resume(std::coroutine_handle<> handle) = 0;
58};
59
60/// @ingroup Async
61/// An executor that runs work synchronously on the calling thread.
62///
63/// Useful for tests and for degenerate single-threaded configurations where no thread
64/// hand-off is desired. Note that with synchronous ODBC drivers an @ref InlineExecutor
65/// used as the offload target will block the calling thread for the duration of the call.
66class InlineExecutor final: public IExecutor, public IResumeScheduler
67{
68 public:
69 void Post(Work work) override
70 {
71 if (work)
72 work();
73 }
74
75 void Resume(std::coroutine_handle<> handle) override
76 {
77 if (handle)
78 handle.resume();
79 }
80};
81
82} // 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:69
void Resume(std::coroutine_handle<> handle) override
Definition Executor.hpp:75