Skip to content
Snippets Groups Projects
Scheduler.hh 10.1 KiB
Newer Older
sbund's avatar
sbund committed
// $Id$
//
// Copyright (C) 2006
sbund's avatar
sbund committed
// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
//     Stefan Bund <stefan.bund@fokus.fraunhofer.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the
// Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

/** \file
    \brief Scheduler public header
g0dil's avatar
g0dil committed
 */

sbund's avatar
sbund committed
#ifndef HH_Scheduler_
#define HH_Scheduler_ 1

// Custom includes
#include <map>
g0dil's avatar
g0dil committed
#include <queue>
sbund's avatar
sbund committed
#include <boost/function.hpp>
#include <boost/utility.hpp>
sbund's avatar
sbund committed

g0dil's avatar
g0dil committed
#include "Utils/MicroTime.hh"

sbund's avatar
sbund committed
//#include "scheduler.mpp"
///////////////////////////////hh.p////////////////////////////////////////

/** \brief SENF Project namespace */
sbund's avatar
sbund committed
    /** \brief Singleton class to manage the event loop

        This class manages a single select() type event loop. A customer of this class may register
tho's avatar
tho committed
        any number of file descriptors with this class and pass callback functions to be called on
        input, output or error. This functions are specified using boost::function objects (See <a
        href="http://www.boost.org/doc/html/function.html">Boost.Function</a>)

        The Scheduler is based on a generic handle representation. The only information needed from
        a handle, is the intrinsic file descriptor. Any object for which the statement
        \code
          int fd = retrieve_filehandle(object);
        \endcode
tho's avatar
tho committed
        is valid and places the relevant file descriptor into fd can be used as a Handle type. There
        is an implementation of retrieve_filehandle(int) within the library to handle explicit file
tho's avatar
tho committed
        descriptors. The <a href="../../../Socket/doc/html/index.html">Socket library</a> provides an
        implementation of <tt>retrieve_filehandle(FileHandle handle)</tt>. If you want to support
        some other handle type, just define an appropriate \c retrieve_filehandle function <em>in
        that types namespace</em>.

        It is important to note, that for every combination of file descriptor and event, only a \e
        single handler may be installed. Installing more handlers does not make sense. If you need
tho's avatar
tho committed
        to distribute data to several interested parties, you must take care of this yourself.

        \todo Fix EventId parameter (probably to int) to allow |-ing without casting ...
sbund's avatar
sbund committed
      */
    class Scheduler
        : boost::noncopyable
    {
    public:
        ///////////////////////////////////////////////////////////////////////////
        // Types

        /// \brief Types of file descriptor events */
        enum EventId { EV_NONE=0,
g0dil's avatar
g0dil committed
                       EV_READ=1, EV_PRIO=2, EV_WRITE=4, 
                       EV_ALL=7,
                       EV_HUP=8, EV_ERR=16 };
        /** \brief Template typedef for Callback type
            This is a template typedef (which does not exist in C++) that is, a template class whose
            sole member is a typedef symbol defining the callback type given the handle type.

            The Callback is any callable object taking a \c Handle and an \c EventId as argument.
         */
        template <class Handle>
        struct GenericCallback {
            typedef boost::function<void (typename boost::call_traits<Handle>::param_type,
                                          EventId) > Callback;
        };
        /** \brief Callback type for timer events */
        typedef boost::function<void ()> TimerCallback;
sbund's avatar
sbund committed

        ///////////////////////////////////////////////////////////////////////////
        ///\name Structors and default members
        ///@{

        // private default constructor
        // no copy constructor
        // no copy assignment
        // default destructor
        // no conversion constructors

        /** \brief Return Scheduler instance

            This static member is used to access the singleton instance. This member is save to
            return a correctly initialized Scheduler instance even if called at global construction
            time

            \implementation This static member just defines the Scheduler as a static method
tho's avatar
tho committed
                variable. The C++ standard then provides above guarantee. The instance will be
                initialized the first time, the code flow passes the variable declaration found in
                the instance() body.
         */
sbund's avatar
sbund committed
        static Scheduler & instance();

        ///@}
        ///////////////////////////////////////////////////////////////////////////

        void add(Handle const & handle,
                 typename GenericCallback<Handle>::Callback const & cb,
                 int eventMask = EV_ALL); ///< Add file handle event callback
                                        /**< add() will add a callback to the Scheduler. The
tho's avatar
tho committed
                                             callback will be called for the given type of event on
                                             the given  arbitrary file-descriptor or
                                             handle-like object. If there already is a Callback
tho's avatar
tho committed
                                             registered for one of the events requested, the new
                                             handler will replace the old one.
                                             \param[in] handle file descriptor or handle providing
                                                 the Handle interface defined above.
                                             \param[in] cb callback
                                             \param[in] eventMask arbitrary combination via '|'
                                                 operator of EventId designators. */
        template <class Handle>
        void remove(Handle const & handle, int eventMask = EV_ALL); ///< Remove event callback
                                        /**< remove() will remove any callback registered for any of
                                             the given events on the given file descriptor or handle
                                             like object.
                                             \param[in] handle file descriptor or handle providing
                                                 the Handle interface defined above.
                                             \param[in] eventMask arbitrary combination via '|'
                                                 operator of EventId designators. */

        void timeout(unsigned long timeout, TimerCallback const & cb); ///< Add timeout event
                                        /**< \param[in] timeout timeout in milliseconds
                                             \param[in] cb callback to call after \a timeout
                                                 milliseconds
                                             \todo Return some kind of handle/pointer and add
                                                 support to update or revoke a timeout */

        void process();                 ///< Event handler main loop
                                        /**< This member must be called at some time to enter the
                                             event handler main loop. Only while this function is
                                             running any events are handled. The call will return
                                             only, if any callback calls terminate(). */
        void terminate();               ///< Called by callbacks to terminate the main loop
                                        /**< This member may be called by any callback to tell the
                                             main loop to terminate. The main loop will return to
                                             it's caller after the currently running callback
                                             returns. */
sbund's avatar
sbund committed

    protected:

    private:
        typedef boost::function<void (EventId)> SimpleCallback;
sbund's avatar
sbund committed
        Scheduler();
g0dil's avatar
g0dil committed
        void do_add(int fd, SimpleCallback const & cb, int eventMask = EV_ALL);
        void do_remove(int fd, int eventMask = EV_ALL);
        /** \brief Descriptor event specification
            \internal */
        struct EventSpec
sbund's avatar
sbund committed
        {
g0dil's avatar
g0dil committed
            SimpleCallback cb_read;
            SimpleCallback cb_prio;
            SimpleCallback cb_write;
sbund's avatar
sbund committed

            int epollMask() const;
        };

        /** \brief Timer event specification
            \internal */
        struct TimerSpec
        {
            TimerSpec() : timeout(), cb() {}
g0dil's avatar
g0dil committed
            TimerSpec(unsigned long long timeout_, TimerCallback cb_)
                : timeout(timeout_), cb(cb_) {}

            bool operator< (TimerSpec const & other) const
                { return timeout > other.timeout; }

            unsigned long long timeout;
            TimerCallback cb;
        };

sbund's avatar
sbund committed
        typedef std::map<int,EventSpec> FdTable;
        typedef std::priority_queue<TimerSpec> TimerQueue;
sbund's avatar
sbund committed

        FdTable fdTable_;
        TimerQueue timerQueue_;
sbund's avatar
sbund committed
        int epollFd_;
sbund's avatar
sbund committed
        bool terminate_;
sbund's avatar
sbund committed
    };

    /** \brief Default file descriptor accessor

        retrieve_filehandle() provides the Scheduler with support for explicit file descriptors as
        file handle argument.

        \relates Scheduler
    int retrieve_filehandle(int fd);

sbund's avatar
sbund committed

///////////////////////////////hh.e////////////////////////////////////////
sbund's avatar
sbund committed
#include "Scheduler.cci"
//#include "Scheduler.ct"
sbund's avatar
sbund committed
#endif


// Local Variables:
// mode: c++
// fill-column: 100
// c-file-style: "senf"
// indent-tabs-mode: nil
// ispell-local-dictionary: "american"
// compile-command: "scons -u test"
// comment-column: 40
sbund's avatar
sbund committed
// End: