QXmpp Version: 1.11.3
Loading...
Searching...
No Matches
Async.h
1// SPDX-FileCopyrightText: 2021 Linus Jahn <lnj@kaidan.im>
2//
3// SPDX-License-Identifier: LGPL-2.1-or-later
4
5#ifndef ASYNC_H
6#define ASYNC_H
7
8#include "QXmppAsync_p.h"
9#include "QXmppGlobal.h"
10
11#include <memory>
12#include <variant>
13
14#include <QFutureWatcher>
15
16namespace QXmpp::Private {
17
18template<typename Function>
19auto later(QObject *context, Function function)
20{
21 QMetaObject::invokeMethod(context, std::forward<Function>(function), Qt::QueuedConnection);
22}
23
24#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
25template<typename T>
26QFuture<T> makeReadyFuture(T &&value) { return QtFuture::makeReadyValueFuture(std::move(value)); }
27#elif QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
28using QtFuture::makeReadyFuture;
29#else
30template<typename T>
31QFuture<T> makeReadyFuture(T &&value)
32{
33 QFutureInterface<T> interface(QFutureInterfaceBase::Started);
34 interface.reportResult(std::move(value));
35 interface.reportFinished();
36 return interface.future();
37}
38
39inline QFuture<void> makeReadyFuture()
40{
41 using State = QFutureInterfaceBase::State;
42 return QFutureInterface<void>(State(State::Started | State::Finished)).future();
43}
44#endif
45
46template<typename T, typename Handler>
47void await(const QFuture<T> &future, QObject *context, Handler handler)
48{
49 auto *watcher = new QFutureWatcher<T>(context);
50 QObject::connect(watcher, &QFutureWatcherBase::finished,
51 context, [watcher, handler = std::move(handler)]() mutable {
52 handler(watcher->result());
53 watcher->deleteLater();
54 });
55 watcher->setFuture(future);
56}
57
58template<typename Handler>
59void await(const QFuture<void> &future, QObject *context, Handler handler)
60{
61 auto *watcher = new QFutureWatcher<void>(context);
62 QObject::connect(watcher, &QFutureWatcherBase::finished,
63 context, [watcher, handler = std::move(handler)]() mutable {
64 handler();
65 watcher->deleteLater();
66 });
67 watcher->setFuture(future);
68}
69
70template<typename T, typename Err, typename Function>
71auto mapSuccess(std::variant<T, Err> var, Function lambda)
72{
73 using MapResult = std::decay_t<decltype(lambda({}))>;
74 using MappedVariant = std::variant<MapResult, Err>;
75 return std::visit(overloaded {
76 [lambda = std::move(lambda)](T val) -> MappedVariant {
77 return lambda(std::move(val));
78 },
79 [](Err err) -> MappedVariant {
80 return err;
81 } },
82 std::move(var));
83}
84
85template<typename T, typename Err>
86auto mapToSuccess(std::variant<T, Err> var)
87{
88 return mapSuccess(std::move(var), [](T) {
89 return Success();
90 });
91}
92
93template<typename T, typename Err>
94auto chainSuccess(QXmppTask<std::variant<T, Err>> &&source, QObject *context) -> QXmppTask<std::variant<QXmpp::Success, QXmppError>>
95{
96 return chain<std::variant<QXmpp::Success, QXmppError>>(std::move(source), context, mapToSuccess<T, Err>);
97}
98
99template<typename Input, typename Converter>
100auto chainMapSuccess(QXmppTask<Input> &&source, QObject *context, Converter convert)
101{
102 return chain<std::variant<decltype(convert({})), QXmppError>>(std::move(source), context, [convert](Input &&input) {
103 return mapSuccess(std::move(input), convert);
104 });
105}
106
107} // namespace QXmpp::Private
108
109#endif // ASYNC_H
Definition QXmppTask.h:46
Definition QXmppError.h:17