OpenNI 1.0.0
XnEvent.h
Go to the documentation of this file.
00001 /*****************************************************************************
00002 *                                                                            *
00003 *  OpenNI 1.0 Alpha                                                          *
00004 *  Copyright (C) 2010 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 
00023 
00024 
00025 #ifndef __XN_EVENT_H__
00026 #define __XN_EVENT_H__
00027 
00028 //---------------------------------------------------------------------------
00029 // Includes
00030 //---------------------------------------------------------------------------
00031 #include "XnCallback.h"
00032 #include "XnList.h"
00033 #include "XnTypes.h"
00034 #include "XnOSCpp.h"
00035 
00036 //---------------------------------------------------------------------------
00037 // Types
00038 //---------------------------------------------------------------------------
00039 class XnEventInterface
00040 {
00041 public:
00042     XnEventInterface() {}
00043     virtual ~XnEventInterface() {}
00044 
00045     typedef XnStatus (XN_CALLBACK_TYPE* HandlerPtr)(void* pCookie);
00046 
00047     virtual XnStatus Register(HandlerPtr pFunc, void* pCookie, XnCallbackHandle* pHandle = NULL) = 0;
00048     virtual XnStatus Unregister(XnCallbackHandle handle) = 0;
00049 };
00050 
00051 class XnEvent : public XnEventInterface
00052 {
00053 public:
00054     XnEvent() : m_hLock(0) 
00055     {
00056         xnOSCreateCriticalSection(&m_hLock);
00057     }
00058 
00059     ~XnEvent()
00060     {
00061         Clear();
00062         xnOSCloseCriticalSection(&m_hLock);
00063     }
00064 
00065     XnStatus Register(HandlerPtr pFunc, void* pCookie, XnCallbackHandle* pHandle)
00066     {
00067         XnStatus nRetVal = XN_STATUS_OK;
00068 
00069         XN_VALIDATE_INPUT_PTR(pFunc);
00070 
00071         XnCallback* pCallback = NULL;
00072         XN_VALIDATE_NEW(pCallback, XnCallback, (void*)pFunc, pCookie);
00073 
00074         // always add to list of added (actual list will be updated in Raise method, to allow registering 
00075         // from a callback).
00076         {
00077             XnAutoCSLocker lock(m_hLock);
00078             nRetVal = m_ToBeAdded.AddLast(pCallback);
00079         }
00080 
00081         if (nRetVal != XN_STATUS_OK)
00082         {
00083             XN_DELETE(pCallback);
00084             return (nRetVal);
00085         }
00086 
00087         // return handle
00088         if (pHandle != NULL)
00089         {
00090             *pHandle = pCallback;
00091         }
00092 
00093         return XN_STATUS_OK;
00094     }
00095 
00096     XnStatus Unregister(XnCallbackHandle handle)
00097     {
00098         XnStatus nRetVal = XN_STATUS_OK;
00099 
00100         XnCallback* pObject = (XnCallback*)handle;
00101 
00102         // add it to a temp list, to allow unregistering from a callback (actual list will be updated in raise
00103         // function).
00104         {
00105             XnAutoCSLocker lock(m_hLock);
00106             nRetVal = m_ToBeRemoved.AddLast(pObject);
00107         }
00108         XN_IS_STATUS_OK(nRetVal);
00109 
00110         return XN_STATUS_OK;
00111     }
00112 
00113     XnStatus Clear()
00114     {
00115         ApplyListChanges();
00116 
00117         for (XnCallbackPtrList::ConstIterator it = m_Handlers.begin(); it != m_Handlers.end(); ++it)
00118         {
00119             XnCallback* pCallback = *it;
00120             XN_DELETE(pCallback);
00121         }
00122 
00123         m_Handlers.Clear();
00124         m_ToBeRemoved.Clear();
00125         m_ToBeAdded.Clear();
00126         return (XN_STATUS_OK);
00127     }
00128 
00129 protected:
00130     XnStatus ApplyListChanges()
00131     {
00132         XnStatus nRetVal = XN_STATUS_OK;
00133 
00134         // first add all
00135         for (XnCallbackPtrList::ConstIterator it = m_ToBeAdded.begin(); it != m_ToBeAdded.end(); ++it)
00136         {
00137             m_Handlers.AddLast(*it);
00138         }
00139         m_ToBeAdded.Clear();
00140 
00141         // and now remove
00142         for (XnCallbackPtrList::ConstIterator it = m_ToBeRemoved.begin(); it != m_ToBeRemoved.end(); ++it)
00143         {
00144             XnCallback* pCallback = *it;
00145 
00146             // check if it's in the list
00147             XnCallbackPtrList::Iterator handlerIt = m_Handlers.Find(pCallback);
00148             if (handlerIt != m_Handlers.end())
00149             {
00150                 m_Handlers.Remove(handlerIt);
00151             }
00152 
00153             XN_DELETE(pCallback);
00154         }
00155         m_ToBeRemoved.Clear();
00156 
00157         return (XN_STATUS_OK);
00158     }
00159 
00160     XN_DECLARE_LIST(XnCallback*, XnCallbackPtrList)
00161 
00162     XN_CRITICAL_SECTION_HANDLE m_hLock;
00163     XnCallbackPtrList m_Handlers;
00164     XnCallbackPtrList m_ToBeAdded;
00165     XnCallbackPtrList m_ToBeRemoved;
00166 };
00167 
00168 #define _XN_RAISE_WITH_RET_CODE(args)           \
00169     nRetVal = pFunc(args pCallback->pCookie);   \
00170     if (nRetVal != XN_STATUS_OK)                \
00171     {                                           \
00172         XnEvent::ApplyListChanges();            \
00173         return (nRetVal);                       \
00174     }
00175 
00176 #define _XN_RAISE_NO_RET_CODE(args)             \
00177     pFunc(args pCallback->pCookie);
00178 
00183 #define _XN_DECLARE_EVENT_CLASS(_class, _interface, _retVal, _raise, _signature, _raise_sign)               \
00184     class _interface : protected XnEvent                                                                    \
00185     {                                                                                                       \
00186     public:                                                                                                 \
00187         typedef _retVal (XN_CALLBACK_TYPE* HandlerPtr)(_signature);                                         \
00188         virtual XnStatus Register(HandlerPtr pFunc, void* pCookie, XnCallbackHandle* pHandle = NULL) = 0;   \
00189         virtual XnStatus Unregister(XnCallbackHandle handle) = 0;                                           \
00190     };                                                                                                      \
00191     class _class : public _interface                                                                        \
00192     {                                                                                                       \
00193     public:                                                                                                 \
00194         XnStatus Register(HandlerPtr pFunc, void* pCookie, XnCallbackHandle* pHandle = NULL)                \
00195         {                                                                                                   \
00196             return XnEvent::Register((XnEvent::HandlerPtr)pFunc, pCookie, pHandle);                         \
00197         }                                                                                                   \
00198         XnStatus Unregister(XnCallbackHandle handle)                                                        \
00199         {                                                                                                   \
00200             return XnEvent::Unregister(handle);                                                             \
00201         }                                                                                                   \
00202         XnStatus Raise(_raise_sign)                                                                         \
00203         {                                                                                                   \
00204             XnStatus nRetVal = XN_STATUS_OK;                                                                \
00205             XnAutoCSLocker lock(m_hLock);                                                                   \
00206             XnEvent::ApplyListChanges();                                                                    \
00207             XnEvent::XnCallbackPtrList::Iterator it = XnEvent::m_Handlers.begin();                          \
00208             for (; it != XnEvent::m_Handlers.end(); ++it)                                                   \
00209             {                                                                                               \
00210                 XnCallback* pCallback = *it;                                                                \
00211                 HandlerPtr pFunc = (HandlerPtr)pCallback->pFuncPtr;                                         \
00212                 _raise                                                                                      \
00213             }                                                                                               \
00214             XnEvent::ApplyListChanges();                                                                    \
00215             return (XN_STATUS_OK);                                                                          \
00216         }                                                                                                   \
00217         XnStatus Clear() { return XnEvent::Clear(); }                                                       \
00218     };
00219 
00220 #define _XN_SIGNATURE_0ARG()
00221 #define _XN_FULL_SIGNATURE_0ARG()   void* pCookie
00222 #define _XN_ARGS_0ARG()
00223 
00224 #define _XN_SIGNATURE_1ARG(_type1, _name1)  _type1 _name1
00225 #define _XN_FULL_SIGNATURE_1ARG(_type1, _name1) _type1 _name1, void* pCookie
00226 #define _XN_ARGS_1ARG(_name1) _name1,
00227 
00228 #define _XN_SIGNATURE_2ARG(_type1, _name1, _type2, _name2)  _type1 _name1, _type2 _name2
00229 #define _XN_FULL_SIGNATURE_2ARG(_type1, _name1, _type2, _name2) _type1 _name1, _type2 _name2, void* pCookie
00230 #define _XN_ARGS_2ARG(_name1, _name2) _name1, _name2,
00231 
00232 #define _XN_SIGNATURE_3ARG(_type1, _name1, _type2, _name2, _type3, _name3)  _type1 _name1, _type2 _name2, _type3 _name3
00233 #define _XN_FULL_SIGNATURE_3ARG(_type1, _name1, _type2, _name2, _type3, _name3) _type1 _name1, _type2 _name2, _type3 _name3, void* pCookie
00234 #define _XN_ARGS_3ARG(_name1, _name2, _name3) _name1, _name2, _name3,
00235 
00236 #define _XN_SIGNATURE_4ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4)  _type1 _name1, _type2 _name2, _type3 _name3, _type4 _name4
00237 #define _XN_FULL_SIGNATURE_4ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4) _type1 _name1, _type2 _name2, _type3 _name3, _type4 _name4, void* pCookie
00238 #define _XN_ARGS_4ARG(_name1, _name2, _name3, _name4) _name1, _name2, _name3, _name4,
00239 
00240 #define _XN_SIGNATURE_5ARG(_type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4, _type5, _name5)  _type1 _name1, _type2 _name2, _type3 _name3, _type4 _name4, _type5 _name5
00241 #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
00242 #define _XN_ARGS_5ARG(_name1, _name2, _name3, _name4, _name5) _name1, _name2, _name3, _name4, _name5,
00243 
00245 #define XN_DECLARE_EVENT_0ARG(_class, _interface)                                           \
00246     _XN_DECLARE_EVENT_CLASS(_class, _interface, void, _XN_RAISE_NO_RET_CODE(_XN_ARGS_0ARG()), _XN_FULL_SIGNATURE_0ARG(), _XN_SIGNATURE_0ARG())
00247 
00248 #define XN_DECLARE_EVENT_0ARG_RETVAL(_class, _interface)                                    \
00249     _XN_DECLARE_EVENT_CLASS(_class, _interface, XnStatus, _XN_RAISE_WITH_RET_CODE(_XN_ARGS_0ARG()), _XN_FULL_SIGNATURE_0ARG(), _XN_SIGNATURE_0ARG())
00250 
00251 #define XN_DECLARE_EVENT_1ARG(_class, _interface, _type1, _name1)                                           \
00252     _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))
00253 
00254 #define XN_DECLARE_EVENT_1ARG_RETVAL(_class, _interface, _type1, _name1)                                    \
00255     _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))
00256 
00257 #define XN_DECLARE_EVENT_2ARG(_class, _interface, _type1, _name1, _type2, _name2)                           \
00258     _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))
00259 
00260 #define XN_DECLARE_EVENT_2ARG_RETVAL(_class, _interface, _type1, _name1, _type2, _name2)                    \
00261     _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))
00262 
00263 #define XN_DECLARE_EVENT_3ARG(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3)           \
00264     _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))
00265 
00266 #define XN_DECLARE_EVENT_3ARG_RETVAL(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3)    \
00267     _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))
00268 
00269 #define XN_DECLARE_EVENT_4ARG(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4)           \
00270     _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))
00271 
00272 #define XN_DECLARE_EVENT_4ARG_RETVAL(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4)            \
00273     _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))
00274 
00275 #define XN_DECLARE_EVENT_5ARG(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4, _type5, _name5)           \
00276     _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))
00277 
00278 #define XN_DECLARE_EVENT_5ARG_RETVAL(_class, _interface, _type1, _name1, _type2, _name2, _type3, _name3, _type4, _name4, _type5, _name5)            \
00279     _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))
00280 
00281 #endif //__XN_EVENT_H__