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/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