LeechCraft 0.6.70-19214-g121e5318a7
Modular cross-platform feature rich live environment.
Loading...
Searching...
No Matches
corocontext.cpp
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#include "corocontext.h"
10#include <unordered_map>
11#include <QThread>
12#include <QtDebug>
13#include "context.h"
14#include "task.h"
15
16namespace LC::Util
17{
19 : std::runtime_error { "coroutine's context " + name.toStdString () + " died" }
20 {
21 }
22
23 CoroContext::CoroContext (const QString& name)
24 : Name_ { name }
25 {
26 }
27
28 CoroContext::CoroContext (const QObject& obj)
29 : CoroContext { obj.objectName ().isEmpty () ? obj.metaObject ()->className () : obj.objectName () }
30 {
31 }
32
34 {
35 for (const auto [_, base, _] : Coros_)
37 qFatal () << "destroying the context" << Name_ << "while its child coro is running; "
38 << "defer the destruction with `QObject::deleteLater()` or a timer";
39
40 while (!Coros_.empty ())
41 {
42 const auto [handle, base, promise] = Coros_.front ();
43 Coros_.pop_front ();
44
45 std::erase_if (promise->Contexts_, [this] (const Registration& reg) { return reg.Ctx_ == this; });
46 promise->DeadContexts_ << Name_;
47
48 if (!handle.done ())
49 handle.resume ();
50 }
51 }
52
54 {
55 if (obj.thread () != QThread::currentThread ())
56 {
57 using namespace std::string_literals;
58 const auto& msg = "binding to a QObject "s + obj.metaObject ()->className () +
59 " [" + obj.objectName ().toStdString () + "] from a different thread";
60 throw std::runtime_error { msg };
61 }
62
63 thread_local std::unordered_map<QObject*, std::unique_ptr<CoroContext>> contexts;
64 auto& ctx = contexts [&obj];
65 if (!ctx)
66 {
67 ctx = std::make_unique<CoroContext> (obj);
68 QObject::connect (&obj,
69 &QObject::destroyed,
70 [&obj]
71 {
72 if (!contexts.erase (&obj))
73 qCritical () << "could not find" << &obj << "in the contexts map — threading messed up?";
74 });
75 }
76 return *ctx;
77 }
78}
ContextDeadException(const QString &)
static CoroContext & Of(QObject &obj)
Returns the context tied to the lifetime of obj.