/**************************************************************************** * * * OpenNI 1.x Alpha * * Copyright (C) 2011 PrimeSense Ltd. * * * * This file is part of OpenNI. * * * * OpenNI is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as published * * by the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * OpenNI 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 Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public License * * along with OpenNI. If not, see . * * * ****************************************************************************/ #ifndef __XN_EVENT_H__ #define __XN_EVENT_H__ //--------------------------------------------------------------------------- // Includes //--------------------------------------------------------------------------- #include "XnCallback.h" #include "XnList.h" #include "XnTypes.h" #include "XnOSCpp.h" //--------------------------------------------------------------------------- // Types //--------------------------------------------------------------------------- class XnEventInterface { public: XnEventInterface() {} virtual ~XnEventInterface() {} typedef XnStatus (XN_CALLBACK_TYPE* HandlerPtr)(void* pCookie); virtual XnStatus Register(HandlerPtr pFunc, void* pCookie, XnCallbackHandle* pHandle = NULL) = 0; virtual XnStatus Unregister(XnCallbackHandle handle) = 0; }; class XnEvent : public XnEventInterface { public: XnEvent() : m_hLock(0) { xnOSCreateCriticalSection(&m_hLock); } virtual ~XnEvent() { Clear(); xnOSCloseCriticalSection(&m_hLock); } XnStatus Register(HandlerPtr pFunc, void* pCookie, XnCallbackHandle* pHandle) { XnStatus nRetVal = XN_STATUS_OK; XN_VALIDATE_INPUT_PTR(pFunc); XnCallback* pCallback = NULL; XN_VALIDATE_NEW(pCallback, XnCallback, (XnFuncPtr)pFunc, pCookie); // always add to list of added (actual list will be updated in Raise method, to allow registering // from a callback). { XnAutoCSLocker lock(m_hLock); nRetVal = m_ToBeAdded.AddLast(pCallback); } if (nRetVal != XN_STATUS_OK) { XN_DELETE(pCallback); return (nRetVal); } // return handle if (pHandle != NULL) { *pHandle = pCallback; } return XN_STATUS_OK; } XnStatus Unregister(XnCallbackHandle handle) { XnStatus nRetVal = XN_STATUS_OK; XnCallback* pObject = (XnCallback*)handle; // add it to a temp list, to allow unregistering from a callback (actual list will be updated in raise // function). { XnAutoCSLocker lock(m_hLock); // try to remove it from the ToBeAdded list. if (!RemoveCallback(m_ToBeAdded, pObject)) { // it's not in this list, so it's probably in the main list nRetVal = m_ToBeRemoved.AddLast(pObject); } } XN_IS_STATUS_OK(nRetVal); return XN_STATUS_OK; } XnStatus Clear() { ApplyListChanges(); for (XnCallbackPtrList::ConstIterator it = m_Handlers.begin(); it != m_Handlers.end(); ++it) { XnCallback* pCallback = *it; XN_DELETE(pCallback); } m_Handlers.Clear(); m_ToBeRemoved.Clear(); m_ToBeAdded.Clear(); return (XN_STATUS_OK); } protected: XnStatus ApplyListChanges() { // first add all for (XnCallbackPtrList::ConstIterator it = m_ToBeAdded.begin(); it != m_ToBeAdded.end(); ++it) { m_Handlers.AddLast(*it); } m_ToBeAdded.Clear(); // and now remove for (XnCallbackPtrList::ConstIterator it = m_ToBeRemoved.begin(); it != m_ToBeRemoved.end(); ++it) { XnCallback* pCallback = *it; RemoveCallback(m_Handlers, pCallback); } m_ToBeRemoved.Clear(); return (XN_STATUS_OK); } #if (XN_PLATFORM == XN_PLATFORM_WIN32) #pragma warning (push) #pragma warning (disable: 4127) #endif XN_DECLARE_LIST(XnCallback*, XnCallbackPtrList) #if (XN_PLATFORM == XN_PLATFORM_WIN32) #pragma warning (pop) #endif XN_CRITICAL_SECTION_HANDLE m_hLock; XnCallbackPtrList m_Handlers; XnCallbackPtrList m_ToBeAdded; XnCallbackPtrList m_ToBeRemoved; private: XnBool RemoveCallback(XnCallbackPtrList& list, XnCallback* pCallback) { XnCallbackPtrList::Iterator handlerIt = list.Find(pCallback); if (handlerIt != list.end()) { list.Remove(handlerIt); XN_DELETE(pCallback); return TRUE; } return FALSE; } }; #define _XN_RAISE_WITH_RET_CODE(args) \ { \ XnStatus nRetVal = pFunc(args pCallback->pCookie); \ if (nRetVal != XN_STATUS_OK) \ { \ XnEvent::ApplyListChanges(); \ return (nRetVal); \ } \ } #define _XN_RAISE_NO_RET_CODE(args) \ pFunc(args pCallback->pCookie); /** * Declares a class inheriting from XnEvent, that can be used as an event with specific signature. * It is highly recommended not to use this macro directly. */ #define _XN_DECLARE_EVENT_CLASS(_class, _interface, _retVal, _raise, _signature, _raise_sign) \ XN_PRAGMA_START_DISABLED_WARNING_SECTION(XN_HIDES_PARENT_METHOD_WARNING_ID) \ class _interface : protected XnEvent \ { \ public: \ typedef _retVal (XN_CALLBACK_TYPE* HandlerPtr)(_signature); \ virtual XnStatus Register(HandlerPtr pFunc, void* pCookie, XnCallbackHandle* pHandle = NULL) = 0; \ virtual XnStatus Unregister(XnCallbackHandle handle) = 0; \ }; \ class _class : public _interface \ { \ public: \ XnStatus Register(HandlerPtr pFunc, void* pCookie, XnCallbackHandle* pHandle = NULL) \ { \ return XnEvent::Register((XnEvent::HandlerPtr)pFunc, pCookie, pHandle); \ } \ XnStatus Unregister(XnCallbackHandle handle) \ { \ return XnEvent::Unregister(handle); \ } \ XnStatus Raise(_raise_sign) \ { \ XnAutoCSLocker lock(m_hLock); \ XnEvent::ApplyListChanges(); \ XnEvent::XnCallbackPtrList::Iterator it = XnEvent::m_Handlers.begin(); \ for (; it != XnEvent::m_Handlers.end(); ++it) \ { \ XnCallback* pCallback = *it; \ HandlerPtr pFunc = (HandlerPtr)pCallback->pFuncPtr; \ _raise \ } \ XnEvent::ApplyListChanges(); \ return (XN_STATUS_OK); \ } \ XnStatus Clear() { return XnEvent::Clear(); } \ }; \ XN_PRAGMA_STOP_DISABLED_WARNING_SECTION #define _XN_SIGNATURE_0ARG() #define _XN_FULL_SIGNATURE_0ARG() void* pCookie #define _XN_ARGS_0ARG() #define _XN_SIGNATURE_1ARG(_type1, _name1) _type1 _name1 #define _XN_FULL_SIGNATURE_1ARG(_type1, _name1) _type1 _name1, void* pCookie #define _XN_ARGS_1ARG(_name1) _name1, #define _XN_SIGNATURE_2ARG(_type1, _name1, _type2, _name2) _type1 _name1, _type2 _name2 #define _XN_FULL_SIGNATURE_2ARG(_type1, _name1, _type2, _name2) _type1 _name1, _type2 _name2, void* pCookie #define _XN_ARGS_2ARG(_name1, _name2) _name1, _name2, #define _XN_SIGNATURE_3ARG(_type1, _name1, _type2, _name2, _type3, _name3) _type1 _name1, _type2 _name2, _type3 _name3 #define _XN_FULL_SIGNATURE_3ARG(_type1, _name1, _type2, _name2, _type3, _name3) _type1 _name1, _type2 _name2, _type3 _name3, void* pCookie #define _XN_ARGS_3ARG(_name1, _name2, _name3) _name1, _name2, _name3, #define _XN_SIGNATURE_4ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4) _type1 _name1, _type2 _name2, _type3 _name3, _type4 _name4 #define _XN_FULL_SIGNATURE_4ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4) _type1 _name1, _type2 _name2, _type3 _name3, _type4 _name4, void* pCookie #define _XN_ARGS_4ARG(_name1, _name2, _name3, _name4) _name1, _name2, _name3, _name4, #define _XN_SIGNATURE_5ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4, _type5, _name5) _type1 _name1, _type2 _name2, _type3 _name3, _type4 _name4, _type5 _name5 #define _XN_FULL_SIGNATURE_5ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4, _type5, _name5) _type1 _name1, _type2 _name2, _type3 _name3, _type4 _name4, _type5 _name5, void* pCookie #define _XN_ARGS_5ARG(_name1, _name2, _name3, _name4, _name5) _name1, _name2, _name3, _name4, _name5, /** Declares an event class */ #define XN_DECLARE_EVENT_0ARG(_class, _interface) \ _XN_DECLARE_EVENT_CLASS(_class, _interface, void, _XN_RAISE_NO_RET_CODE(_XN_ARGS_0ARG()), _XN_FULL_SIGNATURE_0ARG(), _XN_SIGNATURE_0ARG()) #define XN_DECLARE_EVENT_0ARG_RETVAL(_class, _interface) \ _XN_DECLARE_EVENT_CLASS(_class, _interface, XnStatus, _XN_RAISE_WITH_RET_CODE(_XN_ARGS_0ARG()), _XN_FULL_SIGNATURE_0ARG(), _XN_SIGNATURE_0ARG()) #define XN_DECLARE_EVENT_1ARG(_class, _interface, _type1, _name1) \ _XN_DECLARE_EVENT_CLASS(_class, _interface, void, _XN_RAISE_NO_RET_CODE(_XN_ARGS_1ARG(_name1)), _XN_FULL_SIGNATURE_1ARG(_type1, _name1), _XN_SIGNATURE_1ARG(_type1, _name1)) #define XN_DECLARE_EVENT_1ARG_RETVAL(_class, _interface, _type1, _name1) \ _XN_DECLARE_EVENT_CLASS(_class, _interface, XnStatus, _XN_RAISE_WITH_RET_CODE(_XN_ARGS_1ARG(_name1)), _XN_FULL_SIGNATURE_1ARG(_type1, _name1), _XN_SIGNATURE_1ARG(_type1, _name1)) #define XN_DECLARE_EVENT_2ARG(_class, _interface, _type1, _name1, _type2, _name2) \ _XN_DECLARE_EVENT_CLASS(_class, _interface, void, _XN_RAISE_NO_RET_CODE(_XN_ARGS_2ARG(_name1, _name2)), _XN_FULL_SIGNATURE_2ARG(_type1, _name1, _type2, _name2), _XN_SIGNATURE_2ARG(_type1, _name1, _type2, _name2)) #define XN_DECLARE_EVENT_2ARG_RETVAL(_class, _interface, _type1, _name1, _type2, _name2) \ _XN_DECLARE_EVENT_CLASS(_class, _interface, XnStatus, _XN_RAISE_WITH_RET_CODE(_XN_ARGS_2ARG(_name1, _name2)), _XN_FULL_SIGNATURE_2ARG(_type1, _name1, _type2, _name2), _XN_SIGNATURE_2ARG(_type1, _name1, _type2, _name2)) #define XN_DECLARE_EVENT_3ARG(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3) \ _XN_DECLARE_EVENT_CLASS(_class, _interface, void, _XN_RAISE_NO_RET_CODE(_XN_ARGS_3ARG(_name1, _name2, _name3)), _XN_FULL_SIGNATURE_3ARG(_type1, _name1, _type2, _name2, _type3, _name3), _XN_SIGNATURE_3ARG(_type1, _name1, _type2, _name2, _type3, _name3)) #define XN_DECLARE_EVENT_3ARG_RETVAL(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3) \ _XN_DECLARE_EVENT_CLASS(_class, _interface, XnStatus, _XN_RAISE_WITH_RET_CODE(_XN_ARGS_3ARG(_name1, _name2, _name3)), _XN_FULL_SIGNATURE_3ARG(_type1, _name1, _type2, _name2, _type3, _name3), _XN_SIGNATURE_3ARG(_type1, _name1, _type2, _name2, _type3, _name3)) #define XN_DECLARE_EVENT_4ARG(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4) \ _XN_DECLARE_EVENT_CLASS(_class, _interface, void, _XN_RAISE_NO_RET_CODE(_XN_ARGS_4ARG(_name1, _name2, _name3, _name4)), _XN_FULL_SIGNATURE_4ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4), _XN_SIGNATURE_4ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4)) #define XN_DECLARE_EVENT_4ARG_RETVAL(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4) \ _XN_DECLARE_EVENT_CLASS(_class, _interface, XnStatus, _XN_RAISE_WITH_RET_CODE(_XN_ARGS_4ARG(_name1, _name2, _name3, _name4)), _XN_FULL_SIGNATURE_4ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4), _XN_SIGNATURE_4ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4)) #define XN_DECLARE_EVENT_5ARG(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4, _type5, _name5) \ _XN_DECLARE_EVENT_CLASS(_class, _interface, void, _XN_RAISE_NO_RET_CODE(_XN_ARGS_5ARG(_name1, _name2, _name3, _name4, _name5)), _XN_FULL_SIGNATURE_5ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4, _type5, _name5), _XN_SIGNATURE_5ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4, _type5, _name5)) #define XN_DECLARE_EVENT_5ARG_RETVAL(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4, _type5, _name5) \ _XN_DECLARE_EVENT_CLASS(_class, _interface, XnStatus, _XN_RAISE_WITH_RET_CODE(_XN_ARGS_5ARG(_name1, _name2, _name3, _name4, _name5)), _XN_FULL_SIGNATURE_5ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4, _type5, _name5), _XN_SIGNATURE_5ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4, _type5, _name5)) #endif //__XN_EVENT_H__