## Public API Reference

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# 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__