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