28 #include <QtCore/QObject>
29 #include <QtCore/QThread>
30 #include <QtCore/QVariantMap>
32 #include "ReadWriteLockable.h"
35 class MiniPromise :
public QObject,
public std::enable_shared_from_this<MiniPromise>,
public ReadWriteLockable {
37 Q_PROPERTY(QString state READ getStateString)
38 Q_PROPERTY(QString error READ getError)
39 Q_PROPERTY(QVariantMap result READ getResult)
41 using HandlerFunction = std::function<void(QString error, QVariantMap result)>;
42 using SuccessFunction = std::function<void(QVariantMap result)>;
43 using ErrorFunction = std::function<void(QString error)>;
44 using HandlerFunctions = QVector<HandlerFunction>;
45 using Promise = std::shared_ptr<MiniPromise>;
47 static int metaTypeID;
50 MiniPromise(
const QString debugName) { setObjectName(debugName); }
53 if (getStateString() ==
"pending") {
54 qWarning() <<
"MiniPromise::~MiniPromise -- destroying pending promise:" << objectName() << _error << _result <<
"handlers:" << getPendingHandlerCount();
57 Promise
self() {
return shared_from_this(); }
59 Q_INVOKABLE
void executeOnPromiseThread(std::function<
void()>
function, MiniPromise::Promise root =
nullptr) {
60 if (QThread::currentThread() != thread()) {
61 QMetaObject::invokeMethod(
62 this,
"executeOnPromiseThread", Qt::QueuedConnection,
63 Q_ARG(std::function<
void()>,
function),
64 Q_ARG(MiniPromise::Promise,
self()));
72 Promise mixin(
const QVariantMap& source) {
74 for (
const auto& key : source.keys()) {
75 if (!_result.contains(key)) {
76 _result[key] = source[key];
83 Promise assignResult(
const QVariantMap& source) {
85 for (
const auto& key : source.keys()) {
86 _result[key] = source[key];
93 Promise ready(HandlerFunction always) {
return finally(always); }
94 Promise
finally(HandlerFunction always) {
95 if (!_rejected && !_resolved) {
100 executeOnPromiseThread([&]{
101 always(getError(), getResult());
106 Promise fail(ErrorFunction errorOnly) {
107 return fail([errorOnly](QString error, QVariantMap result) {
112 Promise fail(HandlerFunction failFunc) {
115 _onreject << failFunc;
118 executeOnPromiseThread([&]{
119 failFunc(getError(), getResult());
125 Promise then(SuccessFunction successOnly) {
126 return then([successOnly](QString error, QVariantMap result) {
130 Promise then(HandlerFunction successFunc) {
133 _onresolve << successFunc;
136 executeOnPromiseThread([&]{
137 successFunc(getError(), getResult());
144 Promise then(SuccessFunction successOnly, ErrorFunction errorOnly) {
156 Promise ready(Promise next) {
return finally(next); }
157 Promise
finally(Promise next) {
158 return finally([next](QString error, QVariantMap result) {
159 next->handle(error, result);
162 Promise fail(Promise next) {
163 return fail([next](QString error, QVariantMap result) {
164 next->reject(error, result);
167 Promise then(Promise next) {
168 return then([next](QString error, QVariantMap result) {
169 next->resolve(error, result);
176 Promise handle(QString error,
const QVariantMap& result) {
177 if (error.isEmpty()) {
178 resolve(error, result);
180 reject(error, result);
185 Promise resolve(QVariantMap result) {
186 return resolve(QString(), result);
188 Promise resolve(QString error,
const QVariantMap& result) {
189 setState(
true, error, result);
191 executeOnPromiseThread([&]{
192 const QString localError{ getError() };
193 const QVariantMap localResult{ getResult() };
194 HandlerFunctions resolveHandlers;
195 HandlerFunctions finallyHandlers;
197 resolveHandlers = _onresolve;
198 finallyHandlers = _onfinally;
200 for (
const auto& onresolve : resolveHandlers) {
201 onresolve(localError, localResult);
203 for (
const auto& onfinally : finallyHandlers) {
204 onfinally(localError, localResult);
210 Promise reject(QString error) {
211 return reject(error, QVariantMap());
213 Promise reject(QString error,
const QVariantMap& result) {
214 setState(
false, error, result);
216 executeOnPromiseThread([&]{
217 const QString localError{ getError() };
218 const QVariantMap localResult{ getResult() };
219 HandlerFunctions rejectHandlers;
220 HandlerFunctions finallyHandlers;
222 rejectHandlers = _onreject;
223 finallyHandlers = _onfinally;
225 for (
const auto& onreject : rejectHandlers) {
226 onreject(localError, localResult);
228 for (
const auto& onfinally : finallyHandlers) {
229 onfinally(localError, localResult);
237 Promise setState(
bool resolved, QString error,
const QVariantMap& result) {
244 assignResult(result);
248 void setError(
const QString error) { withWriteLock([&]{ _error = error; }); }
249 QString getError()
const {
return resultWithReadLock<QString>([
this]() -> QString {
return _error; }); }
250 QVariantMap getResult()
const {
return resultWithReadLock<QVariantMap>([
this]() -> QVariantMap {
return _result; }); }
251 int getPendingHandlerCount()
const {
252 return resultWithReadLock<int>([
this]() ->
int {
253 return _onresolve.size() + _onreject.size() + _onfinally.size();
256 QString getStateString()
const {
257 return _rejected ?
"rejected" :
258 _resolved ?
"resolved" :
259 getPendingHandlerCount() ?
"pending" :
264 std::atomic<bool> _rejected{
false};
265 std::atomic<bool> _resolved{
false};
266 HandlerFunctions _onresolve;
267 HandlerFunctions _onreject;
268 HandlerFunctions _onfinally;
271 Q_DECLARE_METATYPE(MiniPromise::Promise)
273 inline MiniPromise::Promise makePromise(
const QString& hint = QString()) {
274 if (!QMetaType::isRegistered(qMetaTypeId<MiniPromise::Promise>())) {
275 int type = qRegisterMetaType<MiniPromise::Promise>();
276 qDebug() <<
"makePromise -- registered MetaType<MiniPromise::Promise>:" << type;
278 return std::make_shared<MiniPromise>(hint);