/** * \file callback.h * \brief PIPELINE_CALLBACK_ARGS_CLASS * \date 2009-03-03 18:09GMT * \author Jan Boon (Kaetemi) * PIPELINE_CALLBACK_ARGS_CLASS */ /* * Copyright (C) 2009-2012 by authors * * This file is part of RYZOM CORE PIPELINE. * RYZOM CORE PIPELINE is free software: you can redistribute it * and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 2 of * the License, or (at your option) any later version. * * RYZOM CORE PIPELINE is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with RYZOM CORE PIPELINE; see the file COPYING. If not, see * . */ #ifndef PIPELINE_CALLBACK_H #define PIPELINE_CALLBACK_H #include // STL includes // NeL includes #include // Project includes namespace PIPELINE { #define PIPELINE_CALLBACK_TEMPLATE \ /** \ * \brief PIPELINE_CALLBACK_ARGS_CLASS \ * \date 2009-03-03 18:09GMT \ * \author Jan Boon (Kaetemi) \ * Awesome callback template \ */ \ template \ class PIPELINE_CALLBACK_ARGS_CLASS \ { \ /* Very simple reference counting callback base */ \ class CCallbackBase \ { \ public: \ CCallbackBase() : m_RefCount(0) \ { \ \ } \ \ virtual ~CCallbackBase() \ { \ nlassert(!m_RefCount); \ } \ \ void refAdd() \ { \ ++m_RefCount; \ } \ \ void refRemove() \ { \ --m_RefCount; \ if (!m_RefCount) \ delete this; \ } \ \ virtual TReturn callback(PIPELINE_CALLBACK_ARGS_DECL) = 0; \ \ virtual bool equals(const CCallbackBase *callbackBase) = 0; \ \ /* disable copy */ \ CCallbackBase(const CCallbackBase &); \ CCallbackBase &operator=(const CCallbackBase &); \ \ private: \ uint m_RefCount; \ }; \ \ typedef TReturn TCallbackFunction(PIPELINE_CALLBACK_ARGS_DECL); \ class CCallbackFunction : public CCallbackBase \ { \ public: \ CCallbackFunction(TCallbackFunction *callbackFunction) : m_CallbackFunction(callbackFunction) \ { \ nlassert(m_CallbackFunction); \ } \ \ virtual ~CCallbackFunction() \ { \ m_CallbackFunction = NULL; \ } \ \ virtual TReturn callback(PIPELINE_CALLBACK_ARGS_DECL) \ { \ return m_CallbackFunction(PIPELINE_CALLBACK_ARGS_IMPL); \ } \ \ virtual bool equals(const CCallbackBase *callbackBase) \ { \ const CCallbackFunction *callbackFunction = \ dynamic_cast(callbackBase); \ if (!callbackFunction) return false; \ return m_CallbackFunction == callbackFunction->m_CallbackFunction; \ } \ \ private: \ TCallbackFunction *m_CallbackFunction; \ }; \ \ template \ class CCallbackMethod : public CCallbackBase \ { \ typedef TReturn (TClass::*TCallbackMethod)(PIPELINE_CALLBACK_ARGS_DECL); \ public: \ CCallbackMethod(TClass *callbackObject, TCallbackMethod callbackMethod) : m_CallbackObject(callbackObject), m_CallbackMethod(callbackMethod) \ { \ nlassert(m_CallbackObject); \ nlassert(m_CallbackMethod); \ } \ \ virtual ~CCallbackMethod() \ { \ m_CallbackObject = NULL; \ m_CallbackMethod = NULL; \ } \ \ virtual TReturn callback(PIPELINE_CALLBACK_ARGS_DECL) \ { \ return (m_CallbackObject->*m_CallbackMethod)(PIPELINE_CALLBACK_ARGS_IMPL); \ } \ \ virtual bool equals(const CCallbackBase *callbackBase) \ { \ const CCallbackMethod *callbackMethod = \ dynamic_cast(callbackBase); \ if (!callbackMethod) return false; \ return m_CallbackObject == callbackMethod->m_CallbackObject \ && m_CallbackMethod == callbackMethod->m_CallbackMethod; \ } \ \ private: \ TClass *m_CallbackObject; \ TCallbackMethod m_CallbackMethod; \ }; \ \ public: \ CCallback() : m_CallbackBase(NULL) \ { \ \ } \ \ CCallback(TCallbackFunction *callbackFunction) : m_CallbackBase(new CCallbackFunction(callbackFunction)) \ { \ nlassert(m_CallbackBase); \ m_CallbackBase->refAdd(); \ } \ \ template \ CCallback(TClass *callbackObject, TReturn (TClass::*callbackMethod)(PIPELINE_CALLBACK_ARGS_DECL)) : m_CallbackBase(new CCallbackMethod(callbackObject, callbackMethod)) \ { \ nlassert(m_CallbackBase); \ m_CallbackBase->refAdd(); \ } \ \ CCallback(const CCallback &callback) \ { \ m_CallbackBase = callback.m_CallbackBase; \ if (m_CallbackBase) \ m_CallbackBase->refAdd(); \ } \ \ CCallback &operator=(const CCallback &callback) \ { \ if (m_CallbackBase != callback.m_CallbackBase) \ { \ if (m_CallbackBase) \ m_CallbackBase->refRemove(); \ m_CallbackBase = callback.m_CallbackBase; \ if (m_CallbackBase) \ m_CallbackBase->refAdd(); \ } \ return *this; \ } \ \ ~CCallback() \ { \ if (m_CallbackBase) \ { \ m_CallbackBase->refRemove(); \ m_CallbackBase = NULL; \ } \ } \ \ TReturn callback(PIPELINE_CALLBACK_ARGS_DECL) \ { \ nlassert(m_CallbackBase); \ return m_CallbackBase->callback(PIPELINE_CALLBACK_ARGS_IMPL); \ } \ \ TReturn operator()(PIPELINE_CALLBACK_ARGS_DECL) \ { \ nlassert(m_CallbackBase); \ return m_CallbackBase->callback(PIPELINE_CALLBACK_ARGS_IMPL); \ } \ \ bool valid() const \ { \ return m_CallbackBase != NULL; \ } \ \ operator bool() const \ { \ return m_CallbackBase != NULL; \ } \ \ bool operator==(const CCallback &callback) \ { \ return m_CallbackBase->equals(callback.m_CallbackBase); \ } \ \ private: \ CCallbackBase *m_CallbackBase; \ \ }; /* class CCallback */ \ template class CCallback; #define PIPELINE_CALLBACK_ARGS_CLASS CCallback #define PIPELINE_CALLBACK_ARGS_TYPENAME #define PIPELINE_CALLBACK_ARGS_DECL #define PIPELINE_CALLBACK_ARGS_IMPL PIPELINE_CALLBACK_TEMPLATE #undef PIPELINE_CALLBACK_ARGS_CLASS #undef PIPELINE_CALLBACK_ARGS_TYPENAME #undef PIPELINE_CALLBACK_ARGS_DECL #undef PIPELINE_CALLBACK_ARGS_IMPL #define PIPELINE_CALLBACK_ARGS_CLASS CCallback #define PIPELINE_CALLBACK_ARGS_TYPENAME , typename TArgsA #define PIPELINE_CALLBACK_ARGS_DECL TArgsA argsA #define PIPELINE_CALLBACK_ARGS_IMPL argsA PIPELINE_CALLBACK_TEMPLATE #undef PIPELINE_CALLBACK_ARGS_CLASS #undef PIPELINE_CALLBACK_ARGS_TYPENAME #undef PIPELINE_CALLBACK_ARGS_DECL #undef PIPELINE_CALLBACK_ARGS_IMPL #define PIPELINE_CALLBACK_ARGS_CLASS CCallback #define PIPELINE_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB #define PIPELINE_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB #define PIPELINE_CALLBACK_ARGS_IMPL argsA, argsB PIPELINE_CALLBACK_TEMPLATE #undef PIPELINE_CALLBACK_ARGS_CLASS #undef PIPELINE_CALLBACK_ARGS_TYPENAME #undef PIPELINE_CALLBACK_ARGS_DECL #undef PIPELINE_CALLBACK_ARGS_IMPL #define PIPELINE_CALLBACK_ARGS_CLASS CCallback #define PIPELINE_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB, typename TArgsC #define PIPELINE_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB, TArgsC argsC #define PIPELINE_CALLBACK_ARGS_IMPL argsA, argsB, argsC PIPELINE_CALLBACK_TEMPLATE #undef PIPELINE_CALLBACK_ARGS_CLASS #undef PIPELINE_CALLBACK_ARGS_TYPENAME #undef PIPELINE_CALLBACK_ARGS_DECL #undef PIPELINE_CALLBACK_ARGS_IMPL #define PIPELINE_CALLBACK_ARGS_CLASS CCallback #define PIPELINE_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB, typename TArgsC, typename TArgsD #define PIPELINE_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB, TArgsC argsC, TArgsD argsD #define PIPELINE_CALLBACK_ARGS_IMPL argsA, argsB, argsC, argsD PIPELINE_CALLBACK_TEMPLATE #undef PIPELINE_CALLBACK_ARGS_CLASS #undef PIPELINE_CALLBACK_ARGS_TYPENAME #undef PIPELINE_CALLBACK_ARGS_DECL #undef PIPELINE_CALLBACK_ARGS_IMPL #define PIPELINE_CALLBACK_ARGS_CLASS CCallback #define PIPELINE_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB, typename TArgsC, typename TArgsD, typename TArgsE #define PIPELINE_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB, TArgsC argsC, TArgsD argsD, TArgsE argsE #define PIPELINE_CALLBACK_ARGS_IMPL argsA, argsB, argsC, argsD, argsE PIPELINE_CALLBACK_TEMPLATE #undef PIPELINE_CALLBACK_ARGS_CLASS #undef PIPELINE_CALLBACK_ARGS_TYPENAME #undef PIPELINE_CALLBACK_ARGS_DECL #undef PIPELINE_CALLBACK_ARGS_IMPL #define PIPELINE_CALLBACK_ARGS_CLASS CCallback #define PIPELINE_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB, typename TArgsC, typename TArgsD, typename TArgsE, typename TArgsF #define PIPELINE_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB, TArgsC argsC, TArgsD argsD, TArgsE argsE, TArgsF argsF #define PIPELINE_CALLBACK_ARGS_IMPL argsA, argsB, argsC, argsD, argsE, argsF PIPELINE_CALLBACK_TEMPLATE #undef PIPELINE_CALLBACK_ARGS_CLASS #undef PIPELINE_CALLBACK_ARGS_TYPENAME #undef PIPELINE_CALLBACK_ARGS_DECL #undef PIPELINE_CALLBACK_ARGS_IMPL #define PIPELINE_CALLBACK_ARGS_CLASS CCallback #define PIPELINE_CALLBACK_ARGS_TYPENAME , typename TArgsA, typename TArgsB, typename TArgsC, typename TArgsD, typename TArgsE, typename TArgsF, typename TArgsG #define PIPELINE_CALLBACK_ARGS_DECL TArgsA argsA, TArgsB argsB, TArgsC argsC, TArgsD argsD, TArgsE argsE, TArgsF argsF, TArgsG argsG #define PIPELINE_CALLBACK_ARGS_IMPL argsA, argsB, argsC, argsD, argsE, argsF, argsG PIPELINE_CALLBACK_TEMPLATE #undef PIPELINE_CALLBACK_ARGS_CLASS #undef PIPELINE_CALLBACK_ARGS_TYPENAME #undef PIPELINE_CALLBACK_ARGS_DECL #undef PIPELINE_CALLBACK_ARGS_IMPL #undef PIPELINE_CALLBACK_ARGS_CLASSNAME #undef PIPELINE_CALLBACK_TEMPLATE } /* namespace PIPELINE */ #endif /* #ifndef PIPELINE_CALLBACK_H */ /* end of file */