LeechCraft 0.6.70-17335-ge406ffdcaf
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 <stdexcept>
13#include <QMetaObject>
14#include <QObject>
15#include <QVector>
16#include "../threadsconfig.h"
17
18namespace LC::Util
19{
20 namespace detail
21 {
23 {
24 std::string ClassName_;
25 QString ObjectName_;
26 };
27 }
28
29 class UTIL_THREADS_API ContextDeadException : public std::runtime_error
30 {
31 public:
32 explicit ContextDeadException (const detail::DeadObjectInfo& info);
33 };
34
35 namespace detail
36 {
37 template<typename T>
38 auto Awaiter (T&& obj)
39 {
40 if constexpr (requires { operator co_await (std::forward<T> (obj)); })
41 return operator co_await (std::forward<T> (obj));
42 else if constexpr (requires { std::forward<T> (obj).operator co_await (); })
43 return std::forward<T> (obj).operator co_await ();
44 else
45 return std::forward<T> (obj);
46 }
47
48 UTIL_THREADS_API void CheckDeadObjects (const QVector<DeadObjectInfo>&);
49
50 template<typename Promise, typename OrigAwaiter>
52 {
53 Promise& Promise_;
54 OrigAwaiter Orig_;
55
57 {
58 return Orig_.await_ready ();
59 }
60
61 decltype (auto) await_suspend (auto handle)
62 {
63 return Orig_.await_suspend (handle);
64 }
65
66 decltype (auto) await_resume ()
67 {
68 CheckDeadObjects (Promise_.DeadObjects_);
69 return Orig_.await_resume ();
70 }
71 };
72 }
73
74 template<typename>
76 {
78
79 QVector<QMetaObject::Connection> ContextConnections_;
80 QVector<detail::DeadObjectInfo> DeadObjects_;
81
82 void FinalSuspend () noexcept
83 {
84 for (auto conn : ContextConnections_)
85 QObject::disconnect (conn);
86 }
87
88 template<typename T>
89 auto await_transform (T&& awaitable)
90 {
91 return detail::AwaitableWrapper { *this, detail::Awaiter (std::forward<T> (awaitable)) };
92 }
93 };
94
96 {
97 QObject& Context_;
98
99 explicit AddContextObject (QObject& context)
100 : Context_ { context }
101 {
102 }
103
104 bool await_ready () const noexcept
105 {
106 return false;
107 }
108
109 template<typename Promise>
110 requires requires { typename Promise::HasContextExtensions; }
111 bool await_suspend (std::coroutine_handle<Promise> handle)
112 {
113 auto conn = QObject::connect (&Context_,
114 &QObject::destroyed,
115 [handle] (QObject *object)
116 {
117 auto className = object->metaObject ()->className ();
118 handle.promise ().DeadObjects_.push_back ({ className, object->objectName () });
119 handle.resume ();
120 });
121 handle.promise ().ContextConnections_.push_back (conn);
122 return false;
123 }
124
126 {
127 }
128 };
129}
ContextDeadException(const detail::DeadObjectInfo &info)
Definition context.cpp:25
auto Awaiter(T &&obj)
Definition context.h:38
void CheckDeadObjects(const QVector< DeadObjectInfo > &deadObjects)
Definition context.cpp:32
AddContextObject(QObject &context)
Definition context.h:99
bool await_ready() const noexcept
Definition context.h:104
bool await_suspend(std::coroutine_handle< Promise > handle)
Definition context.h:111
auto await_transform(T &&awaitable)
Definition context.h:89
void FinalSuspend() noexcept
Definition context.h:82
QVector< detail::DeadObjectInfo > DeadObjects_
Definition context.h:80
QVector< QMetaObject::Connection > ContextConnections_
Definition context.h:79
decltype(auto) await_suspend(auto handle)
Definition context.h:61
decltype(auto) await_resume()
Definition context.h:66
#define UTIL_THREADS_API