File indexing completed on 2024-12-08 12:44:38

0001 /*
0002     SPDX-FileCopyrightText: 2014 Daniel Vrátil <dvratil@redhat.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "future.h"
0008 #include "async.h"
0009 
0010 using namespace KAsync;
0011 
0012 QDebug &operator<<(QDebug &dbg, const Error &error)
0013 {
0014     dbg << "Error: " << error.errorCode << "Msg: " << error.errorMessage;
0015     return dbg;
0016 }
0017 
0018 FutureBase::PrivateBase::PrivateBase(const Private::ExecutionPtr &execution)
0019     : finished(false)
0020     , mExecution(execution)
0021 {
0022 }
0023 
0024 FutureBase::PrivateBase::~PrivateBase()
0025 {
0026     Private::ExecutionPtr executionPtr = mExecution.toStrongRef();
0027     if (executionPtr) {
0028         executionPtr->releaseFuture();
0029         releaseExecution();
0030     }
0031 }
0032 
0033 void FutureBase::PrivateBase::releaseExecution()
0034 {
0035     mExecution.clear();
0036 }
0037 
0038 
0039 
0040 FutureBase::FutureBase()
0041     : d(nullptr)
0042 {
0043 }
0044 
0045 FutureBase::FutureBase(FutureBase::PrivateBase *dd)
0046     : d(dd)
0047 {
0048 }
0049 
0050 FutureBase::FutureBase(const KAsync::FutureBase &other)
0051     : d(other.d)
0052 {
0053 }
0054 
0055 FutureBase::~FutureBase()
0056 {
0057 }
0058 
0059 void FutureBase::releaseExecution()
0060 {
0061     d->releaseExecution();
0062 }
0063 
0064 void FutureBase::setFinished()
0065 {
0066     if (isFinished()) {
0067         return;
0068     }
0069     d->finished = true;
0070     //TODO this could directly call the next continuation with the value, and thus avoid unnecessary copying.
0071     for (auto watcher : d->watchers) {
0072         if (watcher) {
0073             watcher->futureReadyCallback();
0074         }
0075     }
0076 }
0077 
0078 bool FutureBase::isFinished() const
0079 {
0080     return d->finished;
0081 }
0082 
0083 void FutureBase::setError(int code, const QString &message)
0084 {
0085     d->errors.clear();
0086     addError(Error(code, message));
0087     setFinished();
0088 }
0089 
0090 void FutureBase::setError(const Error &error)
0091 {
0092     d->errors.clear();
0093     addError(error);
0094     setFinished();
0095 }
0096 
0097 void FutureBase::addError(const Error &error)
0098 {
0099     d->errors << error;
0100 }
0101 
0102 void FutureBase::clearErrors()
0103 {
0104     d->errors.clear();
0105 }
0106 
0107 bool FutureBase::hasError() const
0108 {
0109     return !d->errors.isEmpty();
0110 }
0111 
0112 int FutureBase::errorCode() const
0113 {
0114     if (d->errors.isEmpty()) {
0115         return 0;
0116     }
0117     return d->errors.first().errorCode;
0118 }
0119 
0120 QString FutureBase::errorMessage() const
0121 {
0122     if (d->errors.isEmpty()) {
0123         return QString();
0124     }
0125     return d->errors.first().errorMessage;
0126 }
0127 
0128 QVector<Error> FutureBase::errors() const
0129 {
0130     return d->errors;
0131 }
0132 
0133 void FutureBase::setProgress(int processed, int total)
0134 {
0135     setProgress((qreal) processed / total);
0136 }
0137 
0138 void FutureBase::setProgress(qreal progress)
0139 {
0140     for (auto watcher : d->watchers) {
0141         if (watcher) {
0142             watcher->futureProgressCallback(progress);
0143         }
0144     }
0145 }
0146 
0147 
0148 
0149 void FutureBase::addWatcher(FutureWatcherBase* watcher)
0150 {
0151     d->watchers.append(QPointer<FutureWatcherBase>(watcher));
0152 }
0153 
0154 
0155 
0156 
0157 
0158 FutureWatcherBase::FutureWatcherBase(QObject *parent)
0159     : QObject(parent)
0160     , d(new FutureWatcherBase::Private)
0161 {
0162 }
0163 
0164 FutureWatcherBase::~FutureWatcherBase()
0165 {
0166     delete d;
0167 }
0168 
0169 void FutureWatcherBase::futureReadyCallback()
0170 {
0171     Q_EMIT futureReady();
0172 }
0173 
0174 void FutureWatcherBase::futureProgressCallback(qreal progress)
0175 {
0176     Q_EMIT futureProgress(progress);
0177 }
0178 
0179 void FutureWatcherBase::setFutureImpl(const FutureBase &future)
0180 {
0181     d->future = future;
0182     d->future.addWatcher(this);
0183     if (future.isFinished()) {
0184         futureReadyCallback();
0185     }
0186 }