Page MenuHomePhorge

D12.1732381063.diff
No OneTemporary

Size
9 KB
Referenced Files
None
Subscribers
None

D12.1732381063.diff

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -32,6 +32,7 @@
matrix-sticker.cpp
matrix-sticker-pack-list.cpp
matrix-sticker-pack-source.cpp
+ qt-promise-handler.cpp
device-mgmt/matrix-device.cpp
device-mgmt/matrix-device-list.cpp
diff --git a/src/matrix-sdk.cpp b/src/matrix-sdk.cpp
--- a/src/matrix-sdk.cpp
+++ b/src/matrix-sdk.cpp
@@ -41,6 +41,7 @@
#include "qt-job-handler.hpp"
#include "device-mgmt/matrix-device-list.hpp"
#include "matrix-sticker-pack-list.hpp"
+#include "kazv-log.hpp"
using namespace Kazv;
diff --git a/src/qt-promise-handler.hpp b/src/qt-promise-handler.hpp
--- a/src/qt-promise-handler.hpp
+++ b/src/qt-promise-handler.hpp
@@ -1,6 +1,6 @@
/*
* This file is part of kazv.
- * SPDX-FileCopyrightText: 2020-2021 Tusooa Zhu <tusooa@kazv.moe>
+ * SPDX-FileCopyrightText: 2020-2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -17,8 +17,6 @@
#include <promise-interface.hpp>
-#include "kazv-log.hpp"
-
template<class T>
class QtPromise;
@@ -45,6 +43,18 @@
}
}
+class QtPromiseSignalTrigger : public QObject
+{
+ Q_OBJECT
+public:
+ QtPromiseSignalTrigger(QObject *parent = 0);
+
+ ~QtPromiseSignalTrigger();
+
+Q_SIGNALS:
+ void finished();
+};
+
template<class T>
class QtPromise : public Kazv::AbstractPromise<QtPromiseDetail::QtPromiseHelper::PromiseType, T>
{
@@ -53,29 +63,32 @@
template<class FuncT, class PromiseT, class ResolveT>
struct WaitHelper
{
- void wait() const {
- if (p.ready()) {
- auto res = func(p.get());
- using ResT = decltype(res);
- if constexpr (Kazv::isPromise<ResT>) {
- QtPromiseDetail::post(
- executor,
- [w=WaitHelper<QtPromiseDetail::IdentityFunc, ResT, ResolveT>{
- executor,
- res,
- QtPromiseDetail::IdentityFunc{},
- resolve,
- }]() mutable {
- w.wait();
- });
- } else {
- resolve(res);
- }
+ void resolveOrWait()
+ {
+ auto res = func(p.get());
+ using ResT = decltype(res);
+ if constexpr (Kazv::isPromise<ResT>) {
+ res.then([resolve=resolve](auto val) {
+ resolve(std::move(val));
+ return std::decay_t<decltype(val)>(); // we don't care about this value
+ });
} else {
+ resolve(res);
+ }
+ }
+
+ void wait()
+ {
+ if (p.ready()) {
QtPromiseDetail::post(
executor,
- [*this]() mutable {
- wait();
+ [*this]() mutable { resolveOrWait(); }
+ );
+ } else {
+ QObject::connect(
+ p.m_signalTrigger, &QtPromiseSignalTrigger::finished,
+ executor, [*this]() mutable {
+ resolveOrWait();
}
);
}
@@ -90,28 +103,50 @@
struct ResolveHelper
{
template<class ValT>
- void operator()(ValT val) const {
+ void operator()(ValT val) const
+ {
using ResT = std::decay_t<decltype(val)>;
if constexpr (Kazv::isPromise<ResT>) {
- auto w = WaitHelper<QtPromiseDetail::IdentityFunc, ResT, ResolveHelper>{
+ QtPromiseDetail::post(
executor,
- val,
- QtPromiseDetail::IdentityFunc{},
- *this
- };
- w.wait();
+ [qtPromise=std::move(val), *this]() mutable {
+ if (qtPromise.ready()) {
+ setValue(qtPromise.get());
+ } else {
+ qtPromise.then([*this](auto val) mutable {
+ setValue(std::move(val));
+ return std::decay_t<decltype(val)>(); // we don't care about this value
+ });
+ }
+ });
} else {
- p->set_value(std::move(val));
+ QtPromiseDetail::post(
+ executor,
+ [*this, val=std::move(val)]() mutable {
+ setValue(std::move(val));
+ });
+ }
+ }
+
+ void setValue(T resolvedValue) const
+ {
+ p->set_value(std::move(resolvedValue));
+ if (signalTrigger) {
+ Q_EMIT signalTrigger->finished();
+ signalTrigger->deleteLater();
}
}
QPointer<QObject> executor;
+ QPointer<QtPromiseSignalTrigger> signalTrigger;
std::shared_ptr<std::promise<T>> p;
};
public:
QtPromise(QObject *executor, T value)
: BaseT(this)
- , m_executor(executor) {
+ , m_executor(executor)
+ , m_signalTrigger()
+ {
std::promise<T> p;
m_val = p.get_future().share();
p.set_value(std::move(value));
@@ -120,10 +155,14 @@
template<class Func>
QtPromise(QObject *executor, Func &&callback)
: BaseT(this)
- , m_executor(executor) {
+ , m_executor(executor)
+ , m_signalTrigger(new QtPromiseSignalTrigger())
+ {
auto p = std::make_shared<std::promise<T>>();
m_val = p->get_future().share();
- auto resolve = ResolveHelper{m_executor, p};
+
+ m_signalTrigger->moveToThread(m_executor->thread());
+ auto resolve = ResolveHelper{m_executor, m_signalTrigger, p};
QtPromiseDetail::post(
m_executor,
@@ -162,6 +201,7 @@
}
private:
QPointer<QObject> m_executor;
+ QPointer<QtPromiseSignalTrigger> m_signalTrigger;
std::shared_future<T> m_val;
};
diff --git a/src/qt-promise-handler.cpp b/src/qt-promise-handler.cpp
new file mode 100644
--- /dev/null
+++ b/src/qt-promise-handler.cpp
@@ -0,0 +1,15 @@
+/*
+ * This file is part of kazv.
+ * SPDX-FileCopyrightText: 2020-2023 tusooa <tusooa@kazv.moe>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <libkazv-config.hpp>
+
+#include "qt-promise-handler.hpp"
+
+QtPromiseSignalTrigger::QtPromiseSignalTrigger(QObject *parent)
+ : QObject(parent)
+{}
+
+QtPromiseSignalTrigger::~QtPromiseSignalTrigger() = default;
diff --git a/src/tests/qt-promise-handler-test.hpp b/src/tests/qt-promise-handler-test.hpp
--- a/src/tests/qt-promise-handler-test.hpp
+++ b/src/tests/qt-promise-handler-test.hpp
@@ -16,4 +16,6 @@
void testPromise();
void testTimer();
void testStop();
+ void testSingleTypePromise();
+ void testResolveToPromise();
};
diff --git a/src/tests/qt-promise-handler-test.cpp b/src/tests/qt-promise-handler-test.cpp
--- a/src/tests/qt-promise-handler-test.cpp
+++ b/src/tests/qt-promise-handler-test.cpp
@@ -11,6 +11,8 @@
#include <QTimer>
+#include "promise-interface.hpp"
+
#include "qt-promise-handler-test.hpp"
#include "qt-promise-handler.hpp"
@@ -135,4 +137,76 @@
loop.exec();
}
+void QtPromiseHandlerTest::testSingleTypePromise()
+{
+ QEventLoop loop;
+ QObject *obj = new QObject(&loop);
+ auto ph = Kazv::SingleTypePromiseInterface<int>(QtPromiseHandler(std::ref(*obj)));
+
+ std::vector<int> v;
+
+ auto p1 = ph.create([&v](auto resolve) {
+ qDebug() << "p1";
+ v.push_back(1);
+ resolve(2);
+ });
+
+ auto p2 = p1.then([&v, &ph](int val) {
+ qDebug() << "p2";
+ v.push_back(val);
+ return ph.createResolved(0)
+ .then([&ph](int) {
+ qDebug() << "within p2";
+ return ph.createResolved(3);
+ });
+ });
+
+ auto p3 = p2.then([&v, &ph](int val) {
+ qDebug() << "p3";
+ v.push_back(val);
+ return ph.createResolved(-1);
+ });
+
+ auto p4 = p3.then([](int val) {
+ qDebug() << "p4" << val;
+ [=] { QVERIFY(val == -1); }();
+ return 5;
+ });
+
+ auto p5 = p4.then([obj, &loop](int val) {
+ qDebug() << "p5" << val;
+ [=] { QVERIFY(val == 5); }();
+ obj->deleteLater();
+ loop.quit();
+ return 0;
+ });
+
+ loop.exec();
+
+ QVERIFY((v == std::vector<int>{ 1, 2, 3 }));
+}
+
+void QtPromiseHandlerTest::testResolveToPromise()
+{
+ QEventLoop loop;
+ QObject *obj = new QObject(&loop);
+ auto ph = Kazv::SingleTypePromiseInterface<int>(QtPromiseHandler(std::ref(*obj)));
+
+ auto p1 = ph.createResolveToPromise([&ph](auto resolve) {
+ qDebug() << "p1";
+ resolve(ph.createResolved(1)
+ .then([&ph](auto) {
+ return ph.createResolved(2);
+ }));
+ });
+
+ p1.then([obj, &loop](int val) {
+ [=] { QVERIFY(val == 2); }();
+ obj->deleteLater();
+ loop.quit();
+ return 0;
+ });
+ loop.exec();
+}
+
QTEST_MAIN(QtPromiseHandlerTest)

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 23, 8:57 AM (18 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39396
Default Alt Text
D12.1732381063.diff (9 KB)

Event Timeline