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 }