/* * Copyright 2014 Daniel Vrátil * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library. If not, see . */ #ifndef FUTURE_H #define FUTURE_H class QEventLoop; #include #include #include #include #include namespace Async { class FutureWatcherBase; template class FutureWatcher; namespace Private { class Execution; class ExecutorBase; typedef QSharedPointer ExecutionPtr; } // namespace Private class FutureBase { friend class Async::Private::Execution; friend class FutureWatcherBase; public: virtual ~FutureBase(); void setFinished(); bool isFinished() const; void setError(int code = 1, const QString &message = QString()); int errorCode() const; QString errorMessage() const; void setProgress(qreal progress); void setProgress(int processed, int total); protected: class PrivateBase : public QSharedData { public: PrivateBase(const Async::Private::ExecutionPtr &execution); virtual ~PrivateBase(); void releaseExecution(); bool finished; int errorCode; QString errorMessage; QVector> watchers; private: QWeakPointer mExecution; }; FutureBase(); FutureBase(FutureBase::PrivateBase *dd); FutureBase(const FutureBase &other); void addWatcher(Async::FutureWatcherBase *watcher); void releaseExecution(); protected: QExplicitlySharedDataPointer d; }; template class FutureWatcher; template class Future; template class FutureGeneric : public FutureBase { friend class FutureWatcher; public: void waitForFinished() { if (isFinished()) { return; } FutureWatcher watcher; QEventLoop eventLoop; QObject::connect(&watcher, &Async::FutureWatcher::futureReady, &eventLoop, &QEventLoop::quit); watcher.setFuture(*static_cast*>(this)); eventLoop.exec(); } protected: FutureGeneric(const Async::Private::ExecutionPtr &execution) : FutureBase(new Private(execution)) {} FutureGeneric(const FutureGeneric &other) : FutureBase(other) {} protected: class Private : public FutureBase::PrivateBase { public: Private(const Async::Private::ExecutionPtr &execution) : FutureBase::PrivateBase(execution) {} typename std::conditional::value, int /* dummy */, T>::type value; }; }; template class Future : public FutureGeneric { friend class Async::Private::ExecutorBase; template friend class Async::FutureWatcher; public: Future() : FutureGeneric(Async::Private::ExecutionPtr()) {} Future(const Future &other) : FutureGeneric(other) {} void setValue(const T &value) { static_cast::Private*>(this->d.data())->value = value; } T value() const { return static_cast::Private*>(this->d.data())->value; } protected: Future(const Async::Private::ExecutionPtr &execution) : FutureGeneric(execution) {} }; template<> class Future : public FutureGeneric { friend class Async::Private::ExecutorBase; public: Future() : FutureGeneric(Async::Private::ExecutionPtr()) {} Future(const Future &other) : FutureGeneric(other) {} protected: Future(const Async::Private::ExecutionPtr &execution) : FutureGeneric(execution) {} }; class FutureWatcherBase : public QObject { Q_OBJECT friend class FutureBase; Q_SIGNALS: void futureReady(); void futureProgress(qreal progress); protected: FutureWatcherBase(QObject *parent = nullptr); virtual ~FutureWatcherBase(); void futureReadyCallback(); void futureProgressCallback(qreal progress); void setFutureImpl(const Async::FutureBase &future); protected: class Private { public: Async::FutureBase future; }; Private * const d; private: Q_DISABLE_COPY(FutureWatcherBase); }; template class FutureWatcher : public FutureWatcherBase { friend class Async::FutureGeneric; public: FutureWatcher(QObject *parent = nullptr) : FutureWatcherBase(parent) {} ~FutureWatcher() {} void setFuture(const Async::Future &future) { setFutureImpl(*static_cast(&future)); } Async::Future future() const { return *static_cast*>(&d->future); } private: Q_DISABLE_COPY(FutureWatcher); }; } // namespace Async #endif // FUTURE_H