#ifndef __ASYNC_HPP__ #define __ASYNC_HPP__ #include #include #include #include #include namespace process { // TODO(vinod): Merge this into ExecutorProcess. // TODO(vinod): Add support for void functions. Currently this is tricky, // because Future is not supported. class AsyncExecutorProcess : public Process { private: friend class AsyncExecutor; AsyncExecutorProcess() : ProcessBase(ID::generate("__async_executor__")) {} virtual ~AsyncExecutorProcess() {} // Not copyable, not assignable. AsyncExecutorProcess(const AsyncExecutorProcess&); AsyncExecutorProcess& operator = (const AsyncExecutorProcess&); template typename std::tr1::result_of::type execute( const F& f) { terminate(self()); // Terminate this process after the function returns. return f(); } // TODO(vinod): Use boost macro enumerations. template typename std::tr1::result_of::type execute( const F& f, A1 a1) { terminate(self()); // Terminate this process after the function returns. return f(a1); } template typename std::tr1::result_of::type execute( const F& f, A1 a1, A2 a2) { terminate(self()); // Terminate this process after the function returns. return f(a1, a2); } template typename std::tr1::result_of::type execute( const F& f, A1 a1, A2 a2, A3 a3) { terminate(self()); // Terminate this process after the function returns. return f(a1, a2, a3); } template typename std::tr1::result_of::type execute( const F& f, A1 a1, A2 a2, A3 a3, A4 a4) { terminate(self()); // Terminate this process after the function returns. return f(a1, a2, a3, a4); } }; // This is a wrapper around AsyncExecutorProcess. class AsyncExecutor { private: // Declare async functions as friends. template friend Future::type> async( const F& f); template friend Future::type> async( const F& f, A1 a1); template friend Future::type> async( const F& f, A1 a1, A2 a2); template friend Future::type> async( const F& f, A1 a1, A2 a2, A3 a3); template friend Future::type> async( const F& f, A1 a1, A2 a2, A3 a3, A4 a4); AsyncExecutor() { process = new AsyncExecutorProcess(); spawn(process, true); // Automatically GC. } virtual ~AsyncExecutor() {} // Not copyable, not assignable. AsyncExecutor(const AsyncExecutor&); AsyncExecutor& operator = (const AsyncExecutor&); template Future::type> execute( const F& f) { // Necessary to disambiguate. typedef typename std::tr1::result_of::type (AsyncExecutorProcess::*R)(const F&); return dispatch(process, static_cast(&AsyncExecutorProcess::execute), f); } // TODO(vinod): Use boost macro enumerations. template Future::type> execute( const F& f, A1 a1) { // Necessary to disambiguate. typedef typename std::tr1::result_of::type (AsyncExecutorProcess::*R)(const F&, A1); return dispatch(process, static_cast(&AsyncExecutorProcess::execute), f, a1); } template Future::type> execute( const F& f, A1 a1, A2 a2) { // Necessary to disambiguate. typedef typename std::tr1::result_of::type (AsyncExecutorProcess::*R)(const F&, A1, A2); return dispatch(process, static_cast(&AsyncExecutorProcess::execute), f, a1, a2); } template Future::type> execute( const F& f, A1 a1, A2 a2, A3 a3) { // Necessary to disambiguate. typedef typename std::tr1::result_of::type (AsyncExecutorProcess::*R)(const F&, A1, A2, A3); return dispatch(process, static_cast(&AsyncExecutorProcess::execute), f, a1, a2, a3); } template Future::type> execute( const F& f, A1 a1, A2 a2, A3 a3, A4 a4) { // Necessary to disambiguate. typedef typename std::tr1::result_of::type (AsyncExecutorProcess::*R)(const F&, A1, A2, A3, A4); return dispatch(process, static_cast(&AsyncExecutorProcess::execute), f, a1, a2, a3, a4); } AsyncExecutorProcess* process; }; // Provides an abstraction for asynchronously executing a function. // TODO(vinod): Use boost macro to enumerate arguments/params. template Future::type> async(const F& f) { return AsyncExecutor().execute(f); } template Future::type> async(const F& f, A1 a1) { return AsyncExecutor().execute(f, a1); } template Future::type> async(const F& f, A1 a1, A2 a2) { return AsyncExecutor().execute(f, a1, a2); } template Future::type> async(const F& f, A1 a1, A2 a2, A3 a3) { return AsyncExecutor().execute(f, a1, a2, a3); } template Future::type> async(const F& f, A1 a1, A2 a2, A3 a3, A4 a4) { return AsyncExecutor().execute(f, a1, a2, a3, a4); } } // namespace process { #endif // __ASYNC_HPP__