//  // // ##### #### # # -= Threadux =-  // //  # # # ## ## Invocation.h  // //  # # # ##  // //  # # # ### Stored invocation of a function or method  // //  # # # ## ##  // //  # #### # # R1 2004 by Markus Ewald  // //  // #ifndef THREADUX_INVOCATION_H #define THREADUX_INVOCATION_H #include "Threadux/Threadux.h" #include // Usage // // Example 1: Call a simple function // Invocation MyTest = Invocation::ofFunction(printf, "hello world"); // MyTest(); // // Example 2: Call a functor // Invocation MyTest = Invocation::ofFunctor(new std::less(), 1, 2); // MyTest(); // // Example 3: Call a method on an object // Invocation MyTest = Invocation::ofMethod(cout, &SomeClass::someMethod, "some argument"); // MyTest(); // namespace Threadux { //  // //  Threadux::Invocation  // //  // /// Stored invocation /** Can be used to store a call to a function, functor or method which can then (even repeatedly) be executed at a later time. Arguments can also be stored and are passed to the callee as normal, thought it is not possible to define argument values at the time the call is executed. This class is not intended to replace a full-blown signal/slot system, but to conveniently delay calls to ship them over to an exception-aware location in code into another thread for example. */ class Invocation { public: /// Create function invocation template inline static Invocation ofFunction(FunctionType Function); template inline static Invocation ofFunction(FunctionType Function, Argument1Type Argument1); template inline static Invocation ofFunction(FunctionType Function, Argument1Type Argument1, Argument2Type Argument2); /// Create method invocation template inline static Invocation ofMethod(ObjectType &Object, MethodType Method); template inline static Invocation ofMethod(ObjectType &Object, MethodType Method, Argument1Type Argument1); template inline static Invocation ofMethod(ObjectType &Object, MethodType Method, Argument1Type Argument1, Argument2Type Argument2); /// Create functor invocation template inline static Invocation ofFunctor(std::auto_ptr Functor); template inline static Invocation ofFunctor(std::auto_ptr Functor, Argument1Type Argument1); template inline static Invocation ofFunctor(std::auto_ptr Functor, Argument1Type Argument1, Argument2Type Argument2); /// Copy constructor Invocation(const Invocation &Other) : m_pCaller(Other.m_pCaller) { ++m_pCaller->ReferenceCount; } /// Destructor ~Invocation() { release(); } // // Invocation implementation // public: /// Function operator void operator()() { (*m_pCaller)(); } /// Copy assignment operator void operator =(const Invocation &Other) { release(); m_pCaller = Other.m_pCaller; ++m_pCaller->ReferenceCount; } private: /// Call executer struct Caller { virtual ~Caller() {} virtual void operator()() = 0; size_t ReferenceCount; }; /// Construct from caller (used by static factory methods) Invocation(Caller *pCaller) : m_pCaller(pCaller) { ++m_pCaller->ReferenceCount; } /// Release call executer void release() { if(!--m_pCaller->ReferenceCount) delete m_pCaller; } /// The call executer /** This member will be valid for any existing Invocation instance and points to the instance of a class derived from Caller that will invoke the user specified function, functor or method */ Caller *m_pCaller; }; // ############################################################################################# // // # Threadux::Invocation::ofFunction() # // // ############################################################################################# // template inline Invocation Invocation::ofFunction(FunctionType Function) { struct FunctionCaller : Caller { inline FunctionCaller(FunctionType Function) : m_Function(Function) {} inline void operator ()() { m_Function(); } private: FunctionType m_Function; }; return Invocation(new FunctionCaller(Function)); } // ############################################################################################# // // # Threadux::Invocation::ofFunction() # // // ############################################################################################# // template inline Invocation Invocation::ofFunction(FunctionType Function, Argument1Type Argument1) { struct FunctionCaller : Caller { inline FunctionCaller(FunctionType Function, Argument1Type Argument1) : m_Function(Function), m_Argument1(Argument1) {} inline void operator ()() { m_Function(m_Argument1); } private: FunctionType m_Function; Argument1Type m_Argument1; }; return Invocation(new FunctionCaller(Function, Argument1)); } // ############################################################################################# // // # Threadux::Invocation::ofFunction() # // // ############################################################################################# // template inline Invocation Invocation::ofFunction(FunctionType Function, Argument1Type Argument1, Argument2Type Argument2) { struct FunctionCaller : Caller { inline FunctionCaller(FunctionType Function, Argument1Type Argument1, Argument2Type Argument2) : m_Function(Function), m_Argument1(Argument1), m_Argument2(Argument2) {} inline void operator ()() { m_Function(m_Argument1, m_Argument2); } private: FunctionType m_Function; Argument1Type m_Argument1; Argument2Type m_Argument2; }; return Invocation(new FunctionCaller(Function, Argument1, Argument2)); } // ############################################################################################# // // # Threadux::Invocation::ofFunctor() # // // ############################################################################################# // template inline Invocation Invocation::ofFunctor(std::auto_ptr Functor) { struct FunctorCaller : Caller { inline FunctorCaller(std::auto_ptr Functor) : m_Functor(Functor) {} inline void operator ()() { m_Functor->operator()(); } private: std::auto_ptr m_Functor; }; return Invocation(new FunctorCaller(Functor)); } // ############################################################################################# // // # Threadux::Invocation::ofFunctor() # // // ############################################################################################# // template inline Invocation Invocation::ofFunctor(std::auto_ptr Functor, Argument1Type Argument1) { struct FunctorCaller : Caller { inline FunctorCaller(std::auto_ptr Functor, Argument1Type Argument1) : m_Functor(Functor), m_Argument1(Argument1) {} inline void operator ()() { m_Functor->operator()(m_Argument1); } private: std::auto_ptr m_Functor; Argument1Type m_Argument1; }; return Invocation(new FunctorCaller(Functor, Argument1)); } // ############################################################################################# // // # Threadux::Invocation::ofFunctor() # // // ############################################################################################# // template inline Invocation Invocation::ofFunctor(std::auto_ptr Functor, Argument1Type Argument1, Argument2Type Argument2) { struct FunctorCaller : Caller { inline FunctorCaller(std::auto_ptr Functor, Argument1Type Argument1, Argument2Type Argument2) : m_Functor(Functor), m_Argument1(Argument1), m_Argument2(Argument2) {} inline void operator ()() { m_Functor->operator()(m_Argument1, m_Argument2); } private: std::auto_ptr m_Functor; Argument1Type m_Argument1; Argument2Type m_Argument2; }; return Invocation(new FunctorCaller(Functor, Argument1, Argument2)); } // ############################################################################################# // // # Threadux::Invocation::ofMethod() # // // ############################################################################################# // template inline Invocation Invocation::ofMethod(ObjectType &Object, MethodType Method) { struct MethodCaller : Caller { inline MethodCaller(ObjectType &Object, MethodType Method) : m_Object(Object), m_Method(Method) {} inline void operator ()() { (m_Object.*m_Method)(); } private: ObjectType &m_Object; MethodType m_Method; }; return Invocation(new MethodCaller(Object, Method)); } // ############################################################################################# // // # Threadux::Invocation::ofMethod() # // // ############################################################################################# // template inline Invocation Invocation::ofMethod(ObjectType &Object, MethodType Method, Argument1Type Argument1) { struct MethodCaller : Caller { inline MethodCaller(ObjectType &Object, MethodType Method, Argument1Type Argument1) : m_Object(Object), m_Method(Method), m_Argument1(Argument1) {} inline void operator ()() { (m_Object.*m_Method)(m_Argument1); } private: ObjectType &m_Object; MethodType m_Method; Argument1Type m_Argument1; }; return Invocation(new MethodCaller(Object, Method, Argument1)); } // ############################################################################################# // // # Threadux::Invocation::ofMethod() # // // ############################################################################################# // template inline Invocation Invocation::ofMethod(ObjectType &Object, MethodType Method, Argument1Type Argument1, Argument2Type Argument2) { struct MethodCaller : Caller { inline MethodCaller(ObjectType &Object, MethodType Method, Argument1Type Argument1, Argument2Type Argument2) : m_Object(Object), m_Method(Method), m_Argument1(Argument1), m_Argument2(Argument2) {} inline void operator ()() { (m_Object.*m_Method)(m_Argument1, m_Argument2); } private: ObjectType &m_Object; MethodType m_Method; Argument1Type m_Argument1; Argument2Type m_Argument2; }; return Invocation(new MethodCaller(Object, Method, Argument1, Argument2)); } } // namespace Threadux #endif // THREADUX_INVOCATION_H