CrystalSpace

Public API Reference

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/ref.h"
00038 #include "csutil/refarr.h"
00039 #include "csutil/scf_implementation.h"
00040 #include "csutil/threading/mutex.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   CS::Threading::Mutex 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.Lock(); }
00108   // Unlock the queue
00109   inline void Unlock () { Mutex.Unlock (); }
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 1.2.1 by doxygen 1.5.3