From 77d10f3633eb2210b465397fd3a29c77846c00a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Vr=C3=A1til?= Date: Thu, 11 Dec 2014 12:19:57 +0100 Subject: Async: simplify the template magic around In... being empty or void --- async/src/async.h | 111 +++++++++++++++++++++++++++++------------------------- 1 file changed, 60 insertions(+), 51 deletions(-) (limited to 'async/src') diff --git a/async/src/async.h b/async/src/async.h index 790dfe9..3fee450 100644 --- a/async/src/async.h +++ b/async/src/async.h @@ -34,38 +34,51 @@ namespace Async { +class JobBase; + template class Job; template Job start(const std::function(In ...)> &func); +namespace Private +{ + template + Async::Future* doExec(Job *job, const In & ... args); +} class JobBase { + template + friend Async::Future* Private::doExec(Job *job, const In & ... args); + + template + friend class Job; + +protected: + enum JobType { + Then, + Each + }; + public: - JobBase(JobBase *prev = nullptr) + JobBase(JobType jobType, JobBase *prev = nullptr) : mPrev(prev) , mResult(0) + , mJobType(jobType) {} virtual void exec() = 0; -public: +protected: JobBase *mPrev; void *mResult; -}; -namespace Private { + JobType mJobType; +}; - template - typename std::enable_if::value, void>::type - doExec(JobBase *prev, JobBase *jobBase); - template - typename std::enable_if::type - doExec(JobBase *prev, JobBase *jobBase, int * /* disambiguate */ = 0); -} template class Job : public JobBase @@ -76,20 +89,25 @@ class Job : public JobBase template friend Job start(F_ func); + typedef Out OutType; + typedef typename std::tuple_element<0, std::tuple>::type InType; + public: ~Job() { - // Can't delete in JobBase, since we don't know the type - // and deleting void* is undefined delete reinterpret_cast*>(mResult); } template Job then(F func) { - Job job(this); - job.mFunc = func; - return job; + return Job::create(func, JobBase::Then, this); + } + + template + Job each(F func) + { + return Job::create(func, JobBase::Each, this); } Async::Future result() const @@ -97,16 +115,34 @@ public: return *reinterpret_cast*>(mResult); } - void exec() { - Async::Private::doExec(mPrev, this); + Async::Future *in = nullptr; + if (mPrev) { + mPrev->exec(); + in = reinterpret_cast*>(mPrev->mResult); + assert(in->isFinished()); + } + + Job *job = dynamic_cast*>(this); + Async::Future *out = Private::doExec(this, in ? in->value() : In() ...); + out->waitForFinished(); + job->mResult = reinterpret_cast(out); } private: - Job(JobBase *parent = nullptr) - : JobBase(parent) - {} + Job(JobBase::JobType jobType, JobBase *parent = nullptr) + : JobBase(jobType, parent) + { + } + + template + static Job create(F func, JobBase::JobType jobType, JobBase *parent = nullptr) + { + Job job(jobType, parent); + job.mFunc = func; + return job; + } public: std::function(In ...)> mFunc; @@ -115,44 +151,17 @@ public: template Job start(F func) { - Job job; - job.mFunc = std::function(In ...)>(func); - return job; + return Job::create(func, JobBase::Then); } } // namespace Async -template -typename std::enable_if::value, void>::type -Async::Private::doExec(JobBase *prev, JobBase *jobBase) -{ - prev->exec(); - Async::Future *in = reinterpret_cast*>(prev->mResult); - assert(in->isFinished()); - - Job *job = dynamic_cast*>(jobBase); - Async::Future *out = new Async::Future(job->mFunc(in->value())); - out->waitForFinished(); - job->mResult = reinterpret_cast(out); -}; - template -typename std::enable_if::type -Async::Private::doExec(JobBase *prev, JobBase *jobBase, int * /* disambiguation */ = 0) +Async::Future* Async::Private::doExec(Job *job, const In & ... args) { - if (prev) { - prev->exec(); - Async::Future *in = reinterpret_cast*>(prev->mResult); - assert(in->isFinished()); - } - - Job *job = dynamic_cast*>(jobBase); - Async::Future *out = new Async::Future(job->mFunc()); - out->waitForFinished(); - job->mResult = reinterpret_cast(out); + return new Async::Future(job->mFunc(args ...)); }; - #endif // ASYNC_H -- cgit v1.2.3