From b17284ee7d674416e0d11f1699f73fcc606262d4 Mon Sep 17 00:00:00 2001 From: Linus Jahn Date: Tue, 16 Aug 2022 21:00:15 +0200 Subject: Introduce QXmppTask & QXmppPromise MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #502. Co-authored-by: Jonah BrĂ¼chert --- src/base/QXmppPromise.h | 103 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 src/base/QXmppPromise.h (limited to 'src/base/QXmppPromise.h') 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 +// SPDX-FileCopyrightText: 2022 Jonah BrĂ¼chert +// +// 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 +class QXmppPromise +{ +public: + template> * = nullptr> + QXmppPromise() + : d(QXmpp::Private::TaskPrivate(nullptr)) + { + } + + template> * = nullptr> + QXmppPromise() + : d(QXmpp::Private::TaskPrivate([](void *r) { delete static_cast(r); })) + { + } + + /// + /// Report that the asynchronous operation has finished, and call the connected handler of the + /// QXmppTask belonging to this promise. + /// + /// \param value The result of the asynchronous computation + /// +#ifdef QXMPP_DOC + void reportFinished(T &&value) +#else + template && std::is_base_of_v> * = 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 && std::is_constructible_v && !std::is_base_of_v> * = 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> * = 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 task() + { + return QXmppTask(d); + } + +private: + QXmpp::Private::TaskPrivate d; +}; + +#endif // QXMPPPROMISE_H -- cgit v1.2.3