LeechCraft
0.6.70-19214-g121e5318a7
Modular cross-platform feature rich live environment.
Toggle main menu visibility
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
17
namespace
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
44
UTIL_THREADS_API
void
CheckDeadContexts
(
const
ContextExtensionBase
&);
45
46
template
<
typename
Promise,
typename
OrigAwaiter>
47
struct
AwaitableWrapper
48
{
49
Promise&
Promise_
;
50
OrigAwaiter
Orig_
;
51
52
bool
await_ready
()
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
{
61
Promise_
.State_ =
PromiseBase::CoroState::Suspended
;
62
try
63
{
64
return
Orig_
.await_suspend (handle);
65
}
66
catch
(...)
67
{
68
Promise_
.State_ =
PromiseBase::CoroState::Running
;
69
throw
;
70
}
71
}
72
73
decltype
(
auto
)
await_resume
()
74
{
75
Promise_
.State_ =
PromiseBase::CoroState::Running
;
76
CheckDeadContexts
(
Promise_
);
77
return
Orig_
.await_resume ();
78
}
79
};
80
}
81
82
struct
[[nodiscard]]
AddContext
83
{
84
CoroContext
&
Ctx_
;
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
112
struct
UTIL_THREADS_API
ContextExtensionBase
113
{
114
CoroContext::Registrations
Contexts_
;
115
QStringList
DeadContexts_
;
116
117
~ContextExtensionBase
()
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
>
143
struct
ContextExtension
:
ContextExtensionBase
144
{
145
using
HasContextExtension
= void;
146
};
147
}
LC::Util::CoroContext
Definition
corocontext.h:36
LC::Util::CoroContext::Registrations
std::vector< Registration > Registrations
Definition
corocontext.h:57
LC::Util::detail::IsAwaiter
Definition
context.h:22
corocontext.h
LC::Util::detail
Definition
fancytrayiconfreedesktop.cpp:24
LC::Util::detail::Awaiter
decltype(auto) Awaiter(T &&obj)
Definition
context.h:29
LC::Util::detail::CheckDeadContexts
void CheckDeadContexts(const ContextExtensionBase &promise)
Definition
context.cpp:15
LC::Util
Definition
icoreproxy.h:34
LC::Util::GetAwaiter
detail::EitherAwaiter< L, R, std::identity > GetAwaiter(const Either< L, R > &either, AwaiterCPO)
Definition
either.h:119
LC::Util::AddContext
Definition
context.h:83
LC::Util::AddContext::Ctx_
CoroContext & Ctx_
Definition
context.h:84
LC::Util::AddContext::await_resume
void await_resume() const noexcept
Definition
context.h:107
LC::Util::AddContext::await_ready
bool await_ready() const noexcept
Definition
context.h:91
LC::Util::AddContext::await_suspend
bool await_suspend(std::coroutine_handle< Promise > handle)
Definition
context.h:98
LC::Util::AddContext::AddContext
AddContext(CoroContext &ctx)
Definition
context.h:86
LC::Util::AwaiterCPO
Definition
taskfwd.h:22
LC::Util::ContextExtensionBase
Definition
context.h:113
LC::Util::ContextExtensionBase::await_transform
AddContext await_transform(AddContext awaitable) const noexcept
Definition
context.h:128
LC::Util::ContextExtensionBase::~ContextExtensionBase
~ContextExtensionBase()
Definition
context.h:117
LC::Util::ContextExtensionBase::HasDeadContexts
bool HasDeadContexts() const
Definition
context.h:123
LC::Util::ContextExtensionBase::Contexts_
CoroContext::Registrations Contexts_
Definition
context.h:114
LC::Util::ContextExtensionBase::DeadContexts_
QStringList DeadContexts_
Definition
context.h:115
LC::Util::ContextExtension
Definition
context.h:144
LC::Util::ContextExtension::HasContextExtension
void HasContextExtension
Definition
context.h:145
LC::Util::detail::AwaitableWrapper
Definition
context.h:48
LC::Util::detail::AwaitableWrapper::await_suspend
decltype(auto) await_suspend(auto handle)
Definition
context.h:59
LC::Util::detail::AwaitableWrapper::await_ready
bool await_ready()
Definition
context.h:52
LC::Util::detail::AwaitableWrapper::Promise_
Promise & Promise_
Definition
context.h:49
LC::Util::detail::AwaitableWrapper::Orig_
OrigAwaiter Orig_
Definition
context.h:50
LC::Util::detail::AwaitableWrapper::await_resume
decltype(auto) await_resume()
Definition
context.h:73
LC::Util::detail::PromiseBase::CoroState::Running
@ Running
Definition
task.h:30
LC::Util::detail::PromiseBase::CoroState::Suspended
@ Suspended
Definition
task.h:31
task.h
threadsconfig.h
UTIL_THREADS_API
#define UTIL_THREADS_API
Definition
threadsconfig.h:16
src
util
threads
coro
context.h
Generated by
1.18.0