csutil/cseventq.h
Go to the documentation of this file.00001 /* 00002 Crystal Space 3D engine: Event Queue interface 00003 Copyright (C) 1998 by Andrew Zabolotny <[email protected]> 00004 Copyright (C) 2001 by Eric Sunshine <[email protected]> 00005 Copyright (C) 2005 by Adam D. Bradley <[email protected]> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public 00018 License along with this library; if not, write to the Free 00019 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00020 */ 00021 00022 #ifndef __CS_CSEVENTQ_H__ 00023 #define __CS_CSEVENTQ_H__ 00024 00025 #ifdef ADB_DEBUG /* debugging output... */ 00026 #include <iostream> 00027 #endif 00028 00033 #include "csextern.h" 00034 00035 #include "csutil/array.h" 00036 #include "csutil/hash.h" 00037 #include "csutil/ref.h" 00038 #include "csutil/refarr.h" 00039 #include "csutil/scf_implementation.h" 00040 #include "csutil/thread.h" 00041 #include "csutil/weakref.h" 00042 #include "csutil/eventhandlers.h" 00043 #include "iutil/eventh.h" 00044 #include "iutil/eventq.h" 00045 #include "cssubscription.h" 00046 00047 struct iObjectRegistry; 00048 00049 class csEventCord; 00050 class csEventOutlet; 00051 class csPoolEvent; 00052 00057 #define DEF_EVENT_QUEUE_LENGTH 256 00058 00059 template<> 00060 class csHashComputer<iEventHandler *> : public csHashComputerIntegral<iEventHandler *> {}; 00061 00067 class CS_CRYSTALSPACE_EXPORT csEventQueue : 00068 public scfImplementation1<csEventQueue, iEventQueue> 00069 { 00070 friend class csEventOutlet; 00071 friend class csPoolEvent; 00072 friend class csEventTree; 00073 friend class csEventQueueTest; 00074 00075 private: 00076 // Shared-object registry 00077 iObjectRegistry* Registry; 00078 // Event name registry 00079 csRef<iEventNameRegistry> NameRegistry; 00080 // Event handler registry 00081 csRef<iEventHandlerRegistry> HandlerRegistry; 00082 // The queue itself (technically, a ring buffer) 00083 volatile iEvent** EventQueue; 00084 // Queue head and tail pointers 00085 volatile size_t evqHead, evqTail; 00086 // The maximum queue length 00087 volatile size_t Length; 00088 // Protection against multiple threads accessing same event queue 00089 csRef<csMutex> Mutex; 00090 // Event tree. All subscription PO graphs and delivery queues hang off 00091 // of this. 00092 csEventTree *EventTree; 00093 // Shortcut to per-event-name delivery queues. 00094 csHash<csEventTree *,csEventID> EventHash; 00095 // Array of allocated event outlets. 00096 csArray<csEventOutlet*> EventOutlets; 00097 // Array of allocated event cords. 00098 csHash<csEventCord *, csEventID> EventCords; 00099 // Pool of event objects 00100 csPoolEvent* EventPool; 00102 csRefArray<iEventHandler> handlers; 00103 00104 // Enlarge the queue size. 00105 void Resize (size_t iLength); 00106 // Lock the queue for modifications: NESTED CALLS TO LOCK/UNLOCK NOT ALLOWED! 00107 inline void Lock () { Mutex->LockWait(); } 00108 // Unlock the queue 00109 inline void Unlock () { Mutex->Release(); } 00110 // Send broadcast pseudo-events (bypassing event queue). 00111 void Notify (const csEventID &name); 00112 00113 /* 00114 * Start a loop. The purpose of this function is to protect 00115 * against modifications to the Listeners array while this array 00116 * is being processed. 00117 */ 00118 void StartLoop (); 00119 // End a loop. 00120 void EndLoop (); 00121 00122 public: 00123 00125 csEventQueue (iObjectRegistry*, size_t iLength = DEF_EVENT_QUEUE_LENGTH); 00127 virtual ~csEventQueue (); 00128 00130 virtual void Process (); 00132 virtual void Dispatch (iEvent&); 00133 00135 virtual csHandlerID RegisterListener (iEventHandler*); 00137 virtual csHandlerID RegisterListener (iEventHandler *handler, 00138 const csEventID &event) 00139 { 00140 csHandlerID id = RegisterListener(handler); 00141 if (id!=CS_HANDLER_INVALID) 00142 { 00143 if (Subscribe(handler, event)) 00144 return id; 00145 else 00146 RemoveListener(handler); /* fall through */ 00147 } 00148 return CS_HANDLER_INVALID; 00149 } 00151 virtual csHandlerID RegisterListener (iEventHandler *handler, 00152 const csEventID events[]) 00153 { 00154 csHandlerID id = RegisterListener(handler); 00155 if (id!=CS_HANDLER_INVALID) 00156 { 00157 if (Subscribe(handler, events)) 00158 return id; 00159 else 00160 RemoveListener(handler); /* fall through */ 00161 } 00162 return CS_HANDLER_INVALID; 00163 } 00169 virtual bool Subscribe (iEventHandler*, const csEventID &); 00176 virtual bool Subscribe (iEventHandler*, const csEventID[]); 00182 virtual void Unsubscribe (iEventHandler*, const csEventID &); 00187 virtual void Unsubscribe (iEventHandler*, const csEventID[]); 00194 virtual void RemoveListener (iEventHandler*); 00199 virtual void RemoveAllListeners (); 00200 00202 virtual csPtr<iEventOutlet> CreateEventOutlet (iEventPlug*); 00204 virtual iEventOutlet* GetEventOutlet (); 00206 virtual iEventCord* GetEventCord (const csEventID &); 00207 00209 uint32 CountPool (); 00210 protected: 00211 virtual iEvent *CreateRawEvent (); 00212 public: 00214 virtual csPtr<iEvent> CreateEvent (); 00215 virtual csPtr<iEvent> CreateEvent (const csEventID &name, bool broadcast); 00216 virtual csPtr<iEvent> CreateEvent (const csEventID &name); 00217 virtual csPtr<iEvent> CreateEvent (const char *name); 00218 virtual csPtr<iEvent> CreateBroadcastEvent (const csEventID &name); 00219 virtual csPtr<iEvent> CreateBroadcastEvent (const char *name); 00221 virtual void Post (iEvent*); 00223 virtual csPtr<iEvent> Get (); 00225 virtual void Clear (); 00227 virtual bool IsEmpty () { return evqHead == evqTail; } 00228 00229 csEventID Frame; 00230 csEventID PreProcess; 00231 csEventID ProcessEvent; 00232 csEventID PostProcess; 00233 csEventID FinalProcess; 00234 00247 struct iTypedFrameEventDispatcher : public iEventHandler 00248 { 00249 protected: 00250 csWeakRef<csEventQueue> parent; 00251 csEventID sendEvent; 00252 public: 00253 iTypedFrameEventDispatcher () 00254 { 00255 } 00256 virtual ~iTypedFrameEventDispatcher () 00257 { 00258 } 00259 CS_EVENTHANDLER_DEFAULT_INSTANCE_CONSTRAINTS 00260 virtual bool HandleEvent (iEvent&) 00261 { 00262 parent->Notify (sendEvent); 00263 return false; 00264 } 00265 }; 00266 00267 class PreProcessFrameEventDispatcher 00268 : public scfImplementation2<PreProcessFrameEventDispatcher, 00269 csEventQueue::iTypedFrameEventDispatcher, 00270 scfFakeInterface<iEventHandler> > 00271 { 00272 public: 00273 PreProcessFrameEventDispatcher (csEventQueue* parent) 00274 : scfImplementationType (this) 00275 { 00276 iTypedFrameEventDispatcher::parent = parent; 00277 sendEvent = parent->PreProcess; 00278 } 00279 CS_EVENTHANDLER_PHASE_LOGIC("crystalspace.frame.preprocess") 00280 }; 00281 00282 class ProcessFrameEventDispatcher 00283 : public scfImplementation2<ProcessFrameEventDispatcher, 00284 csEventQueue::iTypedFrameEventDispatcher, 00285 scfFakeInterface<iEventHandler> > 00286 { 00287 public: 00288 ProcessFrameEventDispatcher (csEventQueue* parent) 00289 : scfImplementationType (this) 00290 { 00291 iTypedFrameEventDispatcher::parent = parent; 00292 sendEvent = parent->ProcessEvent; 00293 } 00294 CS_EVENTHANDLER_PHASE_3D("crystalspace.frame.process") 00295 }; 00296 00297 class PostProcessFrameEventDispatcher 00298 : public scfImplementation2<PostProcessFrameEventDispatcher, 00299 csEventQueue::iTypedFrameEventDispatcher, 00300 scfFakeInterface<iEventHandler> > 00301 { 00302 public: 00303 PostProcessFrameEventDispatcher (csEventQueue* parent) 00304 : scfImplementationType (this) 00305 { 00306 iTypedFrameEventDispatcher::parent = parent; 00307 sendEvent = parent->PostProcess; 00308 } 00309 CS_EVENTHANDLER_PHASE_2D("crystalspace.frame.postprocess") 00310 }; 00311 00312 class FinalProcessFrameEventDispatcher 00313 : public scfImplementation2<FinalProcessFrameEventDispatcher, 00314 csEventQueue::iTypedFrameEventDispatcher, 00315 scfFakeInterface<iEventHandler> > 00316 { 00317 public: 00318 FinalProcessFrameEventDispatcher (csEventQueue* parent) 00319 : scfImplementationType (this) 00320 { 00321 iTypedFrameEventDispatcher::parent = parent; 00322 sendEvent = parent->FinalProcess; 00323 } 00324 CS_EVENTHANDLER_PHASE_FRAME("crystalspace.frame.finalprocess") 00325 }; 00326 }; 00327 00328 #endif // __CS_CSEVENTQ_H__
Generated for Crystal Space by doxygen 1.4.7