Lightweight 0.20260921.0
Loading...
Searching...
No Matches
Backend.hpp
1// SPDX-License-Identifier: Apache-2.0
2#pragma once
3
4#include "Async.hpp"
5#include "Executor.hpp"
6#include "StrandExecutor.hpp"
7
8#include <stop_token>
9#include <utility>
10
11namespace Lightweight::Async
12{
13
14/// @ingroup Async
15/// Per-connection asynchronous execution backend.
16///
17/// A backend owns (or references) the execution context used to run a connection's blocking
18/// ODBC work and to resume the awaiting coroutine. Currently the only implementation is
19/// @ref ThreadOffloadBackend (portable; offloads to a worker thread). A native event backend
20/// (Windows + SQL Server) is planned behind this same interface.
21///
22/// The backend is selected once per connection (see @c SqlConnection::EnableAsync) and used by
23/// all of that connection's async methods.
25{
26 public:
27 IAsyncBackend() = default;
28 IAsyncBackend(IAsyncBackend const&) = delete;
29 IAsyncBackend& operator=(IAsyncBackend const&) = delete;
30 IAsyncBackend(IAsyncBackend&&) = delete;
31 IAsyncBackend& operator=(IAsyncBackend&&) = delete;
32 virtual ~IAsyncBackend() = default;
33
34 /// The serializing executor for this connection; blocking work is offloaded here so the
35 /// connection's ODBC handle is only ever touched by one thread at a time.
36 [[nodiscard]] virtual StrandExecutor& Strand() noexcept = 0;
37
38 /// The scheduler used to resume coroutines after a blocking step completes (typically the
39 /// application's run loop).
40 [[nodiscard]] virtual IResumeScheduler& ResumeScheduler() noexcept = 0;
41};
42
43/// Runs a whole synchronous operation on @p backend's strand, resuming on its scheduler.
44///
45/// This is the coarse-grained workhorse used by the high-level async methods: the entire
46/// synchronous body (parameter binding, the ODBC call, and post-processing) runs as one
47/// closure on the connection's strand — never split across threads — and the coroutine
48/// resumes on the app thread with the result.
49///
50/// @tparam F A callable invocable with no arguments.
51/// @param backend The connection's async backend.
52/// @param fn The synchronous operation to run (consumed).
53/// @param token Optional cancellation token (a default-constructed @c std::stop_token is non-cancellable).
54/// @return A Task producing @p fn's result.
55template <typename F>
56[[nodiscard]] Task<detail::OffloadResult<F>> RunAsync(IAsyncBackend& backend, F fn, std::stop_token token = {})
57{
58 return Async(backend.Strand(), backend.ResumeScheduler(), std::move(fn), std::move(token));
59}
60
61} // namespace Lightweight::Async
virtual IResumeScheduler & ResumeScheduler() noexcept=0
virtual StrandExecutor & Strand() noexcept=0