aboutsummaryrefslogtreecommitdiff
path: root/src/base/QXmppPromise.h
diff options
context:
space:
mode:
authorLinus Jahn <lnj@kaidan.im>2022-08-16 21:00:15 +0200
committerLinus Jahn <lnj@kaidan.im>2023-01-03 22:05:54 +0100
commitb17284ee7d674416e0d11f1699f73fcc606262d4 (patch)
tree86597f2bc2a1ed2d257e0cbf8e7de1ca54080c08 /src/base/QXmppPromise.h
parent3271c6642439d4d3c0d8c634e2b3f4cf17b908a0 (diff)
downloadqxmpp-b17284ee7d674416e0d11f1699f73fcc606262d4.tar.gz
Introduce QXmppTask & QXmppPromise
Closes #502. Co-authored-by: Jonah BrĂ¼chert <jbb@kaidan.im>
Diffstat (limited to 'src/base/QXmppPromise.h')
-rw-r--r--src/base/QXmppPromise.h103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/base/QXmppPromise.h b/src/base/QXmppPromise.h
new file mode 100644
index 00000000..09bc5bcb
--- /dev/null
+++ b/src/base/QXmppPromise.h
@@ -0,0 +1,103 @@
+// SPDX-FileCopyrightText: 2022 Linus Jahn <lnj@kaidan.im>
+// SPDX-FileCopyrightText: 2022 Jonah BrĂ¼chert <jbb@kaidan.im>
+//
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+#ifndef QXMPPPROMISE_H
+#define QXMPPPROMISE_H
+
+#include "QXmppTask.h"
+
+///
+/// \brief Create and update QXmppTask objects to communicate results of asynchronous operations.
+///
+/// Unlike QFuture, this is not thread-safe. This avoids the need to do mutex locking at every
+/// access though.
+///
+/// \ingroup Core classes
+///
+/// \since QXmpp 1.5
+///
+template<typename T>
+class QXmppPromise
+{
+public:
+ template<typename U = T, std::enable_if_t<std::is_void_v<U>> * = nullptr>
+ QXmppPromise()
+ : d(QXmpp::Private::TaskPrivate(nullptr))
+ {
+ }
+
+ template<typename U = T, std::enable_if_t<!std::is_void_v<U>> * = nullptr>
+ QXmppPromise()
+ : d(QXmpp::Private::TaskPrivate([](void *r) { delete static_cast<T *>(r); }))
+ {
+ }
+
+ ///
+ /// Report that the asynchronous operation has finished, and call the connected handler of the
+ /// QXmppTask<T> belonging to this promise.
+ ///
+ /// \param value The result of the asynchronous computation
+ ///
+#ifdef QXMPP_DOC
+ void reportFinished(T &&value)
+#else
+ template<typename U, std::enable_if_t<!std::is_void_v<T> && std::is_base_of_v<T, U>> * = nullptr>
+ void finish(U &&value)
+#endif
+ {
+ Q_ASSERT(!d.isFinished());
+ d.setFinished(true);
+ if (d.continuation()) {
+ if (d.isContextAlive()) {
+ d.invokeContinuation(&value);
+ }
+ } else {
+ d.setResult(new U(std::move(value)));
+ }
+ }
+
+ /// \cond
+ template<typename U, std::enable_if_t<!std::is_void_v<T> && std::is_constructible_v<T, U> && !std::is_base_of_v<T, U>> * = nullptr>
+ void finish(U &&value)
+ {
+ Q_ASSERT(!d.isFinished());
+ d.setFinished(true);
+ if (d.continuation()) {
+ if (d.isContextAlive()) {
+ T convertedValue { std::move(value) };
+ d.invokeContinuation(&convertedValue);
+ }
+ } else {
+ d.setResult(new T(std::move(value)));
+ }
+ }
+
+ template<typename U = T, std::enable_if_t<std::is_void_v<U>> * = nullptr>
+ void finish()
+ {
+ Q_ASSERT(!d.isFinished());
+ d.setFinished(true);
+ if (d.continuation()) {
+ if (d.isContextAlive()) {
+ d.invokeContinuation(nullptr);
+ }
+ }
+ }
+ /// \endcond
+
+ ///
+ /// Obtain a handle to this promise that allows to obtain the value that will be produced
+ /// asynchronously.
+ ///
+ QXmppTask<T> task()
+ {
+ return QXmppTask<T>(d);
+ }
+
+private:
+ QXmpp::Private::TaskPrivate d;
+};
+
+#endif // QXMPPPROMISE_H