OpenNI 1.5.7
XnEventT.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_T_H_
00022 #define _XN_EVENT_T_H_ 
00023 
00024 //---------------------------------------------------------------------------
00025 // Includes
00026 //---------------------------------------------------------------------------
00027 #include "XnOSCpp.h"
00028 #include "XnListT.h"
00029 #include "XnTypes.h"
00030 
00031 //---------------------------------------------------------------------------
00032 // Types
00033 //---------------------------------------------------------------------------
00034 
00040 template<typename FuncPtr>
00041 struct XnCallbackT
00042 {
00043     XnCallbackT(FuncPtr func, void* cookie) : pFunc(func), pCookie(cookie) {}
00044 
00045     FuncPtr pFunc;
00046     void* pCookie;
00047 };
00048 
00054 template<typename FuncPtr>
00055 class XnEventInterfaceT
00056 {
00057 public:
00058     typedef FuncPtr HandlerPtr;
00059     typedef XnCallbackT<FuncPtr> TCallback;
00060     typedef XnEventInterfaceT TInterface;
00061 
00062     ~XnEventInterfaceT()
00063     {
00064         Clear();
00065         xnOSCloseCriticalSection(&m_hLock);
00066     }
00067 
00068     XnStatus Register(FuncPtr pFunc, void* pCookie, XnCallbackHandle& hCallback)
00069     {
00070         XnStatus nRetVal = XN_STATUS_OK;
00071 
00072         XN_VALIDATE_INPUT_PTR(pFunc);
00073 
00074         TCallback* pCallback = NULL;
00075         XN_VALIDATE_NEW(pCallback, TCallback, pFunc, pCookie);
00076 
00077         // always add to list of added (actual list will be updated in Raise method, to allow registering 
00078         // from a callback).
00079         {
00080             XnAutoCSLocker locker(m_hLock);
00081             nRetVal = m_toAdd.AddLast(pCallback);
00082         }
00083 
00084         if (nRetVal != XN_STATUS_OK)
00085         {
00086             XN_DELETE(pCallback);
00087             return nRetVal;
00088         }
00089 
00090         // return handle
00091         hCallback = (XnCallbackHandle)pCallback;
00092 
00093         return XN_STATUS_OK;
00094     }
00095 
00096     XnStatus Unregister(XnCallbackHandle hCallback)
00097     {
00098         XnStatus nRetVal = XN_STATUS_OK;
00099 
00100         TCallback* pCallback = (TCallback*)hCallback;
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 locker(m_hLock);
00106 
00107             // try to remove it from the ToBeAdded list.
00108             if (!RemoveCallback(m_toAdd, pCallback))
00109             {
00110                 // it's not in this list, so it's probably in the main list
00111                 nRetVal = m_toRemove.AddLast(pCallback);
00112             }
00113         }
00114         XN_IS_STATUS_OK(nRetVal);
00115 
00116         return XN_STATUS_OK;
00117     }
00118 
00119 protected:
00120     typedef XnListT<TCallback*> CallbackPtrList;
00121 
00122     // Constructors are protected, so that this class cannot be instantiated directly.
00123     XnEventInterfaceT()
00124     {
00125         Init();
00126     }
00127 
00128     XnEventInterfaceT(const XnEventInterfaceT& other)
00129     {
00130         Init();
00131         *this = other;
00132     }
00133 
00134     XnEventInterfaceT& operator=(const XnEventInterfaceT& other)
00135     {
00136         Clear();
00137 
00138         // lock other one (so it won't change while being copied)
00139         XnAutoCSLocker otherLocker(other.m_hLock);
00140         // lock this one (we're making changes)
00141         XnAutoCSLocker locker(m_hLock);
00142 
00143         m_callbacks = other.m_callbacks;
00144         m_toAdd = other.m_toAdd;
00145         m_toRemove = other.m_toRemove;
00146 
00147         ApplyListChanges();
00148 
00149         return *this;
00150     }
00151 
00152     XnStatus Clear()
00153     {
00154         XnAutoCSLocker locker(m_hLock);
00155         ApplyListChanges();
00156 
00157         for (typename CallbackPtrList::ConstIterator it = m_callbacks.Begin(); it != m_callbacks.End(); ++it)
00158         {
00159             TCallback* pCallback = *it;
00160             XN_DELETE(pCallback);
00161         }
00162 
00163         m_callbacks.Clear();
00164         m_toRemove.Clear();
00165         m_toAdd.Clear();
00166         return (XN_STATUS_OK);
00167     }
00168 
00169     XnStatus ApplyListChanges()
00170     {
00171         XnAutoCSLocker locker(m_hLock);
00172 
00173         // first add all
00174         for (typename CallbackPtrList::ConstIterator it = m_toAdd.Begin(); it != m_toAdd.End(); ++it)
00175         {
00176             m_callbacks.AddLast(*it);
00177         }
00178         m_toAdd.Clear();
00179 
00180         // and now remove
00181         for (typename CallbackPtrList::ConstIterator it = m_toRemove.Begin(); it != m_toRemove.End(); ++it)
00182         {
00183             TCallback* pCallback = *it;
00184             RemoveCallback(m_callbacks, pCallback);
00185         }
00186         m_toRemove.Clear();
00187 
00188         return (XN_STATUS_OK);
00189     }
00190 
00191     XnBool RemoveCallback(CallbackPtrList& list, TCallback* pCallback)
00192     {
00193         typename CallbackPtrList::Iterator it = list.Find(pCallback);
00194         if (it != list.End())
00195         {
00196             list.Remove(it);
00197             XN_DELETE(pCallback);
00198             return TRUE;
00199         }
00200 
00201         return FALSE;
00202     }
00203 
00204     XN_CRITICAL_SECTION_HANDLE m_hLock;
00205     CallbackPtrList m_callbacks;
00206     CallbackPtrList m_toAdd;
00207     CallbackPtrList m_toRemove;
00208 
00209 private:
00210     void Init()
00211     {
00212         m_hLock = NULL;
00213         XnStatus nRetVal = xnOSCreateCriticalSection(&m_hLock);
00214         if (nRetVal != XN_STATUS_OK)
00215         {
00216             XN_ASSERT(FALSE);
00217         }
00218     }
00219 };
00220 
00221 // Handlers
00222 struct XnHandlerFuncNoArgs
00223 {
00224     typedef void (XN_CALLBACK_TYPE* FuncPtr)(void* pCookie);
00225 };
00226 
00227 template<class TArg1>
00228 struct XnHandlerFunc1Arg
00229 {
00230     typedef void (XN_CALLBACK_TYPE* FuncPtr)(TArg1 arg1, void* pCookie);
00231 };
00232 
00233 template<class TArg1, class TArg2>
00234 struct XnHandlerFunc2Args
00235 {
00236     typedef void (XN_CALLBACK_TYPE* FuncPtr)(TArg1 arg1, TArg2 arg2, void* pCookie);
00237 };
00238 
00239 template<class TArg1, class TArg2, class TArg3>
00240 struct XnHandlerFunc3Args
00241 {
00242     typedef void (XN_CALLBACK_TYPE* FuncPtr)(TArg1 arg1, TArg2 arg2, TArg3 arg3, void* pCookie);
00243 };
00244 
00245 template<class TArg1, class TArg2, class TArg3, class TArg4>
00246 struct XnHandlerFunc4Args
00247 {
00248     typedef void (XN_CALLBACK_TYPE* FuncPtr)(TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, void* pCookie);
00249 };
00250 
00251 template<class TArg1, class TArg2, class TArg3, class TArg4, class TArg5>
00252 struct XnHandlerFunc5Args
00253 {
00254     typedef void (XN_CALLBACK_TYPE* FuncPtr)(TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, void* pCookie);
00255 };
00256 
00257 // Event classes (there's a class per number of arguments)
00258 class XnEventNoArgs : public XnEventInterfaceT<XnHandlerFuncNoArgs::FuncPtr>
00259 {
00260 public:
00261     XnStatus Raise()
00262     {
00263         XnAutoCSLocker locker(this->m_hLock);
00264         ApplyListChanges();
00265 
00266         for (CallbackPtrList::ConstIterator it = m_callbacks.Begin(); it != m_callbacks.End(); ++it)
00267         {
00268             TCallback* pCallback = *it;
00269             pCallback->pFunc(pCallback->pCookie);
00270         }
00271 
00272         ApplyListChanges();
00273         return (XN_STATUS_OK);
00274     }
00275 };
00276 
00277 
00278 template<class TArg1>
00279 class XnEvent1Arg : public XnEventInterfaceT<typename XnHandlerFunc1Arg<TArg1>::FuncPtr>
00280 {
00281     typedef XnEventInterfaceT<typename XnHandlerFunc1Arg<TArg1>::FuncPtr> Base;
00282 
00283 public:
00284     XnStatus Raise(TArg1 arg)
00285     {
00286         XnAutoCSLocker locker(this->m_hLock);
00287         this->ApplyListChanges();
00288 
00289         for (typename Base::CallbackPtrList::ConstIterator it = this->m_callbacks.Begin(); it != this->m_callbacks.End(); ++it)
00290         {
00291             typename Base::TCallback* pCallback = *it;
00292             pCallback->pFunc(arg, pCallback->pCookie);
00293         }
00294 
00295         this->ApplyListChanges();
00296         return (XN_STATUS_OK);
00297     }
00298 };
00299 
00300 template<class TEventArgs>
00301 class XnEventT : public XnEvent1Arg<const TEventArgs&>
00302 {};
00303 
00304 template<class TArg1, class TArg2>
00305 class XnEvent2Args : public XnEventInterfaceT<typename XnHandlerFunc2Args<TArg1, TArg2>::FuncPtr>
00306 {
00307     typedef XnEventInterfaceT<typename XnHandlerFunc2Args<TArg1, TArg2>::FuncPtr> Base;
00308 
00309 public:
00310     XnStatus Raise(TArg1 arg1, TArg2 arg2)
00311     {
00312         XnAutoCSLocker locker(this->m_hLock);
00313         this->ApplyListChanges();
00314 
00315         for (typename Base::CallbackPtrList::ConstIterator it = this->m_callbacks.Begin(); it != this->m_callbacks.End(); ++it)
00316         {
00317             typename Base::TCallback* pCallback = *it;
00318             pCallback->pFunc(arg1, arg2, pCallback->pCookie);
00319         }
00320 
00321         this->ApplyListChanges();
00322         return (XN_STATUS_OK);
00323     }
00324 };
00325 
00326 template<class TArg1, class TArg2, class TArg3>
00327 class XnEvent3Args : public XnEventInterfaceT<typename XnHandlerFunc3Args<TArg1, TArg2, TArg3>::FuncPtr>
00328 {
00329     typedef XnEventInterfaceT<typename XnHandlerFunc3Args<TArg1, TArg2, TArg3>::FuncPtr> Base;
00330     
00331 public:
00332     XnStatus Raise(TArg1 arg1, TArg2 arg2, TArg3 arg3)
00333     {
00334         XnAutoCSLocker locker(this->m_hLock);
00335         this->ApplyListChanges();
00336 
00337         for (typename Base::CallbackPtrList::ConstIterator it = this->m_callbacks.Begin(); it != this->m_callbacks.End(); ++it)
00338         {
00339             typename Base::TCallback* pCallback = *it;
00340             pCallback->pFunc(arg1, arg2, arg3, pCallback->pCookie);
00341         }
00342 
00343         this->ApplyListChanges();
00344         return (XN_STATUS_OK);
00345     }
00346 };
00347 
00348 template<class TArg1, class TArg2, class TArg3, class TArg4>
00349 class XnEvent4Args : public XnEventInterfaceT<typename XnHandlerFunc4Args<TArg1, TArg2, TArg3, TArg4>::FuncPtr>
00350 {
00351     typedef XnEventInterfaceT<typename XnHandlerFunc4Args<TArg1, TArg2, TArg3, TArg4>::FuncPtr> Base;
00352     
00353 public:
00354     XnStatus Raise(TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4)
00355     {
00356         XnAutoCSLocker locker(this->m_hLock);
00357         this->ApplyListChanges();
00358 
00359         for (typename Base::CallbackPtrList::ConstIterator it = this->m_callbacks.Begin(); it != this->m_callbacks.End(); ++it)
00360         {
00361             typename Base::TCallback* pCallback = *it;
00362             pCallback->pFunc(arg1, arg2, arg3, arg4, pCallback->pCookie);
00363         }
00364 
00365         this->ApplyListChanges();
00366         return (XN_STATUS_OK);
00367     }
00368 };
00369 
00370 template<class TArg1, class TArg2, class TArg3, class TArg4, class TArg5>
00371 class XnEvent5Args : public XnEventInterfaceT<typename XnHandlerFunc5Args<TArg1, TArg2, TArg3, TArg4, TArg5>::FuncPtr>
00372 {
00373     typedef XnEventInterfaceT<typename XnHandlerFunc5Args<TArg1, TArg2, TArg3, TArg4, TArg5>::FuncPtr> Base;
00374     
00375 public:
00376     XnStatus Raise(TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5)
00377     {
00378         XnAutoCSLocker locker(this->m_hLock);
00379         this->ApplyListChanges();
00380 
00381         for (typename Base::CallbackPtrList::ConstIterator it = this->m_callbacks.Begin(); it != this->m_callbacks.End(); ++it)
00382         {
00383             typename Base::TCallback* pCallback = *it;
00384             pCallback->pFunc(arg1, arg2, arg3, arg4, arg5, pCallback->pCookie);
00385         }
00386 
00387         this->ApplyListChanges();
00388         return (XN_STATUS_OK);
00389     }
00390 };
00391 
00392 #endif // _XN_EVENT_T_H_