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