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