diff options
| author | Linus Jahn <lnj@kaidan.im> | 2022-08-16 21:00:15 +0200 |
|---|---|---|
| committer | Linus Jahn <lnj@kaidan.im> | 2023-01-03 22:05:54 +0100 |
| commit | b17284ee7d674416e0d11f1699f73fcc606262d4 (patch) | |
| tree | 86597f2bc2a1ed2d257e0cbf8e7de1ca54080c08 /src/base/QXmppPromise.h | |
| parent | 3271c6642439d4d3c0d8c634e2b3f4cf17b908a0 (diff) | |
| download | qxmpp-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.h | 103 |
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 |
