00001 #ifndef _UNEVT_Dispatcher_H_ // -*-c++-*- 00002 00003 /* 00004 * Copyright 1991-2002 Eric M. Hopper <hopper@omnifarious.org> 00005 * 00006 * This program is free software; you can redistribute it and/or modify it 00007 * under the terms of the GNU Lesser General Public License as published 00008 * by the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, but 00012 * WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 */ 00020 00021 #ifdef __GNUG__ 00022 # pragma interface 00023 #endif 00024 00025 /* $Header: /home/hopper/src/cvs/C++/UniEvent/UniEvent/Dispatcher.h,v 1.18 2002/08/29 00:58:05 hopper Exp $ */ 00026 00027 // For log see ../ChangeLog 00028 00029 #include <LCore/Protocol.h> 00030 #include <UniEvent/UNEVT_ClassIdent.h> 00031 00032 #define _UNEVT_Dispatcher_H_ 00033 00034 namespace strmod { 00035 namespace unievent { 00036 00037 class EventPtr; 00038 00039 /** \class Dispatcher Dispatcher.h UniEvent/Dispatcher.h 00040 * \brief An interface for a simple queuer and dispatcher of events. 00041 * 00042 * This provides an interface for classes that want to implement a queue of 00043 * Event objects that are removed from the queue in FIFO order and 'fired' by 00044 * calling their triggerEvent methods. 00045 */ 00046 class Dispatcher : virtual public lcore::Protocol 00047 { 00048 public: 00049 static const UNEVT_ClassIdent identifier; 00050 00051 //! Because every class (even abstract ones) should have a constructor. 00052 Dispatcher() { } 00053 //! Because abstract classes should have a virtual destructor. 00054 virtual ~Dispatcher() { } 00055 00056 inline virtual int AreYouA(const lcore::ClassIdent &cid) const; 00057 00058 //! Add an event to the queue. 00059 virtual void addEvent(const EventPtr &ev) = 0; 00060 00061 /** 00062 * Add an event that will be posted to poll something if the queue is busy. 00063 * 00064 * The Dispatcher maintains the concept of <em>external</em> 00065 * and <em>internal</em> events. External events are those posted by the 00066 * addEvent function. Internal events are those posted in response to some 00067 * internal condition. 00068 * 00069 * When external events cause other external events to be added, busy loops 00070 * can take over the system. In order to prevent this, an event from this 00071 * queue will be posted if the queue contains only external events. 00072 * 00073 * Events in this queue should query some outside event source for events and 00074 * use addEvent to add any there may be. <strong>Under no circumstance 00075 * should one of these events <em>always</em> cause events to be added 00076 * through addEvent.</strong> Doing this would just propogate the bad busy 00077 * loop behavior. 00078 */ 00079 virtual void addBusyPollEvent(const EventPtr &ev) = 0; 00080 00081 /** 00082 * \brief This event is only triggered whenever an event dispatch is 00083 * attempted when there's an empty queue. 00084 * 00085 * @param ev The event to fire when the queue is empty. 00086 * @return <code>true</code> if the event was successfully set, 00087 * <code>false</code> if the event was not set because some other event was 00088 * already set. 00089 */ 00090 virtual bool onQueueEmpty(const EventPtr &ev) = 0; 00091 00092 /** 00093 * \brief This event is only triggered when interrupt() is called. 00094 * 00095 * When interrupt() is called, a flag is set so this event is put onto the 00096 * front of the queue as soon as the Dispatcher's event loop gets control 00097 * again. 00098 * 00099 * @param ev The event to fire when interrupt() is called. 00100 * @return <code>true</code> if the event was successfully set, 00101 * <code>false</code> if the event was not set because some other event was 00102 * already set. 00103 */ 00104 virtual bool onInterrupt(const EventPtr &ev) = 0; 00105 00106 //! Dispatch a single event. 00107 inline void dispatchEvent(Dispatcher *enclosing = 0); 00108 00109 /** 00110 * \brief Dispatch until a certain number of events have been dispatched, or 00111 * the queue is empty. 00112 */ 00113 virtual void dispatchEvents(unsigned int numevents, 00114 Dispatcher *enclosing = 0) = 0; 00115 //! Dispatch until the queue is empty. 00116 virtual void dispatchUntilEmpty(Dispatcher *enclosing = 0) = 0; 00117 00118 /** 00119 * \brief Interrupts the dispatcher to execute a high priority event. 00120 * 00121 * This sets a flag so that as soon as the Dispatcher's event loop gets 00122 * control, the event set by onInterrupt() will be put on the front of the 00123 * queue. It will also call the Event::interrupt() method of any 00124 * currently executing event. 00125 * 00126 * \note Implementations of this method should be safe to call from a thread 00127 * or a signal handling context. 00128 */ 00129 virtual void interrupt() = 0; 00130 00131 /** 00132 * Cause the multiple event dispatch methods to halt before they normally 00133 * would. 00134 */ 00135 virtual void stopDispatching() = 0; 00136 //! Does the queue have any events in it? 00137 virtual bool isQueueEmpty() const = 0; 00138 00139 protected: 00140 virtual const lcore::ClassIdent *i_GetIdent() const { return &identifier; } 00141 00142 private: 00143 //! Purposely left undefined. 00144 Dispatcher(const Dispatcher &b); 00145 //! Purposely left undefined. 00146 const Dispatcher &operator =(const Dispatcher &b); 00147 }; 00148 00149 //-----------------------------inline functions-------------------------------- 00150 00151 inline int Dispatcher::AreYouA(const lcore::ClassIdent &cid) const 00152 { 00153 return((identifier == cid) || Protocol::AreYouA(cid)); 00154 } 00155 00156 inline void Dispatcher::dispatchEvent(Dispatcher *enclosing) 00157 { 00158 dispatchEvents(1, enclosing); 00159 } 00160 00161 } // namespace unievent 00162 } // namespace strmod 00163 00164 #endif
1.3-rc1