23template <
class Output,
class Input>
24void validate_distinct_async_operand_queues(Output
const& output, Input
const& input)
26 if constexpr (
requires {
31 ERROR_IF(std::addressof(output.queue()) == std::addressof(input.queue()),
32 "async output must not share an epoch queue with an input");
43template <
typename Awaitable>
45 typename std::remove_cvref_t<
decltype(
get_awaiter(a))>::value_type;
51template <
typename Awaitable>
53 typename std::remove_cvref_t<
decltype(
get_awaiter(a))>::value_type;
58template <
typename Awaitable>
60 typename Awaitable::value_type;
61 get_awaiter(a).await_resume().emplace(std::move(v));
64template <
typename Awaitable,
typename T>
71template <
typename Awaitable,
typename T>
73 requires(Awaitable a) {
requires std::constructible_from<T,
decltype(
get_awaiter(a).await_resume())>; };
77template <
typename Awaitable,
typename T>
79 {
get_awaiter(a).await_resume() = std::declval<T>() };
84template <
typename Awaitable>
89template <
typename Awaitable,
typename T>
98template <
typename AsyncLike>
using write_buffer_t =
decltype(std::declval<AsyncLike&>().write());
100template <
typename AsyncLike>
using take_awaiter_t =
decltype(std::declval<write_buffer_t<AsyncLike>&>().take());
103template <
typename AsyncLike>
106template <
typename AsyncLike,
typename T>
111template <
typename AsyncLike,
typename T>
120template <
typename AsyncLike,
typename T>
126template <
typename AsyncLike,
typename T>
147template <
typename T,
typename U,
typename Op>
149 decltype(std::declval<Op>()(std::declval<async_value_t<T>>(), std::declval<
async_value_t<U>>()));
152template <
typename T,
typename U,
typename Op>
154 requires(Op op, async_value_t<T> t, async_value_t<U> u) {
160template <
typename A,
typename B,
typename Writer,
typename Op>
163 requires std::constructible_from<
typename std::remove_cvref_t<
decltype(out.write())>::value_type,
decltype(op(a, b))>;
166template <
typename T,
typename U,
typename Op>
169 requires(async_value_t<T> lhs, async_value_t<U>&& rhs, Op op) { op(lhs, std::forward<async_value_t<U>>(rhs)); };
193template <
typename A,
typename B, async_writer Writer,
typename Op>
197 detail::validate_distinct_async_operand_queues(out, a);
198 detail::validate_distinct_async_operand_queues(out, b);
200 auto a_buf =
read(std::forward<A>(a));
201 auto b_buf =
read(std::forward<B>(b));
202 auto out_buf = out.write();
205 auto ab =
co_await all(a_, b_);
206 auto tmp = op_(std::get<0>(ab), std::get<1>(ab));
209 co_await out_ = std::move(tmp);
211 }(std::move(a_buf), std::move(b_buf), std::move(out_buf), std::move(op)));
227 detail::validate_distinct_async_operand_queues(lhs, rhs);
229 auto rhs_buf =
read(std::forward<U>(rhs));
230 auto lhs_out = lhs.
write();
233 auto output_storage = out_.
storage();
234 auto awaited =
co_await all(output_storage, rhs_);
235 auto& storage = std::get<0>(awaited);
236 auto& rhs_value = std::get<1>(awaited);
238 op_(*storage, rhs_value);
240 }(std::move(lhs_out), std::move(rhs_buf), std::move(op)));
264template <
typename Awaitable,
typename Target>
265concept async_initialization_awaitable =
266 read_buffer_awaitable<Awaitable> &&
267 std::constructible_from<Target, decltype(get_awaiter(std::declval<Awaitable&>()).await_resume())>;
269template <
typename Target,
typename Source>
270concept current_value_assignment_source =
271 !is_async_alias_v<Target> && std::constructible_from<Target, async_value_t<Source>
const&> &&
272 write_proxy_assignable_source<Target, Target>;
274template <
typename Awaitable,
typename Target>
275concept async_alias_assignment_awaitable =
276 read_buffer_awaitable<Awaitable> &&
277 async_alias_assignable_from<Target, decltype(get_awaiter(std::declval<Awaitable&>()).await_resume())>;
284template <
typename T,
typename U>
285 requires(!is_async_alias_v<T> && detail::async_initialization_awaitable<U, T>)
289 auto&&
value =
co_await source_;
290 auto target =
co_await destination_;
291 target.emplace(
value);
294 }(std::forward<U>(source), std::move(destination)));
298template <
typename T,
typename U>
299 requires(!is_async_alias_v<T> && detail::async_source<U> && std::constructible_from<T, async_value_t<U>
const&>)
308template <
typename T,
typename U>
309 requires(!is_async_alias_v<T> && read_buffer_awaitable_of<U, T> && detail::write_proxy_assignable_source<T, T>)
313 T
value(
co_await source_);
315 co_await destination_ = std::move(
value);
317 }(std::forward<U>(source), std::move(destination)));
323template <
typename T,
typename U>
324 requires(is_async_alias_v<T> && detail::async_alias_assignment_awaitable<U, T>)
328 auto&&
value =
co_await source_;
329 co_await destination_ =
value;
332 }(std::forward<U>(source), std::move(destination)));
340template <
typename T,
typename U>
342 requires(detail::current_value_assignment_source<T, U> ||
343 (is_async_alias_v<T> && detail::async_alias_assignable_from<T, async_value_t<U>
const&>))
353template <
typename T,
typename U>
356 (detail::current_value_assignment_source<T, U> ||
357 (is_async_alias_v<T> && detail::async_alias_assignable_from<T,
async_value_t<U> const&>))
362template <
typename T,
typename U>
363 requires(!is_async_alias_v<T>) && async_mutable_writer_of<U, T> && async_movable_to<U, T>
371 auto src = std::forward<U>(rhs).write();
373 T movable(
co_await src.take());
375 co_await dst = std::move(movable);
377 }(std::move(src), std::move(lhs)));
380template <
typename T,
typename U>
381 requires(!is_async_alias_v<T>) && (!async_writer<std::remove_cvref_t<U>>) && std::constructible_from<T, U&&>
385 co_await dst = std::move(val);
387 }(std::move(rhs), std::move(lhs)));
395template <
typename T,
typename U>
396 requires(!is_async_alias_v<T>)
403#define UNI20_DEFINE_BINARY_OP(OPNAME, OP) \
404 template <typename T, typename U> \
405 requires async_binary_applicable<T, U, OP> \
406 auto operator OPNAME(T&& a, U&& b) \
408 using R = async_binary_result_t<T, U, OP>; \
410 async_binary_op(result, std::forward<T>(a), std::forward<U>(b), OP{}); \
419#undef UNI20_DEFINE_BINARY_OP
421#define UNI20_DEFINE_ASSIGN_OP(NAME, OP) \
424 template <typename LHS, typename RHS> void operator()(LHS& lhs, RHS&& rhs) const \
426 lhs OP std::forward<RHS>(rhs); \
435#undef UNI20_DEFINE_ASSIGN_OP
437#define UNI20_DEFINE_ASYNC_COMPOUND_OPERATOR(OPSYM, FUNCTOR) \
438 template <typename T, typename U> \
439 requires uni20::async::is_async_compound_applicable<Async<T>&, U, uni20::async::FUNCTOR> \
440 Async<T>& operator OPSYM(Async<T>& lhs, U && rhs) \
442 uni20::async::async_compound_op(lhs, std::forward<U>(rhs), uni20::async::FUNCTOR{}); \
451#undef UNI20_DEFINE_ASYNC_COMPOUND_OPERATOR
460template <
typename T,
typename U>
465 auto result = -
co_await in_;
467 co_await out_ = std::move(result);
469 }(std::move(rhs), std::move(lhs)));
478 requires requires(T t) { -t; }
Promise-neutral coroutine task ownership and the public AsyncTask type.
Utilities for awaiting on Async<T>: co_await overload, all(), try_await().
Canonical host-oriented coroutine task type.
Definition async_task.hpp:196
Async<T> is a container for coroutine-safe asynchronous read/write.
Definition async/async.hpp:93
WriteBuffer< T > write()
Begin exclusive asynchronous access to the payload.
Definition async/async.hpp:346
Exclusive mutable-access buffer for one Async<T> epoch.
Definition buffers.hpp:859
auto storage() &
Awaiter yielding direct access to writer shared storage.
Definition buffers.hpp:1029
void release() noexcept
Release the writer epoch held by this buffer.
Definition buffers.hpp:957
Raised when a writer requests a mutable reference before construction.
Definition async_errors.hpp:74
Concept to determine if Op(T,U) is a candidate for forwarding for Async.
Definition async_ops.hpp:153
concept for validating a binary operation true if the operation result can be emplaced into the write...
Definition async_ops.hpp:161
Concept for a type that behaves like an asynchronous reader and writer (like Async<T>).
Definition async_ops.hpp:144
Concept for an Awaitable that yields a movable object that can be moved into T.
Definition async_ops.hpp:121
Definition async_ops.hpp:127
Concept for a type that behaves like an asynchronous writer that is also readable: it has a write() f...
Definition async_ops.hpp:136
Definition async_ops.hpp:107
An async_reader is satisfied if .read() returns an async read buffer.
Definition async_ops.hpp:95
Concept requiring an async writer that accepts values constructible from T.
Definition async_ops.hpp:112
An async_writer is satisfied if .write() returns a buffer supporting emplace(...).
Definition async_ops.hpp:104
Definition async_ops.hpp:65
concept for a valid type that supports in-place construction via emplace(...)
Definition async_ops.hpp:59
Definition async_ops.hpp:167
concept for a valid type that behaves as a read buffer awaitable for type T.
Definition async_ops.hpp:72
concept for a valid type that behaves as a read buffer awaitable This requires that the awaiter has a...
Definition async_ops.hpp:44
concept for a valid type that behaves as a write buffer that is also readable This requires that T x ...
Definition async_ops.hpp:90
concept for a valid type that behaves as a write buffer that is also readable This requires that valu...
Definition async_ops.hpp:85
concept for a valid type that behaves as a write buffer awaitable This requires that T x; co_await a ...
Definition async_ops.hpp:78
concept for a valid type that behaves as a write buffer awaitable This requires that value_type x; co...
Definition async_ops.hpp:52
locale_t value
Definition data_table.cpp:49
Coroutine scheduler for AsyncTask.
void async_move(WriteBuffer< T > lhs, U &&rhs)
Definition async_ops.hpp:369
decltype(std::declval< Op >()(std::declval< async_value_t< T > >(), std::declval< async_value_t< U > >())) async_binary_result_t
Result type of applying binary op Op to async_value_t<T>, async_value_t
Definition async_ops.hpp:149
#define UNI20_DEFINE_ASSIGN_OP(NAME, OP)
Definition async_ops.hpp:421
void async_binary_op(Writer &out, A &&a, B &&b, Op op)
Launch a coroutine computing result = op(a, b)
Definition async_ops.hpp:195
void async_initialize(Async< T > &destination, U &&source)
Initialize a fresh independent async value from another async source.
Definition async_ops.hpp:300
void async_compound_op(Async< T > &lhs, U &&rhs, Op op)
Launch a coroutine applying an in-place operation op(lhs, rhs).
Definition async_ops.hpp:225
#define UNI20_DEFINE_ASYNC_COMPOUND_OPERATOR(OPSYM, FUNCTOR)
Definition async_ops.hpp:437
auto operator-(Async< T > const &x)
Unary negation overload for Async values.
Definition async_ops.hpp:477
decltype(std::declval< write_buffer_t< AsyncLike > & >().take()) take_awaiter_t
Alias for the awaiter type returned by write_buffer_t::take().
Definition async_ops.hpp:100
void async_assign(WriteBuffer< T > destination, U &&source)
Assign an awaitable value into an existing independent-value timeline.
Definition async_ops.hpp:310
decltype(std::declval< AsyncLike & >().write()) write_buffer_t
Alias for the write-buffer type produced by write() on an lvalue.
Definition async_ops.hpp:98
#define UNI20_DEFINE_BINARY_OP(OPNAME, OP)
Definition async_ops.hpp:403
void async_negate(WriteBuffer< T > lhs, U &&rhs)
Negate a source value asynchronously and write into a destination buffer.
Definition async_ops.hpp:461
This represents the reverse-mode adjoint for functions of complex variables, assuming a real-valued s...
Definition async/async.hpp:26
void schedule(AsyncTask &&task)
Schedule a task on the currently configured global scheduler.
Definition debug_scheduler.hpp:237
auto all(Aw &&... aw) noexcept
Build an awaitable that waits for all of the provided awaitables.
Definition awaiters.hpp:200
decltype(auto) get_awaiter(U &&u) noexcept
for an awaitable a, return the actual Awaitable object returned by co_await
Definition awaiters.hpp:225
ReadBuffer< T > read(Async< T > const &a)
Convenience helper that forwards to Async<T>::read().
Definition async/async.hpp:540
typename async_value_type< std::remove_cvref_t< T > >::type async_value_t
Extract the underlying value type from an immediate value or Async<T>.
Definition async_traits.hpp:30
Async aliases for lazy tensor-level views.
#define ERROR_IF(cond,...)
Definition trace.hpp:389