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 <bit@freya.etu.ru> 00004 Copyright (C) 2001 by Eric Sunshine <sunshine@sunshineco.com> 00005 Copyright (C) 2005 by Adam D. Bradley <artdodge@cs.bu.edu> 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/list.h" 00038 #include "csutil/ref.h" 00039 #include "csutil/refarr.h" 00040 #include "csutil/scf_implementation.h" 00041 #include "csutil/thread.h" 00042 #include "csutil/weakref.h" 00043 #include "iutil/eventnames.h" 00044 #include "iutil/eventhandlers.h" 00045 #include "iutil/eventq.h" 00046 #include "cssubscription.h" 00047 00048 struct iObjectRegistry; 00049 00050 class csEventCord; 00051 class csEventOutlet; 00052 class csPoolEvent; 00053 00058 #define DEF_EVENT_QUEUE_LENGTH 256 00059 00060 CS_SPECIALIZE_TEMPLATE 00061 class csHashComputer<iEventHandler *> : public csHashComputerIntegral<iEventHandler *> {}; 00062 00068 class CS_CRYSTALSPACE_EXPORT csEventQueue : 00069 public scfImplementation1<csEventQueue, iEventQueue> 00070 { 00071 friend class csEventOutlet; 00072 friend class csPoolEvent; 00073 friend class csEventTree; 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; 00101 00102 // Enlarge the queue size. 00103 void Resize (size_t iLength); 00104 // Lock the queue for modifications: NESTED CALLS TO LOCK/UNLOCK NOT ALLOWED! 00105 inline void Lock () { Mutex->LockWait(); } 00106 // Unlock the queue 00107 inline void Unlock () { Mutex->Release(); } 00108 // Send broadcast pseudo-events (bypassing event queue). 00109 void Notify (const csEventID &name); 00110 00111 /* 00112 * Start a loop. The purpose of this function is to protect 00113 * against modifications to the Listeners array while this array 00114 * is being processed. 00115 */ 00116 void StartLoop (); 00117 // End a loop. 00118 void EndLoop (); 00119 00120 public: 00121 00123 csEventQueue (iObjectRegistry*, size_t iLength = DEF_EVENT_QUEUE_LENGTH); 00125 virtual ~csEventQueue (); 00126 00128 virtual void Process (); 00130 virtual void Dispatch (iEvent&); 00131 00133 virtual csHandlerID RegisterListener (iEventHandler*); 00135 virtual csHandlerID RegisterListener (iEventHandler *handler, 00136 const csEventID &event) 00137 { 00138 csHandlerID id = RegisterListener(handler); 00139 if (id!=CS_HANDLER_INVALID) 00140 { 00141 if (Subscribe(handler, event)) 00142 return id; 00143 else 00144 RemoveListener(handler); /* fall through */ 00145 } 00146 return CS_HANDLER_INVALID; 00147 } 00149 virtual csHandlerID RegisterListener (iEventHandler *handler, 00150 const csEventID events[]) 00151 { 00152 csHandlerID id = RegisterListener(handler); 00153 if (id!=CS_HANDLER_INVALID) 00154 { 00155 if (Subscribe(handler, events)) 00156 return id; 00157 else 00158 RemoveListener(handler); /* fall through */ 00159 } 00160 return CS_HANDLER_INVALID; 00161 } 00167 virtual bool Subscribe (iEventHandler*, const csEventID &); 00174 virtual bool Subscribe (iEventHandler*, const csEventID[]); 00180 virtual void Unsubscribe (iEventHandler*, const csEventID &); 00185 virtual void Unsubscribe (iEventHandler*, const csEventID[]); 00192 virtual void RemoveListener (iEventHandler*); 00197 virtual void RemoveAllListeners (); 00198 00200 virtual csPtr<iEventOutlet> CreateEventOutlet (iEventPlug*); 00202 virtual iEventOutlet* GetEventOutlet (); 00204 virtual iEventCord* GetEventCord (const csEventID &); 00205 00207 uint32 CountPool (); 00208 protected: 00209 virtual iEvent *CreateRawEvent (); 00210 public: 00212 virtual csPtr<iEvent> CreateEvent (); 00213 virtual csPtr<iEvent> CreateEvent (const csEventID &name, bool broadcast); 00214 virtual csPtr<iEvent> CreateEvent (const csEventID &name); 00215 virtual csPtr<iEvent> CreateEvent (const char *name); 00216 virtual csPtr<iEvent> CreateBroadcastEvent (const csEventID &name); 00217 virtual csPtr<iEvent> CreateBroadcastEvent (const char *name); 00219 virtual void Post (iEvent*); 00221 virtual csPtr<iEvent> Get (); 00223 virtual void Clear (); 00225 virtual bool IsEmpty () { return evqHead == evqTail; } 00226 00227 csEventID Frame; 00228 csEventID PreProcess; 00229 csEventID ProcessEvent; 00230 csEventID PostProcess; 00231 csEventID FinalProcess; 00232 00245 struct iTypedFrameEventDispatcher : public iEventHandler 00246 { 00247 protected: 00248 csWeakRef<csEventQueue> parent; 00249 csEventID sendEvent; 00250 public: 00251 iTypedFrameEventDispatcher () 00252 { 00253 } 00254 virtual ~iTypedFrameEventDispatcher () 00255 { 00256 } 00257 CS_EVENTHANDLER_DEFAULT_INSTANCE_CONSTRAINTS 00258 virtual bool HandleEvent (iEvent&) 00259 { 00260 parent->Notify (sendEvent); 00261 return false; 00262 } 00263 }; 00264 00265 class PreProcessFrameEventDispatcher 00266 : public scfImplementation2<PreProcessFrameEventDispatcher, 00267 csEventQueue::iTypedFrameEventDispatcher, 00268 scfFakeInterface<iEventHandler> > 00269 { 00270 public: 00271 PreProcessFrameEventDispatcher (csEventQueue* parent) 00272 : scfImplementationType (this) 00273 { 00274 iTypedFrameEventDispatcher::parent = parent; 00275 sendEvent = parent->PreProcess; 00276 } 00277 CS_EVENTHANDLER_NAMES("crystalspace.frame.preprocess") 00278 CS_CONST_METHOD virtual const csHandlerID * GenericPrec( 00279 csRef<iEventHandlerRegistry> &, 00280 csRef<iEventNameRegistry> &, 00281 csEventID) const 00282 { 00283 return 0; 00284 } 00285 CS_CONST_METHOD virtual const csHandlerID * GenericSucc( 00286 csRef<iEventHandlerRegistry> &r1, 00287 csRef<iEventNameRegistry> &r2, 00288 csEventID e) const 00289 { 00290 static csHandlerID constraint[2] = { 0, CS_HANDLERLIST_END }; 00291 if (e == csevFrame(r2)) 00292 { 00293 constraint[0] = ProcessFrameEventDispatcher::StaticID (r1); 00294 return constraint; 00295 } 00296 return 0; 00297 } 00298 }; 00299 00300 class ProcessFrameEventDispatcher 00301 : public scfImplementation2<ProcessFrameEventDispatcher, 00302 csEventQueue::iTypedFrameEventDispatcher, 00303 scfFakeInterface<iEventHandler> > 00304 { 00305 public: 00306 ProcessFrameEventDispatcher (csEventQueue* parent) 00307 : scfImplementationType (this) 00308 { 00309 iTypedFrameEventDispatcher::parent = parent; 00310 sendEvent = parent->ProcessEvent; 00311 } 00312 CS_EVENTHANDLER_NAMES("crystalspace.frame.process") 00313 CS_CONST_METHOD virtual const csHandlerID * GenericPrec( 00314 csRef<iEventHandlerRegistry> &, 00315 csRef<iEventNameRegistry> &, 00316 csEventID) const 00317 { 00318 return 0; 00319 } 00320 CS_CONST_METHOD virtual const csHandlerID * GenericSucc( 00321 csRef<iEventHandlerRegistry> &r1, 00322 csRef<iEventNameRegistry> &r2, 00323 csEventID e) const 00324 { 00325 static csHandlerID constraint[2] = { 0, CS_HANDLERLIST_END }; 00326 if (e == csevFrame(r2)) 00327 { 00328 constraint[0] = PostProcessFrameEventDispatcher::StaticID (r1); 00329 return constraint; 00330 } 00331 return 0; 00332 } 00333 }; 00334 00335 class PostProcessFrameEventDispatcher 00336 : public scfImplementation2<PostProcessFrameEventDispatcher, 00337 csEventQueue::iTypedFrameEventDispatcher, 00338 scfFakeInterface<iEventHandler> > 00339 { 00340 public: 00341 PostProcessFrameEventDispatcher (csEventQueue* parent) 00342 : scfImplementationType (this) 00343 { 00344 iTypedFrameEventDispatcher::parent = parent; 00345 sendEvent = parent->PostProcess; 00346 } 00347 CS_EVENTHANDLER_NAMES("crystalspace.frame.postprocess") 00348 CS_CONST_METHOD virtual const csHandlerID * GenericPrec( 00349 csRef<iEventHandlerRegistry> &, 00350 csRef<iEventNameRegistry> &, 00351 csEventID) const 00352 { 00353 return 0; 00354 } 00355 CS_CONST_METHOD virtual const csHandlerID * GenericSucc( 00356 csRef<iEventHandlerRegistry> &r1, 00357 csRef<iEventNameRegistry> &r2, 00358 csEventID e) const 00359 { 00360 static csHandlerID constraint[2] = { 0, CS_HANDLERLIST_END }; 00361 if (e == csevFrame(r2)) 00362 { 00363 constraint[0] = FinalProcessFrameEventDispatcher::StaticID (r1); 00364 return constraint; 00365 } 00366 return 0; 00367 } 00368 }; 00369 00370 class FinalProcessFrameEventDispatcher 00371 : public scfImplementation2<FinalProcessFrameEventDispatcher, 00372 csEventQueue::iTypedFrameEventDispatcher, 00373 scfFakeInterface<iEventHandler> > 00374 { 00375 public: 00376 FinalProcessFrameEventDispatcher (csEventQueue* parent) 00377 : scfImplementationType (this) 00378 { 00379 iTypedFrameEventDispatcher::parent = parent; 00380 sendEvent = parent->FinalProcess; 00381 } 00382 CS_EVENTHANDLER_NAMES("crystalspace.frame.finalprocess") 00383 CS_CONST_METHOD virtual const csHandlerID * GenericPrec( 00384 csRef<iEventHandlerRegistry> &, 00385 csRef<iEventNameRegistry> &, 00386 csEventID) const 00387 { 00388 return 0; 00389 } 00390 CS_CONST_METHOD virtual const csHandlerID * GenericSucc( 00391 csRef<iEventHandlerRegistry> &, 00392 csRef<iEventNameRegistry> &, 00393 csEventID) const 00394 { 00395 return 0; 00396 } 00397 }; 00398 }; 00399 00400 #endif // __CS_CSEVENTQ_H__
Generated for Crystal Space by doxygen 1.4.6