cutelyst  4.8.0
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
CoroContext.h
1 /*
2  * SPDX-FileCopyrightText: (C) 2020-2023 Daniel Nicoletti <dantti12@gmail.com>
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 #pragma once
6 
7 #include <Cutelyst/async.h>
8 #include <coroutine>
9 #include <functional>
10 #include <memory>
11 
12 #include <QObject>
13 
14 namespace Cutelyst {
15 
31 {
32 public:
33  struct promise_type {
34  std::coroutine_handle<promise_type> handle;
35  std::vector<QMetaObject::Connection> connections;
36 
37  void clean()
38  {
39  for (auto &conn : connections) {
40  QObject::disconnect(conn);
41  }
42  connections.clear();
43  }
44 
45  void return_void() noexcept {}
46 
47  CoroContext get_return_object()
48  {
49  handle = std::coroutine_handle<promise_type>::from_promise(*this);
50  return {};
51  }
52 
53  std::suspend_never initial_suspend() const noexcept { return {}; }
54  std::suspend_never final_suspend() noexcept { return {}; }
55  void unhandled_exception() {}
56 
57  bool await_ready() const noexcept { return false; }
58 
59  std::suspend_never yield_value(QObject *obj)
60  {
61  auto conn = QObject::connect(obj, &QObject::destroyed, [this] {
62  clean();
63 
64  if (handle) {
65  handle.destroy();
66  }
67  });
68  connections.emplace_back(std::move(conn));
69  return {};
70  }
71 
72  std::suspend_never yield_value(Cutelyst::Context *obj)
73  {
74  // Automatically delay replies
75  // async cannot be used in coroutine body
76  // else we get a double free when the coroutine
77  // body ends and Cutelyst::Engine deletes the Context*
78  // resulting in destroyed signal being emitted and
79  // and coroutine dtor already on the stack to be called
80  ASync a(obj);
81 
82  auto conn = QObject::connect(obj, &QObject::destroyed, [this, a] {
83  clean();
84 
85  if (handle) {
86  handle.destroy();
87  }
88  });
89  connections.emplace_back(std::move(conn));
90  return {};
91  }
92  void await_suspend(std::coroutine_handle<> h) noexcept {}
93  void await_resume() const noexcept {}
94 
95  ~promise_type() { clean(); }
96  };
97 };
98 
99 } // namespace Cutelyst
The CoroContext class.
Definition: CoroContext.h:30
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
Helper class for asynchronous processing.
Definition: async.h:15
The Cutelyst Context.
Definition: context.h:42
The Cutelyst namespace holds all public Cutelyst API.
bool disconnect(const QMetaObject::Connection &connection)
void destroyed(QObject *obj)