LeechCraft  0.6.70-16373-g319c272718
Modular cross-platform feature rich live environment.
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 
18 namespace 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 (obj); })
41  return operator co_await (obj);
42  else if constexpr (requires { obj.operator co_await (); })
43  return obj.operator co_await ();
44  else
45  return obj;
46  }
47 
48  UTIL_THREADS_API void CheckDeadObjects (const QVector<DeadObjectInfo>&);
49 
50  template<typename Promise, typename T>
52  {
53  Promise& Promise_;
54  T Orig_;
55 
56  bool await_ready ()
57  {
58  return Awaiter (Orig_).await_ready ();
59  }
60 
61  decltype (auto) await_suspend (auto handle)
62  {
63  return Awaiter (Orig_).await_suspend (handle);
64  }
65 
66  decltype (auto) await_resume ()
67  {
68  CheckDeadObjects (Promise_.DeadObjects_);
69  return Awaiter (Orig_).await_resume ();
70  }
71  };
72  }
73 
74  template<typename>
76  {
77  using HasContextExtensions = void;
78 
79  QVector<QMetaObject::Connection> ContextConnections_;
80  QVector<detail::DeadObjectInfo> DeadObjects_;
81 
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<ContextExtensions, T> { *this, 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  });
120  handle.promise ().ContextConnections_.push_back (conn);
121  return false;
122  }
123 
124  void await_resume ()
125  {
126  }
127  };
128 }
QVector< QMetaObject::Connection > ContextConnections_
Definition: context.h:79
void FinalSuspend() noexcept
Definition: context.h:82
void CheckDeadObjects(const QVector< DeadObjectInfo > &deadObjects)
Definition: context.cpp:32
#define UTIL_THREADS_API
Definition: threadsconfig.h:16
AddContextObject(QObject &context)
Definition: context.h:99
auto Awaiter(T &obj)
Definition: context.h:38
bool await_ready() const noexcept
Definition: context.h:104
decltype(auto) await_resume()
Definition: context.h:66
decltype(auto) await_suspend(auto handle)
Definition: context.h:61
requires(Tup1Size==Tup2Size) const expr auto ZipWith(Tup1 &&tup1
auto await_transform(T &&awaitable)
Definition: context.h:89
QVector< detail::DeadObjectInfo > DeadObjects_
Definition: context.h:80
auto Tup2 &&tup2 noexcept
Definition: ctstringutils.h:41
bool await_suspend(std::coroutine_handle< Promise > handle)
Definition: context.h:111