EventChannel.h

00001 /***************************************************************************
00002  *                                                                         *
00003  *   (c) Art Tevs, MPI Informatik Saarbruecken                             *
00004  *       mailto: <tevs@mpi-sb.mpg.de>                                      *
00005  *                                                                         *
00006  *   This program is free software; you can redistribute it and/or modify  *
00007  *   it under the terms of the GNU General Public License as published by  *
00008  *   the Free Software Foundation; either version 2 of the License, or     *
00009  *   (at your option) any later version.                                   *
00010  *                                                                         *
00011  ***************************************************************************/
00012 
00013 
00014 #ifndef _NR_EVENT_CHANNEL_H_
00015 #define _NR_EVENT_CHANNEL_H_
00016 
00017 //----------------------------------------------------------------------------------
00018 // Includes
00019 //----------------------------------------------------------------------------------
00020 #include "Prerequisities.h"
00021 #include "EventActor.h"
00022 #include <queue>
00023 
00024 namespace nrEngine{
00025 
00026         //! Event channel used for communication between application/engine's components
00027         /**
00028          * \par
00029          * EventChannel represents a message bus for the communication between
00030          * system components. Events/messages could be send through this channel
00031          * to all listeners connected to this channel.
00032          *
00033          * \par
00034          * In our engine we mix the concept of event messaging and state machines.
00035          * So we do not have only events but also states. The states are stored in
00036          * communication channels, so each listener of a channel could also be noticed
00037          * if any state changes. This is also how we handle it in the nrEngine.
00038          *
00039          * \par
00040          * The communication actors are connected to the channel by its name. Also
00041          * the lifetime of each actor is tracked. So if an actor is removed from the
00042          * memory, so it will be automaticaly disconnected from the database.
00043          * We do not use smart pointers for this purpose, because it will cause in
00044          * undefined working flow. i.e. if you think the actor is removed from the memory
00045          * because you have deleted it, it still get noticed about the things going on
00046          * the channel. So this will ends up in undefined state.In our implementation
00047          * the destructor of EventActor does simply say all channels it connected to,
00048          * that the object does not exists anymore, so it can be disconnected.
00049          * 
00050          * \ingroup event
00051         **/
00052         class _NRExport EventChannel {
00053                 public:
00054 
00055                         //! Create a new instance of the communication channel 
00056                         EventChannel(EventManager* manager, const std::string& name);
00057 
00058                         //! Releas eused memory and destroy hte instance.
00059                         virtual ~EventChannel();
00060 
00061                         /**
00062                          * Connect a new actor to the channel. The actor will be connected
00063                          * so it get noticed about any communication on the channel.
00064                          *
00065                          * The actor has to implement default event reactions needed for
00066                          * our channel communication system. Compilation error will occur
00067                          * if the reactions to the default events are not implemented.
00068                          * 
00069                          * @param actor An actor to connect to the channel
00070                          * @param notice Should channel let notice the actor that he is connected now (default YES)
00071                          **/
00072                         Result add(EventActor* actor, bool notice = true);
00073 
00074                         /**
00075                          * Disconnect an actor from the channel. It is a good coding style
00076                          * if you call this function, when you do not need the connection anymore.
00077                          * However our engine does provide you the possibility to
00078                          * forget about disconnecting the actors from the channel, because the lifetime
00079                          * of an actor will be tracked. If the object does not exists anymore, so
00080                          * it will be automaticaly disconnected.
00081                          *
00082                          * If you want to be performant, so remove actors from the channels, if they do not
00083                          * need the connection anymore.
00084                          *
00085                          * @param actor An actor already connected to the channel
00086                          * @param notice Should channel notice the actor, about disconnection (default YES)
00087                          **/
00088                         Result del(EventActor* actor, bool notice = true);
00089 
00090                         /**
00091                          * Get the name of the channel
00092                          **/
00093                         NR_FORCEINLINE const std::string& getName () const { return mName; }
00094 
00095                         /**
00096                          * Emit a certain event to a channel. This will send this event
00097                          * to all connected actors, so they get noticed about new event.
00098                          *
00099                          * @param event Smart pointer to an event object
00100                          **/
00101                         void emit (SharedPtr<Event> event);
00102 
00103                         /**
00104                          * Instead of emit() this will not send the message directly to
00105                          * the channel listeners, but it store the message first in
00106                          * a queue based on priority numbers of the events. When
00107                          * you call deliver(), then all messages are getting delivered
00108                          * to the channel listeners
00109                          *
00110                          * @param event Smart pointer to the event message
00111                          *
00112                          * NOTE: If event priority is immediately so the message will
00113                          *              be emitted immediately without be stored in the queue
00114                          **/
00115                         void push(SharedPtr<Event> event);
00116 
00117                         /**
00118                          * Deliver all stored event messages from the queue
00119                          * to the actors connected to the channel.
00120                          **/
00121                         void deliver();
00122                         
00123                 protected:
00124                         //! The event manager system is a friend to this class
00125                         friend class EventManager;
00126 
00127                         //! Store here the mapping between actor names and their connections
00128                         typedef std::map<std::string, EventActor*> ActorDatabase;
00129 
00130                         //! Unique name of the communication channel
00131                         std::string mName;
00132                         
00133                         //! We always does store a pointer to the event manager where this channel belongs to
00134                         EventManager* mParentManager;
00135 
00136                         //! Connected actor database
00137                         ActorDatabase mActorDb;
00138                          
00139                         /**
00140                          * This structure is used as a wrapper to define a way
00141                          * how to distinguish between priority numbers of events.
00142                          **/
00143                         template <class ClassT>
00144                         struct GreatEvent : public std::binary_function<ClassT, ClassT, bool>
00145                         {
00146                                 bool operator()(ClassT x, ClassT y) const
00147                                 {
00148                                         return x->getPriority() > y->getPriority();
00149                                 }
00150                         };
00151                         
00152                         //! We store our event messages in a priority queue
00153                         typedef std::priority_queue<SharedPtr<Event>, std::vector<SharedPtr<Event> >, GreatEvent<SharedPtr<Event> > > EventQueue;
00154 
00155                         //! Store the event messages in this variable
00156                         EventQueue mEventQueue;
00157                         
00158                         //! Check whenever a given actor is already connected
00159                         bool isConnected(const std::string& name);
00160                         
00161                         //! Disconnect all actors from the channel
00162                         void _disconnectAll();
00163 
00164         };
00165         
00166 }; // end namespace
00167 
00168 #endif

Generated on Wed Sep 12 23:19:42 2007 for nrEngine by  doxygen 1.5.1