eventbase.h

Go to the documentation of this file.
00001 /**
00002  *  Copyright (C) 2004-2005 Alo Sarv <madcat_@users.sourceforge.net>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 /** \file eventbase.h Interface for Event Handling Subsystem */
00020 
00021 #ifndef __EVENTBASE_H__
00022 #define __EVENTBASE_H__
00023 
00024 #include <hn/osdep.h>
00025 #include <boost/thread.hpp>
00026 #include <boost/noncopyable.hpp>
00027 #include <list>
00028 
00029 /**
00030  * \page ehs Event Handling Subsystem Overview
00031  *
00032  * EHS provides functionality to perform Event-driven programming. EventTable's
00033  * are used to post/store/handle events. EventTable is derived from
00034  * EventTableBase, which interfaces all EventTable objects with main loop,
00035  * latter of which is located in EventMain class. All EventTable objects
00036  * are registred with EventMain on construction and de-registred on
00037  * destruction. Whenever there are events, EventTableBase::HandleEvents()
00038  * function is called on each and every registred EventTableBase objects.
00039  *
00040  * Since one of the most logical way to use this functionality is in
00041  * multi-threaded environment, where threads submit events and main thread
00042  * handles them, everything in here must be 100% thread-safe.
00043  *
00044  * Customizability:
00045  *   New classes can be derived from EventTableBase (or even from EventTable)
00046  *   to further customize this functionality.
00047  */
00048 
00049 class EventTableBase;
00050 
00051 /**
00052  * This Singleton class is the application main event system. Users should never
00053  * need to access this class directly - it is accessed from EventTableBase
00054  * constructor/destructors.
00055  *
00056  * The purpose of this class is to provide a central list of event tables,
00057  * and wait for events. When event occours, mainLoop() makes a virtual function
00058  * call HandleEvents() on each registred event table, handling all pending
00059  * events.
00060  *
00061  * \note Everything here must be thread-safe and protected through mutexes.
00062  */
00063 class EventMain {
00064 public:
00065         //! Can be used to retrieve the only instance of this class
00066         static EventMain& instance();
00067 
00068         //! Initialize this object
00069         static void initialize() {
00070                 instance();
00071         }
00072         //! Add event table
00073         void addEventTable(EventTableBase *et) {
00074                 boost::mutex::scoped_lock l(m_listLock);
00075                 m_list.push_back(et);
00076         }
00077         //! Remove event table
00078         void removeEventTable(EventTableBase *et) {
00079                 boost::mutex::scoped_lock l(m_listLock);
00080                 m_list.remove(et);
00081         }
00082         //! Enter main event loop. This runs until someone calls ExitMainLoop()
00083         void mainLoop();
00084 
00085         //! Handle all pending events in current queues.
00086         void handlePending();
00087 
00088         //! Exit main loop. Notice that this function returns immediately, but
00089         //! application exit will be delayed until next event loop.
00090         void exitMainLoop();
00091 private:
00092         std::list<EventTableBase*> m_list;    //!< List of event tables
00093         boost::mutex m_listLock;
00094         typedef std::list<EventTableBase*>::iterator LIter;
00095         bool m_running;                       //!< Runs until this is true
00096         boost::mutex m_runningLock;
00097 
00098         EventMain() : m_running(true) { }     //!< Constructor
00099         EventMain(const EventMain&);          //!< Copying forbidden
00100         EventMain& operator=(EventMain&);     //!< Copying forbidden
00101         ~EventMain() {}                       //!< Destructor
00102 };
00103 
00104 /**
00105  * Abstract base class for event engine. Provides two common features for all
00106  * event tables:
00107  *
00108  * Notify() function, which need to be used whenever there is new event posted
00109  * to event queue. This is needed by main event loop to "wake up" and call
00110  * handlers.
00111  *
00112  * Pure virtual function prototype HandleEvents(), which needs to be overridden
00113  * by derived classes. This function will be called once per each main event
00114  * loop and must handle all events in the queue.
00115  *
00116  * EventTableBase class registers itself in central list (main event loop).
00117  */
00118 class DLLEXPORT EventTableBase : private boost::noncopyable {
00119         friend class EventMain;
00120 public:
00121         //! Constructor - Add to central event table list
00122         EventTableBase();
00123 
00124         //! Destructor - Remove from central event table list
00125         virtual ~EventTableBase();
00126 
00127 protected:
00128         //! Notify central event system to wake up
00129         static void notify();
00130 
00131         /**
00132          * Must be overridden by derived classes. This is called from central
00133          * event loop for each of the registred objects. Should handle all
00134          * pending events (if existing).
00135          */
00136         virtual void handleEvents() = 0;
00137 private:
00138         /**
00139          * For implementation use only - wait until there is a pending event
00140          * somewhere.
00141          */
00142         static void waitForEvent();
00143 
00144         /**
00145          * Check if there are any pending events anywhere.
00146          */
00147         static bool hasPending();
00148 
00149         /**
00150          * Toggle pending event flag to false.
00151          */
00152         static void setNoPending();
00153 private:
00154         //! Used to broadcast new events
00155         static boost::condition s_eventNotify;
00156         //! Protects the above condition
00157         static boost::mutex s_notifyLock;
00158         //! Whether there are any pending events
00159         static bool s_hasPending;
00160 };
00161 
00162 #endif