LeechCraft 0.6.70-19214-g121e5318a7
Modular cross-platform feature rich live environment.
Loading...
Searching...
No Matches
context.h
Go to the documentation of this file.
1/**********************************************************************
2 * LeechCraft - modular cross-platform feature rich internet client.
3 * Copyright (C) 2006-2014 Georg Rudoy
4 *
5 * Distributed under the Boost Software License, Version 1.0.
6 * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7 **********************************************************************/
8
9#pragma once
10
11#include <coroutine>
12#include <utility>
13#include "../threadsconfig.h"
14#include "task.h"
15#include "corocontext.h"
16
17namespace LC::Util
18{
19 namespace detail
20 {
21 template<typename T>
22 concept IsAwaiter = requires (T t)
23 {
24 t.await_ready ();
25 t.await_resume ();
26 };
27
28 template<typename T>
29 decltype (auto) Awaiter (T&& obj)
30 {
31 if constexpr (requires { GetAwaiter (std::forward<T> (obj), AwaiterCPO {}); })
32 return GetAwaiter (std::forward<T> (obj), AwaiterCPO {});
33 else if constexpr (requires { operator co_await (std::forward<T> (obj)); })
34 return operator co_await (std::forward<T> (obj));
35 else if constexpr (requires { std::forward<T> (obj).operator co_await (); })
36 return std::forward<T> (obj).operator co_await ();
37 else
38 {
39 static_assert (IsAwaiter<std::remove_reference_t<T>>, "operand doesn't look like an Awaitable");
40 return std::forward<T> (obj);
41 }
42 }
43
45
46 template<typename Promise, typename OrigAwaiter>
48 {
49 Promise& Promise_;
50 OrigAwaiter Orig_;
51
53 {
54 // If the coro is near death due to a context death, awaiting it is futile at best and UB at worst
55 // (for instance, if the thing being awaited is guarded by the `CoroContext` who killed the coro).
56 return Promise_.HasDeadContexts () || Orig_.await_ready ();
57 }
58
59 decltype (auto) await_suspend (auto handle)
60 {
62 try
63 {
64 return Orig_.await_suspend (handle);
65 }
66 catch (...)
67 {
69 throw;
70 }
71 }
72
73 decltype (auto) await_resume ()
74 {
77 return Orig_.await_resume ();
78 }
79 };
80 }
81
82 struct [[nodiscard]] AddContext
83 {
85
86 explicit AddContext (CoroContext& ctx)
87 : Ctx_ { ctx }
88 {
89 }
90
91 bool await_ready () const noexcept
92 {
93 return false;
94 }
95
96 template<typename Promise>
97 requires requires { typename Promise::HasContextExtension; }
98 bool await_suspend (std::coroutine_handle<Promise> handle)
99 {
100 // children should die first (as they are registered last)
101 Ctx_.Coros_.push_front ({ handle, &handle.promise (), &handle.promise () });
102 const auto it = Ctx_.Coros_.begin ();
103 handle.promise ().Contexts_.push_back ({ &Ctx_, it });
104 return false;
105 }
106
107 void await_resume () const noexcept
108 {
109 }
110 };
111
113 {
115 QStringList DeadContexts_;
116
118 {
119 for (auto [ctx, thisPos] : Contexts_)
120 ctx->Coros_.erase (thisPos);
121 }
122
123 bool HasDeadContexts () const
124 {
125 return !DeadContexts_.isEmpty ();
126 }
127
128 AddContext await_transform (AddContext awaitable) const noexcept
129 {
130 return awaitable;
131 }
132
133 template<typename Self, typename T>
134 requires (!std::same_as<std::decay_t<T>, AddContext>)
135 auto await_transform (this Self&& self, T&& awaitable)
136 {
137 using OrigAwaiter = decltype (detail::Awaiter (std::forward<T> (awaitable)));
138 return detail::AwaitableWrapper<std::decay_t<Self>, OrigAwaiter> { self, detail::Awaiter (std::forward<T> (awaitable)) };
139 }
140 };
141
142 template<typename>
147}
std::vector< Registration > Registrations
Definition corocontext.h:57
decltype(auto) Awaiter(T &&obj)
Definition context.h:29
void CheckDeadContexts(const ContextExtensionBase &promise)
Definition context.cpp:15
detail::EitherAwaiter< L, R, std::identity > GetAwaiter(const Either< L, R > &either, AwaiterCPO)
Definition either.h:119
CoroContext & Ctx_
Definition context.h:84
void await_resume() const noexcept
Definition context.h:107
bool await_ready() const noexcept
Definition context.h:91
bool await_suspend(std::coroutine_handle< Promise > handle)
Definition context.h:98
AddContext(CoroContext &ctx)
Definition context.h:86
AddContext await_transform(AddContext awaitable) const noexcept
Definition context.h:128
CoroContext::Registrations Contexts_
Definition context.h:114
decltype(auto) await_suspend(auto handle)
Definition context.h:59
decltype(auto) await_resume()
Definition context.h:73
#define UTIL_THREADS_API