#ifndef __PROCESS_DEFERRED_HPP__ #define __PROCESS_DEFERRED_HPP__ #include #include #include #include namespace process { // Forward declarations (removing these produces cryptic compiler // errors even though we are just using them to declare friends). class Executor; template struct _Defer; // Acts like a function call but runs within an asynchronous execution // context such as an Executor or a ProcessBase (enforced because only // an executor or the 'defer' routines are allowed to create them). template struct Deferred : std::tr1::function { private: // Only an Executor and the 'defer' routines can create these. friend class Executor; template friend struct _Defer; friend Deferred defer(const std::tr1::function& f); #define TEMPLATE(Z, N, DATA) \ template \ friend Deferred defer( \ const std::tr1::function& f); REPEAT_FROM_TO(1, 11, TEMPLATE, _) // Args A0 -> A9. #undef TEMPLATE Deferred(const std::tr1::function& f) : std::tr1::function(f) {} }; // The result of invoking the 'defer' routines is actually an internal // type, effectively just a wrapper around the result of invoking // 'std::tr1::bind'. However, we want the result of bind to be // castable to a 'Deferred' but we don't want anyone to be able to // create a 'Deferred' so we use a level-of-indirection via this type. template struct _Defer : std::tr1::_Bind { template operator Deferred<_F> () { return Deferred<_F>(std::tr1::function<_F>(*this)); } private: friend class Executor; template friend _Defer, void (T::*)(void))) (const PID&, void (T::*)(void))> defer(const PID& pid, void (T::*method)(void)); #define TEMPLATE(Z, N, DATA) \ template \ friend _Defer, \ void (T::*)(ENUM_PARAMS(N, P)), \ ENUM_PARAMS(N, A))) \ (const PID&, \ void (T::*)(ENUM_PARAMS(N, P)), \ ENUM_PARAMS(N, P))> \ defer(const PID& pid, \ void (T::*method)(ENUM_PARAMS(N, P)), \ ENUM_BINARY_PARAMS(N, A, a)); REPEAT_FROM_TO(1, 11, TEMPLATE, _) // Args A0 -> A9. #undef TEMPLATE template friend _Defer(*(PID, Future (T::*)(void)))( const PID&, Future (T::*)(void))> defer(const PID& pid, Future (T::*method)(void)); #define TEMPLATE(Z, N, DATA) \ template \ friend _Defer(*(PID, \ Future (T::*)(ENUM_PARAMS(N, P)), \ ENUM_PARAMS(N, A))) \ (const PID&, \ Future (T::*)(ENUM_PARAMS(N, P)), \ ENUM_PARAMS(N, P))> \ defer(const PID& pid, \ Future (T::*method)(ENUM_PARAMS(N, P)), \ ENUM_BINARY_PARAMS(N, A, a)); REPEAT_FROM_TO(1, 11, TEMPLATE, _) // Args A0 -> A9. #undef TEMPLATE template friend _Defer(*(PID, R (T::*)(void)))( const PID&, R (T::*)(void))> defer(const PID& pid, R (T::*method)(void)); #define TEMPLATE(Z, N, DATA) \ template \ friend _Defer(*(PID, \ R (T::*)(ENUM_PARAMS(N, P)), \ ENUM_PARAMS(N, A))) \ (const PID&, \ R (T::*)(ENUM_PARAMS(N, P)), \ ENUM_PARAMS(N, P))> \ defer(const PID& pid, \ R (T::*method)(ENUM_PARAMS(N, P)), \ ENUM_BINARY_PARAMS(N, A, a)); REPEAT_FROM_TO(1, 11, TEMPLATE, _) // Args A0 -> A9. #undef TEMPLATE _Defer(const std::tr1::_Bind& b) : std::tr1::_Bind(b) {} }; } // namespace process { #endif // __PROCESS_DEFERRED_HPP__