OpenNI 1.3.2

XnEvent.h

Go to the documentation of this file.
00001 /****************************************************************************
00002 *                                                                           *
00003 *  OpenNI 1.1 Alpha                                                         *
00004 *  Copyright (C) 2011 PrimeSense Ltd.                                       *
00005 *                                                                           *
00006 *  This file is part of OpenNI.                                             *
00007 *                                                                           *
00008 *  OpenNI is free software: you can redistribute it and/or modify           *
00009 *  it under the terms of the GNU Lesser General Public License as published *
00010 *  by the Free Software Foundation, either version 3 of the License, or     *
00011 *  (at your option) any later version.                                      *
00012 *                                                                           *
00013 *  OpenNI is distributed in the hope that it will be useful,                *
00014 *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00015 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the             *
00016 *  GNU Lesser General Public License for more details.                      *
00017 *                                                                           *
00018 *  You should have received a copy of the GNU Lesser General Public License *
00019 *  along with OpenNI. If not, see <http://www.gnu.org/licenses/>.           *
00020 *                                                                           *
00021 ****************************************************************************/
00022 #ifndef __XN_EVENT_H__
00023 #define __XN_EVENT_H__
00024 
00025 //---------------------------------------------------------------------------
00026 // Includes
00027 //---------------------------------------------------------------------------
00028 #include "XnCallback.h"
00029 #include "XnList.h"
00030 #include "XnTypes.h"
00031 #include "XnOSCpp.h"
00032 
00033 //---------------------------------------------------------------------------
00034 // Types
00035 //---------------------------------------------------------------------------
00036 class XnEventInterface
00037 {
00038 public:
00039     XnEventInterface() {}
00040     virtual ~XnEventInterface() {}
00041 
00042     typedef XnStatus (XN_CALLBACK_TYPE* HandlerPtr)(void* pCookie);
00043 
00044     virtual XnStatus Register(HandlerPtr pFunc, void* pCookie, XnCallbackHandle* pHandle = NULL) = 0;
00045     virtual XnStatus Unregister(XnCallbackHandle handle) = 0;
00046 };
00047 
00048 class XnEvent : public XnEventInterface
00049 {
00050 public:
00051     XnEvent() : m_hLock(0) 
00052     {
00053         xnOSCreateCriticalSection(&m_hLock);
00054     }
00055 
00056     virtual ~XnEvent()
00057     {
00058         Clear();
00059         xnOSCloseCriticalSection(&m_hLock);
00060     }
00061 
00062     XnStatus Register(HandlerPtr pFunc, void* pCookie, XnCallbackHandle* pHandle)
00063     {
00064         XnStatus nRetVal = XN_STATUS_OK;
00065 
00066         XN_VALIDATE_INPUT_PTR(pFunc);
00067 
00068         XnCallback* pCallback = NULL;
00069         XN_VALIDATE_NEW(pCallback, XnCallback, (XnFuncPtr)pFunc, pCookie);
00070 
00071         // always add to list of added (actual list will be updated in Raise method, to allow registering 
00072         // from a callback).
00073         {
00074             XnAutoCSLocker lock(m_hLock);
00075             nRetVal = m_ToBeAdded.AddLast(pCallback);
00076         }
00077 
00078         if (nRetVal != XN_STATUS_OK)
00079         {
00080             XN_DELETE(pCallback);
00081             return (nRetVal);
00082         }
00083 
00084         // return handle
00085         if (pHandle != NULL)
00086         {
00087             *pHandle = pCallback;
00088         }
00089 
00090         return XN_STATUS_OK;
00091     }
00092 
00093     XnStatus Unregister(XnCallbackHandle handle)
00094     {
00095         XnStatus nRetVal = XN_STATUS_OK;
00096 
00097         XnCallback* pObject = (XnCallback*)handle;
00098 
00099         // add it to a temp list, to allow unregistering from a callback (actual list will be updated in raise
00100         // function).
00101         {
00102             XnAutoCSLocker lock(m_hLock);
00103 
00104             // try to remove it from the ToBeAdded list.
00105             if (!RemoveCallback(m_ToBeAdded, pObject))
00106             {
00107                 // it's not in this list, so it's probably in the main list
00108                 nRetVal = m_ToBeRemoved.AddLast(pObject);
00109             }
00110         }
00111         XN_IS_STATUS_OK(nRetVal);
00112 
00113         return XN_STATUS_OK;
00114     }
00115 
00116     XnStatus Clear()
00117     {
00118         ApplyListChanges();
00119 
00120         for (XnCallbackPtrList::ConstIterator it = m_Handlers.begin(); it != m_Handlers.end(); ++it)
00121         {
00122             XnCallback* pCallback = *it;
00123             XN_DELETE(pCallback);
00124         }
00125 
00126         m_Handlers.Clear();
00127         m_ToBeRemoved.Clear();
00128         m_ToBeAdded.Clear();
00129         return (XN_STATUS_OK);
00130     }
00131 
00132 protected:
00133     XnStatus ApplyListChanges()
00134     {
00135         // first add all
00136         for (XnCallbackPtrList::ConstIterator it = m_ToBeAdded.begin(); it != m_ToBeAdded.end(); ++it)
00137         {
00138             m_Handlers.AddLast(*it);
00139         }
00140         m_ToBeAdded.Clear();
00141 
00142         // and now remove
00143         for (XnCallbackPtrList::ConstIterator it = m_ToBeRemoved.begin(); it != m_ToBeRemoved.end(); ++it)
00144         {
00145             XnCallback* pCallback = *it;
00146             RemoveCallback(m_Handlers, pCallback);
00147         }
00148         m_ToBeRemoved.Clear();
00149 
00150         return (XN_STATUS_OK);
00151     }
00152 
00153 #if (XN_PLATFORM == XN_PLATFORM_WIN32)
00154 #pragma warning (push)
00155 #pragma warning (disable: 4127)
00156 #endif
00157 
00158     XN_DECLARE_LIST(XnCallback*, XnCallbackPtrList)
00159 
00160 #if (XN_PLATFORM == XN_PLATFORM_WIN32)
00161 #pragma warning (pop)
00162 #endif
00163 
00164     XN_CRITICAL_SECTION_HANDLE m_hLock;
00165     XnCallbackPtrList m_Handlers;
00166     XnCallbackPtrList m_ToBeAdded;
00167     XnCallbackPtrList m_ToBeRemoved;
00168 
00169 private:
00170     XnBool RemoveCallback(XnCallbackPtrList& list, XnCallback* pCallback)
00171     {
00172         XnCallbackPtrList::Iterator handlerIt = list.Find(pCallback);
00173         if (handlerIt != list.end())
00174         {
00175             list.Remove(handlerIt);
00176             XN_DELETE(pCallback);
00177             return TRUE;
00178         }
00179 
00180         return FALSE;
00181     }
00182 };
00183 
00184 #define _XN_RAISE_WITH_RET_CODE(args)           \
00185     nRetVal = pFunc(args pCallback->pCookie);   \
00186     if (nRetVal != XN_STATUS_OK)                \
00187     {                                           \
00188         XnEvent::ApplyListChanges();            \
00189         return (nRetVal);                       \
00190     }
00191 
00192 #define _XN_RAISE_NO_RET_CODE(args)             \
00193     pFunc(args pCallback->pCookie);
00194 
00199 #define _XN_DECLARE_EVENT_CLASS(_class, _interface, _retVal, _raise, _signature, _raise_sign)               \
00200     class _interface : protected XnEvent                                                                    \
00201     {                                                                                                       \
00202     public:                                                                                                 \
00203         typedef _retVal (XN_CALLBACK_TYPE* HandlerPtr)(_signature);                                         \
00204         virtual XnStatus Register(HandlerPtr pFunc, void* pCookie, XnCallbackHandle* pHandle = NULL) = 0;   \
00205         virtual XnStatus Unregister(XnCallbackHandle handle) = 0;                                           \
00206     };                                                                                                      \
00207     class _class : public _interface                                                                        \
00208     {                                                                                                       \
00209     public:                                                                                                 \
00210         XnStatus Register(HandlerPtr pFunc, void* pCookie, XnCallbackHandle* pHandle = NULL)                \
00211         {                                                                                                   \
00212             return XnEvent::Register((XnEvent::HandlerPtr)pFunc, pCookie, pHandle);                         \
00213         }                                                                                                   \
00214         XnStatus Unregister(XnCallbackHandle handle)                                                        \
00215         {                                                                                                   \
00216             return XnEvent::Unregister(handle);                                                             \
00217         }                                                                                                   \
00218         XnStatus Raise(_raise_sign)                                                                         \
00219         {                                                                                                   \
00220             XnStatus nRetVal = XN_STATUS_OK;                                                                \
00221             XnAutoCSLocker lock(m_hLock);                                                                   \
00222             XnEvent::ApplyListChanges();                                                                    \
00223             XnEvent::XnCallbackPtrList::Iterator it = XnEvent::m_Handlers.begin();                          \
00224             for (; it != XnEvent::m_Handlers.end(); ++it)                                                   \
00225             {                                                                                               \
00226                 XnCallback* pCallback = *it;                                                                \
00227                 HandlerPtr pFunc = (HandlerPtr)pCallback->pFuncPtr;                                         \
00228                 _raise                                                                                      \
00229             }                                                                                               \
00230             XnEvent::ApplyListChanges();                                                                    \
00231             return (XN_STATUS_OK);                                                                          \
00232         }                                                                                                   \
00233         XnStatus Clear() { return XnEvent::Clear(); }                                                       \
00234     };
00235 
00236 #define _XN_SIGNATURE_0ARG()
00237 #define _XN_FULL_SIGNATURE_0ARG()   void* pCookie
00238 #define _XN_ARGS_0ARG()
00239 
00240 #define _XN_SIGNATURE_1ARG(_type1, _name1)  _type1 _name1
00241 #define _XN_FULL_SIGNATURE_1ARG(_type1, _name1) _type1 _name1, void* pCookie
00242 #define _XN_ARGS_1ARG(_name1) _name1,
00243 
00244 #define _XN_SIGNATURE_2ARG(_type1, _name1, _type2, _name2)  _type1 _name1, _type2 _name2
00245 #define _XN_FULL_SIGNATURE_2ARG(_type1, _name1, _type2, _name2) _type1 _name1, _type2 _name2, void* pCookie
00246 #define _XN_ARGS_2ARG(_name1, _name2) _name1, _name2,
00247 
00248 #define _XN_SIGNATURE_3ARG(_type1, _name1, _type2, _name2, _type3, _name3)  _type1 _name1, _type2 _name2, _type3 _name3
00249 #define _XN_FULL_SIGNATURE_3ARG(_type1, _name1, _type2, _name2, _type3, _name3) _type1 _name1, _type2 _name2, _type3 _name3, void* pCookie
00250 #define _XN_ARGS_3ARG(_name1, _name2, _name3) _name1, _name2, _name3,
00251 
00252 #define _XN_SIGNATURE_4ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4)  _type1 _name1, _type2 _name2, _type3 _name3, _type4 _name4
00253 #define _XN_FULL_SIGNATURE_4ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4) _type1 _name1, _type2 _name2, _type3 _name3, _type4 _name4, void* pCookie
00254 #define _XN_ARGS_4ARG(_name1, _name2, _name3, _name4) _name1, _name2, _name3, _name4,
00255 
00256 #define _XN_SIGNATURE_5ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4, _type5, _name5)  _type1 _name1, _type2 _name2, _type3 _name3, _type4 _name4, _type5 _name5
00257 #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
00258 #define _XN_ARGS_5ARG(_name1, _name2, _name3, _name4, _name5) _name1, _name2, _name3, _name4, _name5,
00259 
00261 #if XN_PLATFORM == XN_PLATFORM_WIN32
00262     #define XN_DECLARE_EVENT_0ARG(_class, _interface)                                           \
00263     __pragma(warning(push))\
00264     __pragma(warning(disable:4189))\
00265         _XN_DECLARE_EVENT_CLASS(_class, _interface, void, _XN_RAISE_NO_RET_CODE(_XN_ARGS_0ARG()), _XN_FULL_SIGNATURE_0ARG(), _XN_SIGNATURE_0ARG())\
00266     __pragma(warning(pop))
00267 #else
00268     #define XN_DECLARE_EVENT_0ARG(_class, _interface)                                           \
00269         _XN_DECLARE_EVENT_CLASS(_class, _interface, void, _XN_RAISE_NO_RET_CODE(_XN_ARGS_0ARG()), _XN_FULL_SIGNATURE_0ARG(), _XN_SIGNATURE_0ARG())
00270 #endif
00271 
00272 #define XN_DECLARE_EVENT_0ARG_RETVAL(_class, _interface)                                    \
00273     _XN_DECLARE_EVENT_CLASS(_class, _interface, XnStatus, _XN_RAISE_WITH_RET_CODE(_XN_ARGS_0ARG()), _XN_FULL_SIGNATURE_0ARG(), _XN_SIGNATURE_0ARG())
00274 
00275 #define XN_DECLARE_EVENT_1ARG(_class, _interface, _type1, _name1)                                           \
00276     _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))
00277 
00278 #define XN_DECLARE_EVENT_1ARG_RETVAL(_class, _interface, _type1, _name1)                                    \
00279     _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))
00280 
00281 #define XN_DECLARE_EVENT_2ARG(_class, _interface, _type1, _name1, _type2, _name2)                           \
00282     _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))
00283 
00284 #define XN_DECLARE_EVENT_2ARG_RETVAL(_class, _interface, _type1, _name1, _type2, _name2)                    \
00285     _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))
00286 
00287 #define XN_DECLARE_EVENT_3ARG(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3)           \
00288     _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))
00289 
00290 #define XN_DECLARE_EVENT_3ARG_RETVAL(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3)    \
00291     _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))
00292 
00293 #define XN_DECLARE_EVENT_4ARG(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4)           \
00294     _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))
00295 
00296 #define XN_DECLARE_EVENT_4ARG_RETVAL(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4)            \
00297     _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))
00298 
00299 #define XN_DECLARE_EVENT_5ARG(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4, _type5, _name5)           \
00300     _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))
00301 
00302 #define XN_DECLARE_EVENT_5ARG_RETVAL(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4, _type5, _name5)            \
00303     _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))
00304 
00305 #endif //__XN_EVENT_H__