Projects
Kube:Winterfell
kasync
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 3
View file
kasync-4.99.0.tar.gz/autotests/CMakeLists.txt
Changed
@@ -5,9 +5,9 @@ LINK_LIBRARIES KF5Async Qt5::Test ) -if (WITH_KJOB) - ecm_add_test(kjobtest.cpp testkjob.cpp - TEST_NAME kjobtest - LINK_LIBRARIES KF5Async Qt5::Test KF5::CoreAddons - ) -endif() +# if (WITH_KJOB) +# ecm_add_test(kjobtest.cpp testkjob.cpp +# TEST_NAME kjobtest +# LINK_LIBRARIES KF5Async Qt5::Test KF5::CoreAddons +# ) +# endif()
View file
kasync-4.99.0.tar.gz/autotests/asynctest.cpp
Changed
@@ -32,6 +32,18 @@ #include <functional> +#define COMPARERET(actual, expected, retval) \ +do {\ + if (!QTest::qCompare(actual, expected, #actual, #expected, __FILE__, __LINE__))\ + return retval;\ +} while (0) + +#define VERIFYRET(statement, retval) \ +do {\ + if (!QTest::qVerify((statement), #statement, "", __FILE__, __LINE__))\ + return retval;\ +} while (0) + class AsyncTest : public QObject { Q_OBJECT @@ -45,53 +57,18 @@ private Q_SLOTS: void testSyncPromises(); + void testErrorHandling(); + void testContext(); + void testDoWhile(); void testAsyncPromises(); - void testAsyncPromises2(); void testNestedAsync(); - void testNestedJob_data(); - void testNestedJob(); void testVoidNestedJob(); - void testImplicitConversion(); - void testStartValue(); - - void testAsyncThen(); - void testAsyncThenClassArgument(); - void testSyncThen(); - void testJoinedThen(); - void testVoidThen(); - void testMemberThen(); - void testSyncMemberThen(); - void testSyncVoidMemberThen(); - void testAsyncEach(); - void testSyncEach(); - void testNestedEach(); - void testJoinedEach(); - void testVoidEachThen(); - void testAsyncVoidEachThen(); - - void testAsyncReduce(); - void testSyncReduce(); - void testJoinedReduce(); - void testVoidReduce(); - - void testProgressReporting(); - void testErrorHandler(); - void testErrorPropagation(); - void testErrorHandlerAsync(); - void testErrorPropagationAsync(); - void testNestedErrorPropagation(); - - void testChainingRunningJob(); - void testChainingFinishedJob(); - - void testLifetimeWithoutHandle(); - void testLifetimeWithHandle(); - - void testErrorTask_data(); - void testErrorTask(); + void testAsyncSerialEach(); void benchmarkSyncThenExecutor(); + void benchmarkFutureThenExecutor(); + void benchmarkThenExecutor(); private: template<typename T> @@ -190,58 +167,342 @@ void AsyncTest::testSyncPromises() { - auto baseJob = KAsync::start<int>( - [](KAsync::Future<int> &f) { - f.setValue(42); - f.setFinished(); - }) - .then<QString, int>( - [](int v, KAsync::Future<QString> &f) { - f.setValue(QLatin1String("Result is ") + QString::number(v)); - f.setFinished(); - }); + { + auto future = KAsync::syncStart<int>( + []() { + return 42; + }).exec(); + QVERIFY(future.isFinished()); + QCOMPARE(future.value(), 42); + } + + { + auto future = KAsync::start<int>( + [](KAsync::Future<int> &f) { + f.setResult(42); + }).exec(); + QVERIFY(future.isFinished()); + QCOMPARE(future.value(), 42); + } + + //Sync start + { + auto future = KAsync::start<int>([] { + return KAsync::value<int>(42); + }).exec(); + QVERIFY(future.isFinished()); + QCOMPARE(future.value(), 42); + } - auto job = baseJob.then<QString, QString>( - [](const QString &v, KAsync::Future<QString> &f) { - f.setValue(v.toUpper()); - f.setFinished(); + //Sync start + { + bool called = false; + auto future = KAsync::start<void>( + [&called] { + called = true; + return KAsync::null<void>(); + }).exec(); + QVERIFY(future.isFinished()); + QVERIFY(called); + } + //void + { + auto future = KAsync::start<void>( + []() { + return KAsync::null<void>(); + }).exec(); + QVERIFY(future.isFinished()); + } + + //value + { + auto future = KAsync::value<int>(42).exec(); + QVERIFY(future.isFinished()); + QCOMPARE(future.value(), 42); + } + + //Sync then + { + auto job = KAsync::value<int>(42); + auto future = job.then<int, int>([](int value) { + return KAsync::value<int>(value); + }).exec(); + QVERIFY(future.isFinished()); + QCOMPARE(future.value(), 42); + } + + //Job then + { + auto job = KAsync::value<int>(42); + auto future = job.then<QString, int>([](int value) { + return KAsync::value<QString>(QString::number(value)); + }).exec(); + QVERIFY(future.isFinished()); + QCOMPARE(future.value(), QString::number(42)); + } + + //void Job then + { + bool continuationCalled = false; + auto job = KAsync::null<void>(); + auto future = job.then<void>([&continuationCalled] { + return KAsync::start<void>([&continuationCalled] { + continuationCalled = true; + return KAsync::null<void>(); + }); + }).exec(); + QVERIFY(future.isFinished()); + QVERIFY(continuationCalled); + } + + //Nested job then + { + auto job = KAsync::value<int>(42); + auto future = job.then<QString, int>( + KAsync::start<QString, int>([](int i) { + return KAsync::value<QString>(QString::number(i)); + }) + ).exec(); + QVERIFY(future.isFinished()); + QCOMPARE(future.value(), QString::number(42)); + } + + //Convert to void + { + KAsync::Job<void> job = KAsync::start<int>(
View file
kasync-4.99.0.tar.gz/doc/api/Doxyfile.local
Changed
@@ -1,3 +1,4 @@ +PROJECT_NAME = KASync BUILTIN_STL_SUPPORT = YES EXTRACT_ALL = NO EXTRACT_PRIVATE = NO @@ -5,5 +6,6 @@ INLINE_INFO = NO SORT_MEMBER_DOCS = YES FILE_PATTERNS = *.h +RECURSIVE = YES PREDEFINED = ONLY_DOXYGEN \ KASYNC_EXPORT
View file
kasync-4.99.0.tar.gz/src/async.cpp
Changed
@@ -1,5 +1,6 @@ /* * Copyright 2014 Daniel Vrátil <dvratil@redhat.com> + * Copyright 2016 Christian Mollekopf <mollekopf@kolabsystems.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as @@ -27,8 +28,7 @@ Private::Execution::Execution(const Private::ExecutorBasePtr &executor) : executor(executor) , resultBase(nullptr) - , isRunning(false) - , isFinished(false) + , tracer(nullptr) { } @@ -43,13 +43,7 @@ void Private::Execution::setFinished() { - isFinished = true; - //executor.clear(); -#ifndef QT_NO_DEBUG - if (tracer) { - delete tracer; - } -#endif + delete tracer; } void Private::Execution::releaseFuture() @@ -57,19 +51,6 @@ resultBase = 0; } -bool Private::Execution::errorWasHandled() const -{ - Execution *exec = const_cast<Execution*>(this); - while (exec) { - if (exec->executor->hasErrorFunc()) { - return true; - } - exec = exec->prevExecution.data(); - } - return false; -} - - @@ -94,57 +75,32 @@ { } -static void asyncWhile(const std::function<void(std::function<void(bool)>)> &body, const std::function<void()> &completionHandler) { - body([body, completionHandler](bool complete) { - if (complete) { - completionHandler(); - } else { - asyncWhile(body, completionHandler); - } - }); -} -Job<void> KAsync::dowhile(Condition condition, ThenTask<void> body) +Job<void> KAsync::doWhile(Job<ControlFlowFlag> body) { - return KAsync::start<void>([body, condition](KAsync::Future<void> &future) { - asyncWhile([condition, body, &future](std::function<void(bool)> whileCallback) { - KAsync::start<void>(body).then<void>([whileCallback, condition]() { - whileCallback(!condition()); - }, - [&future](int code, const QString &errorMessage) { - future.setError(code, errorMessage); - }).exec(); - }, - [&future]() { //while complete - future.setFinished(); - }); + return body.then<void, ControlFlowFlag>([body](const KAsync::Error &error, ControlFlowFlag flag) { + if (error) { + return KAsync::error(error); + } else if (flag == ControlFlowFlag::Continue) { + return doWhile(body); + } + return KAsync::null(); }); } -Job<void> KAsync::dowhile(ThenTask<bool> body) +Job<void> KAsync::doWhile(JobContinuation<ControlFlowFlag> body) { - return KAsync::start<void>([body](KAsync::Future<void> &future) { - asyncWhile([body](std::function<void(bool)> whileCallback) { - KAsync::start<bool>(body).then<bool, bool>([whileCallback](bool result) { - whileCallback(!result); - //FIXME this return value is only required because .then<bool, void> doesn't work - return true; - }).exec(); - }, - [&future]() { //while complete - future.setFinished(); - }); - }); + return doWhile(KAsync::start<ControlFlowFlag>([body] { + qDebug() << "Calling wrapper"; + return body(); + })); } Job<void> KAsync::wait(int delay) { - auto timer = QSharedPointer<QTimer>::create(); - return KAsync::start<void>([timer, delay](KAsync::Future<void> &future) { - timer->setSingleShot(true); - QObject::connect(timer.data(), &QTimer::timeout, [&future]() { + return KAsync::start<void>([delay](KAsync::Future<void> &future) { + QTimer::singleShot(delay, [&future]() { future.setFinished(); }); - timer->start(delay); }); }
View file
kasync-4.99.0.tar.gz/src/async.h
Changed
@@ -1,5 +1,7 @@ /* * Copyright 2014 - 2015 Daniel Vrátil <dvratil@redhat.com> + * Copyright 2016 Daniel Vrátil <dvratil@kde.org> + * Copyright 2016 Christian Mollekopf <mollekopf@kolabsystems.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as @@ -62,7 +64,6 @@ * * Future: Representation of the result that is being calculated * * - * TODO: Composed progress reporting * TODO: Possibility to abort a job through future (perhaps optional?) * TODO: Support for timeout, specified during exec call, after which the error * handler gets called with a defined errorCode. @@ -82,32 +83,23 @@ class Job; template<typename Out, typename ... In> -using ThenTask = typename detail::identity<std::function<void(In ..., KAsync::Future<Out>&)>>::type; +using HandleContinuation = typename detail::identity<std::function<void(In ..., KAsync::Future<Out>&)>>::type; + +template<typename Out, typename ... In> +using HandleErrorContinuation = typename detail::identity<std::function<void(const KAsync::Error &, In ..., KAsync::Future<Out>&)>>::type; + +template<typename Out, typename ... In> +using SyncContinuation = typename detail::identity<std::function<Out(In ...)>>::type; + +template<typename Out, typename ... In> +using SyncErrorContinuation = typename detail::identity<std::function<Out(const KAsync::Error &, In ...)>>::type; + template<typename Out, typename ... In> -using SyncThenTask = typename detail::identity<std::function<Out(In ...)>>::type; +using JobContinuation = typename detail::identity<std::function<KAsync::Job<Out>(In ...)>>::type; + template<typename Out, typename ... In> -using NestedThenTask = typename detail::identity<std::function<KAsync::Job<Out>(In ...)>>::type; -template<typename Out, typename In> -using EachTask = typename detail::identity<std::function<void(In, KAsync::Future<Out>&)>>::type; -template<typename T, typename Out, typename In> -using MemberEachTask = void(T::*)(In, KAsync::Future<Out>&); -template<typename Out, typename In> -using SyncEachTask = typename detail::identity<std::function<Out(In)>>::type; -template<typename Out, typename In> -using NestedEachTask = typename detail::identity<std::function<KAsync::Job<Out>(In)>>::type; -template<typename T, typename Out, typename In> -using MemberSyncEachTask = Out(T::*)(In); -template<typename Out, typename In> -using ReduceTask = typename detail::identity<std::function<void(In, KAsync::Future<Out>&)>>::type; -template<typename T, typename Out, typename In> -using MemberReduceTask = void(T::*)(In, KAsync::Future<Out> &); -template<typename Out, typename In> -using SyncReduceTask = typename detail::identity<std::function<Out(In)>>::type; -template<typename T, typename Out, typename In> -using MemberSyncReduceTask = Out(T::*)(In); - -using ErrorHandler = std::function<void(int, const QString &)>; -using Condition = std::function<bool()>; +using JobErrorContinuation = typename detail::identity<std::function<KAsync::Job<Out>(const KAsync::Error &, In ...)>>::type; + //@cond PRIVATE namespace Private @@ -128,21 +120,29 @@ } void releaseFuture(); - bool errorWasHandled() const; ExecutorBasePtr executor; FutureBase *resultBase; - bool isRunning; - bool isFinished; ExecutionPtr prevExecution; -#ifndef QT_NO_DEBUG Tracer *tracer; -#endif }; +template<typename Out, typename ... In> +struct ContinuationHelper { + ContinuationHelper(const HandleContinuation<Out, In...> &func) : handleContinuation(func) {}; + ContinuationHelper(const HandleErrorContinuation<Out, In...> &func) : handleErrorContinuation(func) {}; + ContinuationHelper(const JobContinuation<Out, In...> &func) : jobContinuation(func) {}; + ContinuationHelper(const JobErrorContinuation<Out, In...> &func) : jobErrorContinuation(func) {}; + + HandleContinuation<Out, In...> handleContinuation; + HandleErrorContinuation<Out, In...> handleErrorContinuation; + JobContinuation<Out, In...> jobContinuation; + JobErrorContinuation<Out, In...> jobErrorContinuation; +}; + typedef QSharedPointer<Execution> ExecutionPtr; class KASYNC_EXPORT ExecutorBase @@ -153,7 +153,7 @@ template<typename Out, typename ... In> friend class KAsync::Job; - friend class Execution; + friend struct Execution; friend class KAsync::Tracer; public: @@ -166,97 +166,51 @@ template<typename T> KAsync::Future<T>* createFuture(const ExecutionPtr &execution) const; - virtual bool hasErrorFunc() const = 0; - virtual bool handleError(const ExecutionPtr &execution) = 0; - ExecutorBasePtr mPrev; -#ifndef QT_NO_DEBUG + void prepend(const ExecutorBasePtr &e) + { + if (mPrev) { + mPrev->prepend(e); + } else { + mPrev = e; + } + } + + void addToContext(const QVariant &entry) + { + mContext << entry; + } + QString mExecutorName; -#endif + QVector<QVariant> mContext; +}; + +enum ExecutionFlag { + Always, + ErrorCase, + GoodCase }; template<typename PrevOut, typename Out, typename ... In> class Executor : public ExecutorBase { protected: - Executor(ErrorHandler errorFunc, const Private::ExecutorBasePtr &parent) + + Executor(const Private::ExecutorBasePtr &parent, ExecutionFlag executionFlag) : ExecutorBase(parent) - , mErrorFunc(errorFunc) + , executionFlag(executionFlag) {} virtual ~Executor() {} virtual void run(const ExecutionPtr &execution) = 0; ExecutionPtr exec(const ExecutorBasePtr &self); - bool hasErrorFunc() const Q_DECL_OVERRIDE { return (bool) mErrorFunc; } - bool handleError(const ExecutionPtr &execution) Q_DECL_OVERRIDE; - - std::function<void(int, const QString &)> mErrorFunc; -}; - -template<typename Out, typename ... In> -class ThenExecutor: public Executor<typename detail::prevOut<In ...>::type, Out, In ...> -{ -public: - ThenExecutor(ThenTask<Out, In ...> then, ErrorHandler errorFunc, const ExecutorBasePtr &parent); - void run(const ExecutionPtr &execution) Q_DECL_OVERRIDE; -private: - ThenTask<Out, In ...> mFunc; -}; - -template<typename PrevOut, typename Out, typename In> -class EachExecutor : public Executor<PrevOut, Out, In> -{ -public: - EachExecutor(EachTask<Out, In> each, ErrorHandler errorFunc, const ExecutorBasePtr &parent); - void run(const ExecutionPtr &execution) Q_DECL_OVERRIDE; -private: - EachTask<Out, In> mFunc; - QVector<KAsync::FutureWatcher<Out>*> mFutureWatchers; -}; - -template<typename Out, typename In> -class ReduceExecutor : public ThenExecutor<Out, In> -{ -public: - ReduceExecutor(ReduceTask<Out, In> reduce, ErrorHandler errorFunc, const ExecutorBasePtr &parent); -private: - ReduceTask<Out, In> mFunc; -}; - -template<typename Out, typename ... In> -class SyncThenExecutor : public Executor<typename detail::prevOut<In ...>::type, Out, In ...> -{ -public: - SyncThenExecutor(SyncThenTask<Out, In ...> then, ErrorHandler errorFunc, const ExecutorBasePtr &parent);
View file
kasync-4.99.0.tar.gz/src/async_impl.h
Changed
@@ -1,5 +1,6 @@ /* * Copyright 2014 - 2015 Daniel Vrátil <dvratil@redhat.com> + * Copyright 2016 Daniel Vrátil <dvratil@kde.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as
View file
kasync-4.99.0.tar.gz/src/debug.cpp
Changed
@@ -66,10 +66,8 @@ void Tracer::msg(Tracer::MsgType msgType) { -#ifndef QT_NO_DEBUG qCDebug(Trace).nospace() << (QString().fill(QLatin1Char(' '), mId * 2) % (msgType == KAsync::Tracer::Start ? QStringLiteral(" START ") : QStringLiteral(" END ")) % QString::number(mId) % QStringLiteral(" ") % mExecution->executor->mExecutorName); -#endif }
View file
kasync-4.99.0.tar.gz/src/debug.h
Changed
@@ -39,7 +39,7 @@ namespace Private { -class Execution; +struct Execution; } class KASYNC_EXPORT Tracer
View file
kasync-4.99.0.tar.gz/src/future.cpp
Changed
@@ -22,7 +22,6 @@ FutureBase::PrivateBase::PrivateBase(const Private::ExecutionPtr &execution) : finished(false) - , errorCode(0) , mExecution(execution) { } @@ -73,6 +72,7 @@ return; } d->finished = true; + //TODO this could directly call the next continuation with the value, and thus avoid unnecessary copying. for (auto watcher : d->watchers) { if (watcher) { watcher->futureReadyCallback(); @@ -87,19 +87,52 @@ void FutureBase::setError(int code, const QString &message) { - d->errorCode = code; - d->errorMessage = message; + d->errors.clear(); + addError(Error(code, message)); setFinished(); } +void FutureBase::setError(const Error &error) +{ + d->errors.clear(); + addError(error); + setFinished(); +} + +void FutureBase::addError(const Error &error) +{ + d->errors << error; +} + +void FutureBase::clearErrors() +{ + d->errors.clear(); +} + +bool FutureBase::hasError() const +{ + return !d->errors.isEmpty(); +} + int FutureBase::errorCode() const { - return d->errorCode; + if (d->errors.isEmpty()) { + return 0; + } + return d->errors.first().errorCode; } QString FutureBase::errorMessage() const { - return d->errorMessage; + if (d->errors.isEmpty()) { + return QString(); + } + return d->errors.first().errorMessage; +} + +QVector<Error> FutureBase::errors() const +{ + return d->errors; } void FutureBase::setProgress(int processed, int total)
View file
kasync-4.99.0.tar.gz/src/future.h
Changed
@@ -1,5 +1,6 @@ /* * Copyright 2014 Daniel Vrátil <dvratil@redhat.com> + * Copyright 2016 Daniel Vrátil <dvratil@kde.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as @@ -38,12 +39,41 @@ class FutureWatcher; namespace Private { -class Execution; +struct Execution; class ExecutorBase; typedef QSharedPointer<Execution> ExecutionPtr; } // namespace Private +struct KASYNC_EXPORT Error +{ + Error() : errorCode(0) {}; + explicit Error(const char *message) : errorCode(1), errorMessage(QString::fromLatin1(message)) {} + Error(int code, const char *message) : errorCode(code), errorMessage(QString::fromLatin1(message)) {} + Error(int code, const QString &message) : errorCode(code), errorMessage(message) {} + + bool operator ==(const Error &other) const { + return (errorCode == other.errorCode) && (errorMessage == other.errorMessage); + } + + bool operator !=(const Error &other) const { + return !(*this == other); + } + + operator bool() const { + return (errorCode != 0); + } + + int errorCode; + QString errorMessage; +private: + //Disable all implicit conversions except to bool, to avoid accidentally implicitly casting an error to a continuation argument. + //This becomes an issue if you forget to specify all template arguments, as the template argument deduction may employ a nonsensical implicit conversion from i.e. error to int. So as long as the Error object is used in the Job::then overload resolution no implicit conversions here. + //Of course this "solution" still breaks if you forget the template argument with a boolean parameter.... + template <typename T> + operator T() const; +}; + class KASYNC_EXPORT FutureBase { friend class KAsync::Private::Execution; @@ -57,8 +87,13 @@ bool isFinished() const; void setError(int code = 1, const QString &message = QString()); + void setError(const Error &error); + void addError(const Error &error); + void clearErrors(); + bool hasError() const; int errorCode() const; QString errorMessage() const; + QVector<Error> errors() const; void setProgress(qreal progress); void setProgress(int processed, int total); @@ -73,8 +108,7 @@ void releaseExecution(); bool finished; - int errorCode; - QString errorMessage; + QVector<Error> errors; QVector<QPointer<FutureWatcherBase>> watchers; private: @@ -294,6 +328,12 @@ #endif // ONLY_DOXYGEN + void setResult(const T &value) + { + static_cast<typename FutureGeneric<T>::Private*>(this->d.data())->value = value; + FutureBase::setFinished(); + } + protected: //@cond PRIVATE Future(const KAsync::Private::ExecutionPtr &execution)
View file
kasync-4.99.0.tar.gz/src/job_impl.h
Changed
@@ -1,6 +1,7 @@ /* * Copyright 2014 - 2015 Daniel Vrátil <dvratil@redhat.com> - * Copyright 2015 Daniel Vrátil <dvratil@kde.org> + * Copyright 2015 - 2016 Daniel Vrátil <dvratil@kde.org> + * Copyright 2016 Christian Mollekopf <mollekopf@kolabsystems.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as @@ -26,212 +27,352 @@ namespace KAsync { +namespace Private { + template<typename Out, typename ... In> -template<typename OutOther, typename ... InOther> -Job<OutOther, InOther ...> Job<Out, In ...>::then(ThenTask<OutOther, InOther ...> func, - ErrorHandler errorFunc) +class ThenExecutor: public Executor<typename detail::prevOut<In ...>::type, Out, In ...> { - return Job<OutOther, InOther ...>(Private::ExecutorBasePtr( - new Private::ThenExecutor<OutOther, InOther ...>(func, errorFunc, mExecutor))); -} +public: + ThenExecutor(ContinuationHelper<Out, In ...> workerHelper, const ExecutorBasePtr &parent = {}, + ExecutionFlag executionFlag = ExecutionFlag::GoodCase) + : Executor<typename detail::prevOut<In ...>::type, Out, In ...>(parent, executionFlag) + , mContinuationHelper(workerHelper) + { + STORE_EXECUTOR_NAME("ThenExecutor", Out, In ...); + } -template<typename Out, typename ... In> -template<typename T, typename OutOther, typename ... InOther> -typename std::enable_if<std::is_class<T>::value, Job<OutOther, InOther ...>>::type -Job<Out, In ...>::then(T *object, - typename detail::funcHelper<T, OutOther, InOther ...>::type func, - ErrorHandler errorFunc) -{ - return Job<OutOther, InOther ...>(Private::ExecutorBasePtr( - new Private::ThenExecutor<OutOther, InOther ...>( - memberFuncWrapper<ThenTask<OutOther, InOther ...>, T, OutOther, InOther ...>(object, func), - errorFunc, mExecutor))); -} + void run(const ExecutionPtr &execution) Q_DECL_OVERRIDE + { + KAsync::Future<typename detail::prevOut<In ...>::type> *prevFuture = nullptr; + if (execution->prevExecution) { + prevFuture = execution->prevExecution->result<typename detail::prevOut<In ...>::type>(); + assert(prevFuture->isFinished()); + } + + //Execute one of the available workers + KAsync::Future<Out> *future = execution->result<Out>(); + + if (ThenExecutor<Out, In ...>::mContinuationHelper.handleContinuation) { + ThenExecutor<Out, In ...>::mContinuationHelper.handleContinuation(prevFuture ? prevFuture->value() : In() ..., *future); + } else if (ThenExecutor<Out, In ...>::mContinuationHelper.handleErrorContinuation) { + ThenExecutor<Out, In ...>::mContinuationHelper.handleErrorContinuation(prevFuture->hasError() ? prevFuture->errors().first() : Error(), prevFuture ? prevFuture->value() : In() ..., *future); + } else if (ThenExecutor<Out, In ...>::mContinuationHelper.jobContinuation) { + executeJobAndApply(prevFuture ? prevFuture->value() : In() ..., ThenExecutor<Out, In...>::mContinuationHelper.jobContinuation, *future, std::is_void<Out>()); + } else if (ThenExecutor<Out, In ...>::mContinuationHelper.jobErrorContinuation) { + executeJobAndApply(prevFuture->hasError() ? prevFuture->errors().first() : Error(), prevFuture ? prevFuture->value() : In() ..., ThenExecutor<Out, In...>::mContinuationHelper.jobErrorContinuation, *future, std::is_void<Out>()); + } + } -template<typename Out, typename ... In> -template<typename OutOther, typename ... InOther> -Job<OutOther, InOther ...> Job<Out, In ...>::then(SyncThenTask<OutOther, InOther ...> func, - ErrorHandler errorFunc) -{ - return Job<OutOther, InOther ...>(Private::ExecutorBasePtr( - new Private::SyncThenExecutor<OutOther, InOther ...>(func, errorFunc, mExecutor))); -} +private: + + void executeJobAndApply(In ... input, const JobContinuation<Out, In ...> &func, + Future<Out> &future, std::false_type) + { + func(input ...) + .template then<void, Out>([&future](const KAsync::Error &error, const Out &v, + KAsync::Future<void> &f) { + if (error) { + future.setError(error); + } else { + future.setResult(v); + } + f.setFinished(); + }).exec(); + } -template<typename Out, typename ... In> -template<typename T, typename OutOther, typename ... InOther> -typename std::enable_if<std::is_class<T>::value, Job<OutOther, InOther ...>>::type -Job<Out, In ...>::then(T *object, - typename detail::syncFuncHelper<T, OutOther, InOther ...>::type func, - ErrorHandler errorFunc) -{ - return Job<OutOther, InOther ...>(Private::ExecutorBasePtr( - new Private::SyncThenExecutor<OutOther, InOther ...>( - memberFuncWrapper<SyncThenTask<OutOther, InOther ...>, T, OutOther, InOther ...>(object, func), - errorFunc, mExecutor))); -} + void executeJobAndApply(In ... input, const JobContinuation<Out, In ...> &func, + Future<Out> &future, std::true_type) + { + func(input ...) + .template then<void>([&future](const KAsync::Error &error, KAsync::Future<void> &f) { + if (error) { + future.setError(error); + } else { + future.setFinished(); + } + f.setFinished(); + }).exec(); + } -template<typename Out, typename ... In> -template<typename OutOther, typename ... InOther> -typename std::enable_if<!std::is_void<OutOther>::value, Job<OutOther, InOther ...>>::type -Job<Out, In ...>::then(NestedThenTask<OutOther, InOther ...> func, - ErrorHandler errorFunc) -{ - return then<OutOther, InOther ...>(nestedJobWrapper<OutOther, InOther ...>(func), errorFunc); -} + void executeJobAndApply(const Error &error, In ... input, const JobErrorContinuation<Out, In ...> &func, + Future<Out> &future, std::false_type) + { + func(error, input ...) + .template then<void, Out>([&future](const KAsync::Error &error, const Out &v, + KAsync::Future<void> &f) { + if (error) { + future.setError(error); + } else { + future.setResult(v); + } + f.setFinished(); + }).exec(); + } -template<typename Out, typename ... In> -template<typename OutOther, typename ContOut, typename ... InOther> -typename std::enable_if<std::is_void<OutOther>::value, Job<OutOther, InOther ...>>::type -Job<Out, In ...>::then(NestedThenTask<void, InOther ...> func, ErrorHandler errorFunc) -{ - return then<OutOther, InOther ...>(nestedJobWrapper<void, InOther ...>(func), errorFunc); -} + void executeJobAndApply(const Error &error, In ... input, const JobErrorContinuation<Out, In ...> &func, + Future<Out> &future, std::true_type) + { + func(error, input ...) + .template then<void>([&future](const KAsync::Error &error, KAsync::Future<void> &f) { + if (error) { + future.setError(error); + } else { + future.setFinished(); + } + f.setFinished(); + }).exec(); + } -template<typename Out, typename ... In> -template<typename OutOther, typename ... InOther> -Job<OutOther, InOther ...> Job<Out, In ...>::then(Job<OutOther, InOther ...> otherJob, ErrorHandler errorFunc) -{ - return then<OutOther, InOther ...>(nestedJobWrapper<OutOther, InOther ...>(otherJob), errorFunc); -} + ContinuationHelper<Out, In ...> mContinuationHelper; +}; -template<typename Out, typename ... In> -template<typename ReturnType, typename KJobType, ReturnType (KJobType::*KJobResultMethod)(), typename ... Args> -typename std::enable_if<std::is_base_of<KJob, KJobType>::value, Job<ReturnType, Args ...>>::type -Job<Out, In ...>::then() -{ - return start<ReturnType, KJobType, KJobResultMethod, Args ...>(); -} template<typename Out, typename ... In> -template<typename OutOther, typename InOther> -Job<OutOther, InOther> Job<Out, In ...>::each(EachTask<OutOther, InOther> func, - ErrorHandler errorFunc) +class SyncThenExecutor: public Executor<typename detail::prevOut<In ...>::type, Out, In ...> { - eachInvariants<OutOther>(); - return Job<OutOther, InOther>(Private::ExecutorBasePtr( - new Private::EachExecutor<Out, OutOther, InOther>(func, errorFunc, mExecutor))); -} +private: -template<typename Out, typename ... In> -template<typename T, typename OutOther, typename InOther> -typename std::enable_if<std::is_class<T>::value, Job<OutOther, InOther> >::type -Job<Out, In ...>::each(T *object, MemberEachTask<T, OutOther, InOther> func, - ErrorHandler errorFunc) -{ - eachInvariants<OutOther>(); - return Job<OutOther, InOther>(Private::ExecutorBasePtr( - new Private::EachExecutor<Out, OutOther, InOther>(
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.