LeechCraft  0.6.70-18450-gabe19ee3b0
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  decltype (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 
56  bool await_ready ()
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  struct [[nodiscard]] AddContextObject
75  {
76  QObject& Context_;
77 
78  explicit AddContextObject (QObject& context)
79  : Context_ { context }
80  {
81  }
82 
83  bool await_ready () const noexcept
84  {
85  return false;
86  }
87 
88  template<typename Promise>
89  requires requires { typename Promise::HasContextExtensions; }
90  bool await_suspend (std::coroutine_handle<Promise> handle)
91  {
92  auto conn = QObject::connect (&Context_,
93  &QObject::destroyed,
94  [handle] (QObject *object)
95  {
96  auto className = object->metaObject ()->className ();
97  handle.promise ().DeadObjects_.push_back ({ className, object->objectName () });
98  handle.resume ();
99  });
100  handle.promise ().ContextConnections_.push_back (conn);
101  return false;
102  }
103 
104  void await_resume ()
105  {
106  }
107  };
108 
109  template<typename>
111  {
112  using HasContextExtensions = void;
113 
114  QVector<QMetaObject::Connection> ContextConnections_;
115  QVector<detail::DeadObjectInfo> DeadObjects_;
116 
117  void FinalSuspend () const noexcept
118  {
119  for (const auto& conn : ContextConnections_)
120  QObject::disconnect (conn);
121  }
122 
124  {
125  return awaitable;
126  }
127 
128  template<typename T>
129  auto await_transform (T&& awaitable)
130  {
131  using OrigAwaiter = decltype (detail::Awaiter (std::forward<T> (awaitable)));
132  return detail::AwaitableWrapper<ContextExtensions, OrigAwaiter> { *this, detail::Awaiter (std::forward<T> (awaitable)) };
133  }
134  };
135 }
decltype(auto) await_suspend(auto handle)
Definition: context.h:61
QVector< QMetaObject::Connection > ContextConnections_
Definition: context.h:114
decltype(auto) Awaiter(T &&obj)
Definition: context.h:38
void CheckDeadObjects(const QVector< DeadObjectInfo > &deadObjects)
Definition: context.cpp:32
#define UTIL_THREADS_API
Definition: threadsconfig.h:16
AddContextObject(QObject &context)
Definition: context.h:78
decltype(auto) await_resume()
Definition: context.h:66
bool await_ready() const noexcept
Definition: context.h:83
requires(Tup1Size==Tup2Size) const expr auto ZipWith(Tup1 &&tup1
auto await_transform(T &&awaitable)
Definition: context.h:129
void FinalSuspend() const noexcept
Definition: context.h:117
QVector< detail::DeadObjectInfo > DeadObjects_
Definition: context.h:115
auto Tup2 &&tup2 noexcept
Definition: ctstringutils.h:68
bool await_suspend(std::coroutine_handle< Promise > handle)
Definition: context.h:90
AddContextObject await_transform(AddContextObject awaitable) const
Definition: context.h:123