Scheduler: Implement new file descriptor event API
g0dil [Fri, 19 Sep 2008 10:52:03 +0000 (10:52 +0000)]
Scheduler: Clean up FIFORunner::TaskInfo interface
Update rest of senf to use the new API

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@909 270642c3-0616-0410-b53a-bc976706d245

51 files changed:
Console/Readline.cc
Console/Readline.hh
Console/Server.cc
Console/Server.hh
Console/Server.ih
Examples/MCSniffer/MCSniffer.cc
Examples/Sniffer/Sniffer.cc
Examples/TCPClientServer/server.cc
Examples/UDPClientServer/udpServer.cc
PPI/IOEvent.cc
PPI/IOEvent.cti
PPI/IOEvent.hh
Scheduler/Binding.cci [deleted file]
Scheduler/Binding.cti [deleted file]
Scheduler/Binding.hh [deleted file]
Scheduler/Binding.test.cc [deleted file]
Scheduler/FIFORunner.cc
Scheduler/FIFORunner.cci
Scheduler/FIFORunner.hh
Scheduler/FdDispatcher.cc [deleted file]
Scheduler/FdDispatcher.cci [deleted file]
Scheduler/FdDispatcher.hh [deleted file]
Scheduler/FdDispatcher.ih [deleted file]
Scheduler/FdEvent.cc [new file with mode: 0644]
Scheduler/FdEvent.cci [new file with mode: 0644]
Scheduler/FdEvent.ct [moved from Scheduler/FdDispatcher.ct with 78% similarity]
Scheduler/FdEvent.cti [moved from Scheduler/FdDispatcher.cti with 76% similarity]
Scheduler/FdEvent.hh [new file with mode: 0644]
Scheduler/FdEvent.ih [new file with mode: 0644]
Scheduler/FdEvent.test.cc [moved from Scheduler/FdDispatcher.test.cc with 58% similarity]
Scheduler/FileDispatcher.cc [deleted file]
Scheduler/FileDispatcher.hh [deleted file]
Scheduler/FileDispatcher.test.cc [deleted file]
Scheduler/Poller.ct
Scheduler/ReadHelper.ct
Scheduler/ReadHelper.hh
Scheduler/Scheduler.cc
Scheduler/Scheduler.cci
Scheduler/Scheduler.cti [deleted file]
Scheduler/Scheduler.hh
Scheduler/Scheduler.test.cc
Scheduler/SignalEvent.cc
Scheduler/TimerEvent.cc
Scheduler/TimerEvent.hh
Scheduler/TimerEvent.ih
Scheduler/WriteHelper.ct
Scheduler/WriteHelper.hh
Utils/Daemon/Daemon.cc
Utils/Daemon/Daemon.cci [moved from Scheduler/FileDispatcher.cci with 68% similarity]
Utils/Daemon/Daemon.hh
Utils/Daemon/Daemon.ih

index f1597d4..a02e2a8 100644 (file)
@@ -116,10 +116,8 @@ namespace {
 
 prefix_ senf::console::detail::ReadlineClientReader::ReadlineClientReader(Client & client)
     : ClientReader(client), ch_ (-1), skipChars_ (0), 
-      schedBinding_ ( client.handle(), 
-                      senf::membind(&ReadlineClientReader::charEvent, this),
-                      Scheduler::EV_READ, 
-                      false ),
+      readevent_ ( "ReadlineClientReader", senf::membind(&ReadlineClientReader::charEvent, this),
+                   client.handle(), Scheduler::EV_READ, false ),
       terminate_ (false)
 {
     if (instance_ != 0)
@@ -158,7 +156,7 @@ prefix_ senf::console::detail::ReadlineClientReader::ReadlineClientReader(Client
 
     _rl_bell_preference = 0; // Set this *after* the config file has been read
 
-    schedBinding_.enable();
+    readevent_.enable();
 }
 
 prefix_ senf::console::detail::ReadlineClientReader::~ReadlineClientReader()
index 09a9e61..69ae87d 100644 (file)
@@ -31,7 +31,6 @@
 #include "Server.hh"
 #include "../Utils/Exception.hh"
 #include "../Scheduler/Scheduler.hh"
-#include "../Scheduler/Binding.hh"
 
 //#include "Readline.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
@@ -79,7 +78,7 @@ namespace detail {
         unsigned skipChars_;
         char nameBuffer_[256];
         char promptBuffer_[1024];
-        SchedulerBinding schedBinding_;
+        scheduler::FdEvent readevent_;
         bool terminate_;
 
         char * savedLineBuffer_;
index 3148e76..df6c421 100644 (file)
@@ -94,15 +94,11 @@ prefix_ senf::console::Server & senf::console::Server::start(ServerHandle handle
 }
 
 prefix_ senf::console::Server::Server(ServerHandle handle)
-    : handle_ (handle), root_ (senf::console::root().thisptr()), mode_ (Automatic)
-{
-    Scheduler::instance().add( handle_, senf::membind(&Server::newClient, this) );
-}
-
-prefix_ senf::console::Server::~Server()
-{
-    Scheduler::instance().remove(handle_);
-}
+    : handle_ (handle), 
+      event_ ("console::Server", senf::membind(&Server::newClient, this),
+              handle_, scheduler::FdEvent::EV_READ),
+      root_ (senf::console::root().thisptr()), mode_ (Automatic)
+{}
 
 prefix_ void senf::console::Server::newClient(int event)
 {
@@ -185,9 +181,10 @@ prefix_ void senf::console::detail::DumbClientReader::v_translate(std::string &
 
 prefix_
 senf::console::detail::NoninteractiveClientReader::NoninteractiveClientReader(Client & client)
-    : ClientReader (client), binding_ (handle(),
-                                       senf::membind(&NoninteractiveClientReader::newData, this),
-                                       senf::Scheduler::EV_READ)
+    : ClientReader (client), 
+      readevent_ ("NoninteractiveClientReader", 
+                  senf::membind(&NoninteractiveClientReader::newData, this),
+                  handle(), senf::Scheduler::EV_READ)
 {}
 
 prefix_ void senf::console::detail::NoninteractiveClientReader::v_disablePrompt()
@@ -223,7 +220,8 @@ senf::console::detail::NoninteractiveClientReader::newData(int event)
 prefix_ senf::console::Client::Client(Server & server, ClientHandle handle)
     : out_t(boost::ref(*this)), senf::log::IOStreamTarget(out_t::member), server_ (server),
       handle_ (handle), 
-      binding_ (handle, boost::bind(&Client::setNoninteractive,this), Scheduler::EV_READ, false),
+      readevent_ ("senf::console::Client", boost::bind(&Client::setNoninteractive,this), 
+                  handle, Scheduler::EV_READ, false),
       timer_ ("senf::console::Client interactive timeout", 
               boost::bind(&Client::setInteractive, this),
               Scheduler::instance().eventTime() + ClockService::milliseconds(INTERACTIVE_TIMEOUT),
@@ -240,7 +238,7 @@ prefix_ senf::console::Client::Client(Server & server, ClientHandle handle)
         setNoninteractive();
         break;
     case Server::Automatic :
-        binding_.enable();
+        readevent_.enable();
         timer_.enable();
         break;
     }
@@ -248,7 +246,7 @@ prefix_ senf::console::Client::Client(Server & server, ClientHandle handle)
 
 prefix_ void senf::console::Client::setInteractive()
 {
-    binding_.disable();
+    readevent_.disable();
     timer_.disable();
     mode_ = Server::Interactive;
     reader_.reset(new detail::SafeReadlineClientReader (*this));
@@ -257,7 +255,7 @@ prefix_ void senf::console::Client::setInteractive()
 
 prefix_ void senf::console::Client::setNoninteractive()
 {
-    binding_.disable();
+    readevent_.disable();
     timer_.disable();
     mode_ = Server::Noninteractive;
     reader_.reset(new detail::NoninteractiveClientReader(*this));
index 66426a0..1974a74 100644 (file)
@@ -35,7 +35,6 @@
 #include "../Socket/Protocols/INet/TCPSocketHandle.hh"
 #include "../Socket/ServerSocketHandle.hh"
 #include "../Scheduler/Scheduler.hh"
-#include "../Scheduler/Binding.hh"
 #include "../Scheduler/ReadHelper.hh"
 #include "Parse.hh"
 #include "Executor.hh"
@@ -80,8 +79,6 @@ namespace console {
 
         ///////////////////////////////////////////////////////////////////////////
 
-        ~Server();
-
         static Server & start(senf::INet4SocketAddress const & address);
                                         ///< Start server on given IPv4 address/port
         static Server & start(senf::INet6SocketAddress const & address);
@@ -132,6 +129,7 @@ namespace console {
         void removeClient(Client & client);
         
         ServerHandle handle_;
+        scheduler::FdEvent event_;
         DirectoryNode::ptr root_;
         Mode mode_;
         
@@ -195,7 +193,7 @@ namespace console {
         
         Server & server_;
         ClientHandle handle_;
-        SchedulerBinding binding_;
+        scheduler::FdEvent readevent_;
         scheduler::TimerEvent timer_;
         CommandParser parser_;
         Executor executor_;
index 3ca80a1..c65a88f 100644 (file)
@@ -173,7 +173,7 @@ namespace detail {
 
         void newData(int event);
 
-        SchedulerBinding binding_;
+        scheduler::FdEvent readevent_;
         std::string buffer_;
     };
     
index 211ebaf..0d6fb37 100644 (file)
@@ -44,16 +44,16 @@ class MCSniffer
 {
     senf::UDPv4ClientSocketHandle sock;
     std::ostream& stream;
+    senf::scheduler::FdEvent event;
 
 public:
     MCSniffer(senf::INet4Address addr, std::ostream& s)
-        : stream(s)
+        : stream(s), event("MCSniffer", senf::membind(&MCSniffer::dumpPacket, this),
+                           sock, senf::scheduler::FdEvent::EV_READ)
     {
         // sock.bind(addr);
         sock.protocol().mcLoop(true);
         sock.protocol().mcAddMembership(addr);
-        senf::Scheduler::instance().add(
-            sock, senf::membind(&MCSniffer::dumpPacket, this));
     }
 
 private:
index 7f74806..48e17ed 100644 (file)
@@ -67,17 +67,18 @@ int loop_main (int argc, char const * argv[])
 class Sniffer
 {
     senf::PacketSocketHandle sock;
+    senf::scheduler::FdEvent event;
 
 public:
     Sniffer(std::string const & interface)
+        : event ("Sniffer", senf::membind(&Sniffer::dumpPacket, this),
+                 sock, senf::scheduler::FdEvent::EV_READ)
     {
         sock.bind(senf::LLSocketAddress(interface));
     }
 
     void run()
     {
-        senf::Scheduler::instance().add(
-            sock, senf::membind(&Sniffer::dumpPacket, this));
         senf::Scheduler::instance().process();
     }
 
index 4dbf274..6eab3a2 100644 (file)
 class Server
 {
     senf::TCPv4ServerSocketHandle serverSock;
+    senf::scheduler::FdEvent acceptevent;
+    senf::scheduler::FdEvent readevent;
 
 public:
     Server(senf::INet4Address const & host, unsigned int port)
-        : serverSock(senf::INet4SocketAddress(host, port)) {}
+        : serverSock(senf::INet4SocketAddress(host, port)),
+          acceptevent("Server accept", senf::membind(&Server::accept, this),
+                      serverSock, senf::scheduler::FdEvent::EV_READ),
+          readevent("Server read", 0)
+        {}
 
     void run()
     {
-        senf::Scheduler::instance().add(
-            serverSock,
-            senf::membind(&Server::accept, this),
-            senf::Scheduler::EV_READ);
         senf::Scheduler::instance().process();
     }
 
@@ -53,16 +55,17 @@ private:
     void accept(int event)
     {
         senf::TCPv4ClientSocketHandle clientSock (serverSock.accept());
-        senf::Scheduler::instance().add(
-            clientSock,
-            boost::bind(&Server::readFromClient, this, clientSock, _1),
-            senf::Scheduler::EV_READ);
+        readevent
+            .action(boost::bind(&Server::readFromClient, this, clientSock, _1))
+            .handle(clientSock)
+            .events(senf::scheduler::FdEvent::EV_READ)
+            .enable();
     }
 
     void readFromClient(senf::TCPv4ClientSocketHandle clientSock, int event)
     {
         if (!clientSock) {
-            senf::Scheduler::instance().remove(clientSock);
+            readevent.disable();
             return;
         }
         std::string data (clientSock.read());
index d549a92..201ca3f 100644 (file)
 class Server
 {
     senf::UDPv4ClientSocketHandle serverSock;
+    senf::scheduler::FdEvent event;
 
 public:
     Server(senf::INet4Address const & host, unsigned int port)
-        : serverSock(senf::INet4SocketAddress(host, port)) {}
+        : serverSock(senf::INet4SocketAddress(host, port)),
+          event("UDPv4ClientServer", senf::membind(&Server::readFromClient, this),
+                serverSock, senf::scheduler::FdEvent::EV_READ, false)
+        {}
 
     void run()
     {
-        senf::Scheduler::instance().add(
-                serverSock,
-                senf::membind(&Server::readFromClient, this),
-                senf::Scheduler::EV_READ);
+        event.enable();
         senf::Scheduler::instance().process();
     }
 
@@ -63,3 +64,14 @@ int main(int argc, char const * argv[])
     }
     return 0;
 }
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u"
+// End:
index 73bcc5f..f63288d 100644 (file)
@@ -28,7 +28,6 @@
 
 // Custom includes
 #include "../Utils/senfassert.hh"
-#include <boost/bind.hpp>
 
 //#include "IOEvent.mpp"
 #define prefix_
 
 prefix_ void senf::ppi::IOEvent::v_enable()
 {
-    Scheduler::instance().add(fd_, boost::bind(&IOEvent::cb,this,_1),
-                              Scheduler::EventId(events_));
+    event_.enable();
 }
 
 prefix_ void senf::ppi::IOEvent::v_disable()
 {
-    Scheduler::instance().remove(fd_, Scheduler::EventId(events_));
+    event_.disable();
 }
 
 prefix_ void senf::ppi::IOEvent::cb(int event)
 {
-    if ((event & ~events_) != 0) {
+    if ((event & ~event_.events()) != 0) {
         if (event & Err)
             throw ErrorException();
         else if (event & Hup)
index 682d464..29c0fbb 100644 (file)
@@ -26,6 +26,7 @@
 //#include "IOEvent.ih"
 
 // Custom includes
+#include <boost/bind.hpp>
 
 #define prefix_ inline
 ///////////////////////////////cti.p///////////////////////////////////////
@@ -35,7 +36,8 @@
 
 template <class Handle>
 prefix_ senf::ppi::IOEvent::IOEvent(Handle handle, unsigned events)
-    : fd_(retrieve_filehandle(handle)), events_(events)
+    : fd_ (retrieve_filehandle(handle)),
+      event_ ("senf::ppi::IOEvent", boost::bind(&IOEvent::cb,this,_1), fd_, events, false) 
 {}
 
 ///////////////////////////////cti.e///////////////////////////////////////
index 77c5d26..7707cfb 100644 (file)
@@ -106,12 +106,12 @@ namespace ppi {
 
     private:
         virtual void v_enable();
-         virtual void v_disable();
+        virtual void v_disable();
         
         void cb(int event);
 
         int fd_;
-        unsigned events_;
+        scheduler::FdEvent event_;
     };
 
     
diff --git a/Scheduler/Binding.cci b/Scheduler/Binding.cci
deleted file mode 100644 (file)
index bd8e3e9..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2008 
-//
-// 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 Binding inline non-template implementation */
-
-//#include "Binding.ih"
-
-// Custom includes
-
-#define prefix_ inline
-///////////////////////////////cci.p///////////////////////////////////////
-
-prefix_ void senf::SchedulerBinding::enable()
-{
-    if (! enabled_) {
-        senf::Scheduler::instance().add(fd_, cb_, eventMask_);
-        enabled_ = true;
-    }
-}
-
-prefix_ void senf::SchedulerBinding::disable()
-{
-    if (enabled_) {
-        senf::Scheduler::instance().remove(fd_);
-        enabled_ = false;
-    }
-}
-
-prefix_ bool senf::SchedulerBinding::enabled()
-{
-    return enabled_;
-}
-
-prefix_ senf::SchedulerBinding::~SchedulerBinding()
-{
-    disable();
-}
-
-///////////////////////////////cci.e///////////////////////////////////////
-#undef prefix_
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
diff --git a/Scheduler/Binding.cti b/Scheduler/Binding.cti
deleted file mode 100644 (file)
index 3ae11e8..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2008 
-//
-// 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 Binding inline template implementation */
-
-//#include "Binding.ih"
-
-// Custom includes
-
-#define prefix_ inline
-///////////////////////////////cti.p///////////////////////////////////////
-
-template <class Handle>
-prefix_ senf::SchedulerBinding::SchedulerBinding(Handle const & handle,
-                                                 Scheduler::FdCallback cb, int eventMask,
-                                                 bool enabled)
-    : fd_ (retrieve_filehandle(handle)), cb_ (cb), eventMask_ (eventMask), enabled_ (false)
-{
-    if (enabled)
-        enable();
-}
-
-///////////////////////////////cti.e///////////////////////////////////////
-#undef prefix_
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
diff --git a/Scheduler/Binding.hh b/Scheduler/Binding.hh
deleted file mode 100644 (file)
index e8b535b..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2008 
-//
-// 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 Binding public header */
-
-#ifndef HH_Binding_
-#define HH_Binding_ 1
-
-// Custom includes
-#include <boost/utility.hpp>
-#include "Scheduler.hh"
-
-//#include "Binding.mpp"
-///////////////////////////////hh.p////////////////////////////////////////
-
-namespace senf {
-
-    /** \brief Manage scheduler handle binding
-
-        This class will manage the binding of an arbitrary handle to the scheduler: The handle will
-        automatically be removed from the Scheduler when this instance is destroyed. Example using a
-        SocketHandle instance for the handle:
-        \code
-        class Foo
-        {
-        public:
-            Foo(SocketHandle handle) : binding_ (handle, senf::membind(&cb, this),
-                                                 senf::Scheduler::EV_READ) {}
-
-            void blarf() { binding_.disable(); }
-
-        private:
-           void cb(Scheduler::EventId event);
-
-           senf::SchedulerBinding binding_;
-        };
-        \endcode
-
-        The handle will be registered automatically in the constructor and will be unregistered in
-        the destructor. Additionally, the helper has enable() and disable() members to register or
-        remove the handle to/from the Scheduler.
-     */
-    class SchedulerBinding
-        : boost::noncopyable
-    {
-    public:
-        template <class Handle>
-        SchedulerBinding(Handle const & handle, Scheduler::FdCallback cb, 
-                         int eventMask = Scheduler::EV_ALL, bool enabled = true);
-                                        ///< Register handle with the Scheduler
-                                        /**< This constructor is like calling Scheduler::add()
-                                             unless \a enabled is \c false, in which case the handle
-                                             is \e not initially registered (it may be registered by
-                                             caling enable() 
-                                             \param[in] handle Handle to register
-                                             \param[in] cb Callback
-                                             \param[in] eventMask type of events to register for
-                                             \param[in] enabled wether to add handle to Scheduler
-                                                 automatically  */
-
-        ~SchedulerBinding();            ///< Remove scheduler registration
-        
-        void enable();                  ///< Add handle to Scheduler
-                                        /**< Adds the handle if it is not already registered */
-        void disable();                 ///< Remove handle from Scheduler
-                                        /**< Remove handle from Scheduler if registered */
-
-        bool enabled();                 ///< \c true, if handle is registered
-
-    protected:
-
-    private:
-        int fd_;
-        Scheduler::FdCallback cb_;
-        int eventMask_;
-        bool enabled_;
-    };
-}
-
-///////////////////////////////hh.e////////////////////////////////////////
-#include "Binding.cci"
-//#include "Binding.ct"
-#include "Binding.cti"
-#endif
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
diff --git a/Scheduler/Binding.test.cc b/Scheduler/Binding.test.cc
deleted file mode 100644 (file)
index 662892b..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2008 
-//
-// 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 Binding.test unit tests */
-
-//#include "Binding.test.hh"
-//#include "Binding.test.ih"
-
-// Custom includes
-#include "Binding.hh"
-
-#include "../Utils/auto_unit_test.hh"
-#include <boost/test/test_tools.hpp>
-
-#define prefix_
-///////////////////////////////cc.p////////////////////////////////////////
-
-BOOST_AUTO_UNIT_TEST(binding)
-{
-}
-
-///////////////////////////////cc.e////////////////////////////////////////
-#undef prefix_
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
index 0e5d5be..35858a0 100644 (file)
@@ -131,11 +131,11 @@ prefix_ void senf::scheduler::FIFORunner::run()
             SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
         while (next_ != end) {
             TaskInfo & task (*next_);
-            if (task.runnable) {
-                task.runnable = false;
-                runningName_ = task.name;
+            if (task.runnable_) {
+                task.runnable_ = false;
+                runningName_ = task.name_;
 #           ifdef SENF_DEBUG
-                runningBacktrace_ = task.backtrace;
+                runningBacktrace_ = task.backtrace_;
 #           endif
                 TaskList::iterator i (next_);
                 ++ next_;
index 4bea7ba..209bd99 100644 (file)
 #define prefix_ inline
 ///////////////////////////////cci.p///////////////////////////////////////
 
-prefix_ senf::scheduler::FIFORunner::TaskInfo::TaskInfo(std::string const & name_)
-    : runnable (false), name (name_)
+prefix_ senf::scheduler::FIFORunner::TaskInfo::TaskInfo(std::string const & name)
+    : runnable_ (false), name_ (name)
 {}
 
 prefix_ senf::scheduler::FIFORunner::TaskInfo::~TaskInfo()
 {}
 
+prefix_ void senf::scheduler::FIFORunner::TaskInfo::setRunnable()
+{
+    runnable_ = true;
+}
+
 prefix_ void senf::scheduler::FIFORunner::enqueue(TaskInfo * task)
 {
     tasks_.push_back(*task);
 #ifdef SENF_DEBUG
     std::stringstream ss;
     backtrace(ss, 32);
-    task->backtrace = ss.str();
+    task->backtrace_ = ss.str();
 #endif
 }
 
index 2c04bc6..3887a3d 100644 (file)
@@ -70,22 +70,26 @@ namespace scheduler {
 
             TaskInfo is the base-class for all tasks.
          */
-        struct TaskInfo 
+        class TaskInfo 
             : public TaskListBase
         {
-            explicit TaskInfo(std::string const & name_);
+        public:
+            explicit TaskInfo(std::string const & name);
             virtual ~TaskInfo();
 
-            bool runnable;              ///< Runnable flag
-                                        /**< This must be set to \c true when the task is
-                                             runnable. It is reset automatically when the task is
-                                             run. */
+        protected:
+            void setRunnable();
+            
+        private:
+            virtual void run() = 0;
 
-            std::string name;           ///< Descriptive task name
+            bool runnable_;
+            std::string name_;
 #       ifdef SENF_DEBUG
-            std::string backtrace;
+            std::string backtrace_;
 #       endif
-            virtual void run() = 0;     ///< Called to run the task
+
+            friend class FIFORunner;
         };
 
         ///////////////////////////////////////////////////////////////////////////
@@ -135,7 +139,6 @@ namespace scheduler {
         friend class senf::Scheduler;
     };
 
-
 }}
 
 ///////////////////////////////hh.e////////////////////////////////////////
diff --git a/Scheduler/FdDispatcher.cc b/Scheduler/FdDispatcher.cc
deleted file mode 100644 (file)
index 4d8007b..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2008 
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-//     Stefan Bund <g0dil@berlios.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 FdDispatcher non-inline non-template implementation */
-
-#include "FdDispatcher.hh"
-#include "FdDispatcher.ih"
-
-// Custom includes
-#include "../Utils/senfassert.hh"
-
-//#include "FdDispatcher.mpp"
-#define prefix_
-///////////////////////////////cc.p////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////
-// senf::scheduler::FdDispatcher
-
-prefix_ senf::scheduler::FdDispatcher::~FdDispatcher()
-{
-    for (FdMap::iterator i (fds_.begin()); i != fds_.end(); ++i) {
-        manager_.remove(i->first);
-        runner_.dequeue(static_cast<FdEvent::ReadTask*>(&i->second));
-        runner_.dequeue(static_cast<FdEvent::PrioTask*>(&i->second));
-        runner_.dequeue(static_cast<FdEvent::WriteTask*>(&i->second));
-    }
-}
-
-prefix_ bool senf::scheduler::FdDispatcher::add(std::string const & name, int fd,
-                                                Callback const & cb, int events)
-{
-    if (events == 0)
-        return true;
-    
-    FdMap::iterator i (fds_.find(fd));
-    if (i == fds_.end()) {
-        i = fds_.insert(std::make_pair(fd, FdEvent(name))).first;
-        runner_.enqueue(static_cast<FdEvent::ReadTask*>(&i->second));
-        runner_.enqueue(static_cast<FdEvent::PrioTask*>(&i->second));
-        runner_.enqueue(static_cast<FdEvent::WriteTask*>(&i->second));
-    }
-    FdEvent & event (i->second);
-
-    if (events & EV_READ) 
-        event.FdEvent::ReadTask::cb = cb;
-    if (events & EV_PRIO) 
-        event.FdEvent::PrioTask::cb = cb;
-    if (events & EV_WRITE) 
-        event.FdEvent::WriteTask::cb = cb;
-
-    if (! manager_.set(fd, event.activeEvents(), &event)) {
-        runner_.dequeue(static_cast<FdEvent::ReadTask*>(&i->second));
-        runner_.dequeue(static_cast<FdEvent::PrioTask*>(&i->second));
-        runner_.dequeue(static_cast<FdEvent::WriteTask*>(&i->second));
-        fds_.erase(i);
-        return false;
-    }
-    else
-        return true;
-}
-
-prefix_ void senf::scheduler::FdDispatcher::remove(int fd, int events)
-{
-    if (events == 0)
-        return;
-
-    FdMap::iterator i (fds_.find(fd));
-    if (i == fds_.end())
-        return;
-    FdEvent & event (i->second);
-
-    if (events & EV_READ) 
-        event.FdEvent::ReadTask::cb = 0;
-    if (events & EV_PRIO) 
-        event.FdEvent::PrioTask::cb = 0;
-    if (events & EV_WRITE)
-        event.FdEvent::WriteTask::cb = 0;
-
-    int activeEvents (event.activeEvents());
-    if (! activeEvents) {
-        manager_.remove(fd);
-        runner_.dequeue(static_cast<FdEvent::ReadTask*>(&i->second));
-        runner_.dequeue(static_cast<FdEvent::PrioTask*>(&i->second));
-        runner_.dequeue(static_cast<FdEvent::WriteTask*>(&i->second));
-        fds_.erase(fd);
-    } else
-        manager_.set(fd, activeEvents, &event);
-}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::scheduler::FdDispatcher::FdEvent
-
-prefix_ void senf::scheduler::FdDispatcher::FdEvent::signal(int e)
-{
-    events = e;
-
-    if (events & EV_READ) 
-        ReadTask::runnable = true;
-    if (events & EV_PRIO) 
-        PrioTask::runnable = true;
-    if (events & EV_WRITE)
-        WriteTask::runnable = true;
-
-    if ((events & (EV_ERR | EV_HUP)) && ! (events & (EV_READ | EV_PRIO | EV_WRITE))) {
-        if (ReadTask::cb) ReadTask::runnable = true;
-        if (PrioTask::cb) PrioTask::runnable = true;
-        if (WriteTask::cb) WriteTask::runnable = true;
-    }
-}
-
-///////////////////////////////cc.e////////////////////////////////////////
-#undef prefix_
-//#include "FdDispatcher.mpp"
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
diff --git a/Scheduler/FdDispatcher.cci b/Scheduler/FdDispatcher.cci
deleted file mode 100644 (file)
index d7c1034..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2008 
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-//     Stefan Bund <g0dil@berlios.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 FdDispatcher inline non-template implementation */
-
-#include "FdDispatcher.ih"
-
-// Custom includes
-
-#define prefix_ inline
-///////////////////////////////cci.p///////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////
-// senf::scheduler::FdDispatcher
-
-prefix_ senf::scheduler::FdDispatcher::FdDispatcher(FdManager & manager, FIFORunner & runner)
-    : manager_ (manager), runner_ (runner)
-{}
-
-prefix_ bool senf::scheduler::FdDispatcher::empty()
-    const
-{
-    return fds_.empty();
-}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::scheduler::FdDispatcher::FdEvent
-
-prefix_ int senf::scheduler::FdDispatcher::FdEvent::activeEvents()
-    const
-{
-    return 
-        (ReadTask::cb ? EV_READ : 0) | 
-        (PrioTask::cb ? EV_PRIO : 0) |
-        (WriteTask::cb ? EV_WRITE : 0);
-}
-
-///////////////////////////////cci.e///////////////////////////////////////
-#undef prefix_
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
diff --git a/Scheduler/FdDispatcher.hh b/Scheduler/FdDispatcher.hh
deleted file mode 100644 (file)
index bfca398..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2008 
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-//     Stefan Bund <g0dil@berlios.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 FdDispatcher public header */
-
-#ifndef HH_FdDispatcher_
-#define HH_FdDispatcher_ 1
-
-// Custom includes
-#include <map>
-#include "FdManager.hh"
-#include "FIFORunner.hh"
-
-//#include "FdDispatcher.mpp"
-#include "FdDispatcher.ih"
-///////////////////////////////hh.p////////////////////////////////////////
-
-namespace senf {
-namespace scheduler {
-
-    /** \brief Scheduler dispatcher managing poll-able file descriptors
-
-        File descriptors are added directly to the event loop.
-      */
-    class FdDispatcher
-    {
-    public:
-        ///////////////////////////////////////////////////////////////////////////
-        // Types
-
-        typedef boost::function<void (int)> Callback;
-
-        enum Events { 
-            EV_READ = FdManager::EV_READ, EV_PRIO = FdManager::EV_PRIO, EV_WRITE = FdManager::EV_WRITE,
-            EV_HUP = FdManager::EV_HUP, EV_ERR = FdManager::EV_ERR,
-            EV_ALL = FdManager::EV_READ | FdManager::EV_WRITE | FdManager::EV_PRIO
-        };
-
-        ///////////////////////////////////////////////////////////////////////////
-        ///\name Structors and default members
-        ///@{
-        
-        FdDispatcher(FdManager & manager, FIFORunner & runner);
-        ~FdDispatcher();
-
-        ///@}
-        ///////////////////////////////////////////////////////////////////////////
-
-        bool add(std::string const & name, int fd, Callback const & cb, int events = EV_ALL);
-                                        ///< Add file descriptor callback
-                                        /**< There is always one active callback for each
-                                             combination of file descriptor and event. Registering a
-                                             new callback will overwrite the old callback.
-                                             \param[in] name descriptive name
-                                             \param[in] fd file descriptor
-                                             \param[in] cb callback
-                                             \param[in] events Events to call \a cb for */
-
-        void remove(int fd, int events = EV_ALL); ///< Remove callback
-                                        /**< \param[in] fd file descriptor
-                                             \param[in] events Events for which to remove the
-                                                 callback */
-        
-        bool empty() const;             ///< \c true, if no file descriptors are registered.
-
-    protected:
-
-    private:
-        /// Internal: File descriptor event
-        struct FdEvent 
-            : public detail::FdTask<0, FdEvent>,
-              public detail::FdTask<1, FdEvent>,
-              public detail::FdTask<2, FdEvent>,
-              public FdManager::Event
-        {
-            typedef detail::FdTask<0, FdEvent> ReadTask;
-            typedef detail::FdTask<1, FdEvent> PrioTask;
-            typedef detail::FdTask<2, FdEvent> WriteTask;
-
-            explicit FdEvent(std::string const & name)
-                : ReadTask (name), PrioTask (name), WriteTask (name) {}
-
-            virtual void signal(int events);
-            int activeEvents() const;
-            int events;
-        };
-
-        typedef std::map<int, FdEvent> FdMap;
-
-        FdMap fds_;
-        FdManager & manager_;
-        FIFORunner & runner_;
-    };
-
-}}
-
-///////////////////////////////hh.e////////////////////////////////////////
-#include "FdDispatcher.cci"
-#include "FdDispatcher.ct"
-#include "FdDispatcher.cti"
-#endif
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
diff --git a/Scheduler/FdDispatcher.ih b/Scheduler/FdDispatcher.ih
deleted file mode 100644 (file)
index b0c1c01..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2008 
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-//     Stefan Bund <g0dil@berlios.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 FdDispatcher internal header */
-
-#ifndef IH_FdDispatcher_
-#define IH_FdDispatcher_ 1
-
-// Custom includes
-
-///////////////////////////////ih.p////////////////////////////////////////
-
-namespace senf {
-namespace scheduler {
-namespace detail {
-    
-    /** \brief Internal: File descriptor task
-        
-        \implementation This class allows to inherit FIFORunner::TaskInfo multiple times to add
-            multiple tasks to one event and still allows efficient access to the event class
-     */
-    template <unsigned index, class Self>
-    struct FdTask
-        : public FIFORunner::TaskInfo
-    {
-        explicit FdTask(std::string const & name) 
-            : FIFORunner::TaskInfo (name) {}
-
-        typedef boost::function<void (int)> Callback;
-        virtual void run();
-        Self & self();
-        Callback cb;
-    };
-
-}}}
-
-///////////////////////////////ih.e////////////////////////////////////////
-#endif
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
diff --git a/Scheduler/FdEvent.cc b/Scheduler/FdEvent.cc
new file mode 100644 (file)
index 0000000..58c3d7e
--- /dev/null
@@ -0,0 +1,189 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.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 FdDispatcher non-inline non-template implementation */
+
+#include "FdEvent.hh"
+#include "FdEvent.ih"
+
+// Custom includes
+#include "../Utils/senfassert.hh"
+
+//#include "FdEvent.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::detail::FdDispatcher
+
+prefix_ senf::scheduler::detail::FdDispatcher::~FdDispatcher()
+{
+    for (FdSet::iterator i (fds_.begin()); i != fds_.end(); ++i) {
+        FdManager::instance().remove(i->fd_);
+        FIFORunner::instance().dequeue(&(*i));
+    }
+}
+
+prefix_ bool senf::scheduler::detail::FdDispatcher::add(FdEvent & event)
+{
+    std::pair<FdSet::iterator,FdSet::iterator> range (fds_.equal_range(event));
+    int events (0);
+    for (FdSet::iterator i (range.first); i != range.second; ++i)
+       events |= i->events_;
+    if (event.events_ & events)
+       throw FdEvent::DuplicateEventRegistrationException();
+
+    if (! FdManager::instance().set(event.fd_, events | event.events_, &event))
+        return false;
+
+    FIFORunner::instance().enqueue(&event);
+    fds_.insert(range.first, event);
+
+    return true;
+}
+
+prefix_ void senf::scheduler::detail::FdDispatcher::remove(FdEvent & event)
+{
+    fds_.erase(FdSet::current(event));
+    FIFORunner::instance().dequeue(&event);
+
+    std::pair<FdSet::iterator,FdSet::iterator> range (fds_.equal_range(event));
+    if (range.first == range.second)
+       FdManager::instance().remove(event.fd_);
+    else {
+        int events (0);
+        for (FdSet::iterator i (range.first); i != range.second; ++i)
+            events |= i->events_;
+       FdManager::instance().set(event.fd_, events, &(*range.first));
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::detail::FileDispatcher
+
+prefix_ void senf::scheduler::detail::FileDispatcher::add(FdEvent & event)
+{
+    std::pair<FdSet::iterator,FdSet::iterator> range (fds_.equal_range(event));
+    int events (0);
+    for (FdSet::iterator i (range.first); i != range.second; ++i)
+       events |= i->events_;
+    if (event.events_ & events)
+       throw FdEvent::DuplicateEventRegistrationException();
+
+    FIFORunner::instance().enqueue(&event);
+    fds_.insert(range.first, event);
+
+    FdManager::instance().timeout(0);
+}
+
+prefix_ senf::scheduler::detail::FileDispatcher::FileDispatcher()
+    : managerTimeout_ (scheduler::FdManager::instance().timeout())
+{}
+
+prefix_ senf::scheduler::detail::FileDispatcher::~FileDispatcher()
+{
+    FdManager::instance().timeout(-1);
+    for (FdSet::iterator i (fds_.begin()); i != fds_.end(); ++i)
+        FIFORunner::instance().dequeue(&(*i));
+}
+
+prefix_ void senf::scheduler::detail::FileDispatcher::prepareRun()
+{
+    for (FdSet::iterator i (fds_.begin()); i != fds_.end(); ++i) {
+        i->signaledEvents_ = i->events_;
+        i->setRunnable();
+    }
+}
+
+prefix_ void senf::scheduler::detail::FileDispatcher::remove(FdEvent & event)
+{
+    fds_.erase(FdSet::current(event));
+    FIFORunner::instance().dequeue(&event);
+    if (fds_.empty())
+        FdManager::instance().timeout(managerTimeout_);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::FdEvent
+
+prefix_ void senf::scheduler::FdEvent::disable()
+{
+    if (enabled()) {
+        if (pollable_)
+            detail::FdDispatcher::instance().remove(*this);
+        else
+            detail::FileDispatcher::instance().remove(*this);
+    }
+}
+
+prefix_ void senf::scheduler::FdEvent::enable()
+{
+    if (! enabled() && events_ && fd_ != -1) {
+        if (pollable_ && detail::FdDispatcher::instance().add(*this))
+            return;
+        detail::FileDispatcher::instance().add(*this);
+        pollable_ = false;
+    }
+}
+
+prefix_ senf::scheduler::FdEvent & senf::scheduler::FdEvent::events(int events)
+{
+    bool en = enabled();
+    disable();
+    events_ = events;
+    if (en)
+       enabled();
+    return *this;
+}
+
+prefix_ void senf::scheduler::FdEvent::signal(int events)
+{
+    detail::FdDispatcher::FdSet::iterator i (detail::FdDispatcher::FdSet::current(*this));
+    detail::FdDispatcher::FdSet::iterator const i_end (detail::FdDispatcher::instance().fds_.end());
+    bool all ((events & (EV_ERR | EV_HUP)) && ! (events & (EV_READ | EV_PRIO | EV_WRITE)));
+    for (; i != i_end && fd_ == i->fd_; ++i) {
+       i->signaledEvents_ = events;
+       if (i->events_ & events || all)
+           i->setRunnable();
+    }
+}
+
+prefix_ void senf::scheduler::FdEvent::run()
+{
+    cb_(signaledEvents_);
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "FdEvent.mpp"
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Scheduler/FdEvent.cci b/Scheduler/FdEvent.cci
new file mode 100644 (file)
index 0000000..5391f71
--- /dev/null
@@ -0,0 +1,129 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.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 FdDispatcher inline non-template implementation */
+
+#include "FdEvent.ih"
+
+// Custom includes
+#include "../Utils/senfassert.hh"
+#include "FdManager.hh"
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::FdEvent
+
+prefix_ senf::scheduler::FdEvent::FdEvent(std::string const & name, Callback const & cb)
+    : FIFORunner::TaskInfo (name), cb_ (cb), fd_ (-1), pollable_ (true), events_ (0)
+{}
+
+prefix_ senf::scheduler::FdEvent::~FdEvent()
+{
+    if (detail::FdDispatcher::alive())
+       disable();
+}
+
+prefix_ bool senf::scheduler::FdEvent::enabled()
+{
+    return detail::FdSetBase::linked();
+}
+
+prefix_ senf::scheduler::FdEvent & senf::scheduler::FdEvent::action(Callback const & cb)
+{
+    cb_ = cb;
+    return *this;
+}
+
+prefix_ senf::scheduler::FdEvent & senf::scheduler::FdEvent::addEvents(int e)
+{
+    events( events() | e );
+    return *this;
+}
+
+prefix_ senf::scheduler::FdEvent & senf::scheduler::FdEvent::removeEvents(int e)
+{
+    events( events() & ~e );
+    return *this;
+}
+
+prefix_ int senf::scheduler::FdEvent::events()
+{
+    return events_;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::detail::FdDispatcher
+
+prefix_ senf::scheduler::detail::FdDispatcher::FdDispatcher()
+{}
+
+prefix_ bool senf::scheduler::detail::FdDispatcher::empty()
+    const
+{
+    return fds_.empty();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::detail::FileDispatcher
+
+prefix_ void senf::scheduler::detail::FileDispatcher::timeout(int t)
+{
+    managerTimeout_ = t;
+    if (fds_.empty())
+        FdManager::instance().timeout(managerTimeout_);
+}
+
+prefix_ int senf::scheduler::detail::FileDispatcher::timeout()
+    const
+{
+    return managerTimeout_;
+}
+
+prefix_ bool senf::scheduler::detail::FileDispatcher::empty()
+    const
+{
+    return fds_.empty();
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+prefix_ int senf::scheduler::retrieve_filehandle(int fd)
+{
+    return fd;
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
similarity index 78%
rename from Scheduler/FdDispatcher.ct
rename to Scheduler/FdEvent.ct
index 5451da7..c6dfbf9 100644 (file)
 /** \file
     \brief FdDispatcher non-inline template implementation  */
 
-#include "FdDispatcher.ih"
+#include "FdEvent.ih"
 
 // Custom includes
 
 #define prefix_
 ///////////////////////////////ct.p////////////////////////////////////////
 
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::FdEvent
+
+template <class Handle>
+prefix_ senf::scheduler::FdEvent & senf::scheduler::FdEvent::handle(Handle const & handle)
+{
+    bool en (enabled());
+    fd_ = retrieve_filehandle(handle);
+    pollable_ = true;
+    if (en)
+        enable();
+    return *this;
+}
+
 ///////////////////////////////ct.e////////////////////////////////////////
 #undef prefix_
 
similarity index 76%
rename from Scheduler/FdDispatcher.cti
rename to Scheduler/FdEvent.cti
index b82d411..f33ef1c 100644 (file)
@@ -23,7 +23,7 @@
 /** \file
     \brief FdDispatcher inline template implementation */
 
-#include "FdDispatcher.ih"
+#include "FdEvent.ih"
 
 // Custom includes
 
 ///////////////////////////////cti.p///////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::scheduler::detail::FdTask<index,Self>
-
-template <unsigned index, class Self>
-prefix_ void senf::scheduler::detail::FdTask<index,Self>::run()
-{
-    cb(self().events);
-}
-
-template <unsigned index, class Self>
-prefix_ Self & senf::scheduler::detail::FdTask<index,Self>::self()
+// senf::scheduler::FdEvent
+
+template <class Handle>
+prefix_ senf::scheduler::FdEvent::FdEvent(std::string const & name, Callback const & cb,
+                                          Handle const & handle, int events,
+                                          bool initiallyEnabled)
+    : FIFORunner::TaskInfo (name), cb_ (cb), fd_ (retrieve_filehandle(handle)), pollable_ (true),
+      events_ (events)
 {
-    return static_cast<Self&>(*this);
+    if (initiallyEnabled)
+       enable();
 }
 
 ///////////////////////////////cti.e///////////////////////////////////////
diff --git a/Scheduler/FdEvent.hh b/Scheduler/FdEvent.hh
new file mode 100644 (file)
index 0000000..736c3cf
--- /dev/null
@@ -0,0 +1,183 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.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 FdDispatcher public header */
+
+#ifndef HH_FdDispatcher_
+#define HH_FdDispatcher_ 1
+
+// Custom includes
+#include "../boost/intrusive/iset_hook.hpp"
+#include "../Utils/Exception.hh"
+#include "FdManager.hh"
+#include "FIFORunner.hh"
+
+//#include "FdEvent.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace scheduler {
+
+    namespace detail {
+       struct FdSetTag;
+       typedef boost::intrusive::iset_base_hook<FdSetTag> FdSetBase;
+        struct FdSetCompare;
+        struct FindFd;
+        class FdDispatcher;
+        class FileDispatcher;
+    }
+
+    /** \brief File descriptor event
+
+        The FdEvent class registers a file descriptor for read or write events.
+
+        The type of event is specified using an event mask. Possible events are
+
+        \li \c EV_READ: File descriptor is readable (or at EOF)
+        \li \c EV_PRIO: There is out-of-band data available to be read on the file descriptor
+        \li \c EV_WRITE: File descriptor is writable
+
+        These event flags can be or-ed together to form an event mask. The callback will be called
+        with those flags set which are currently signaled. There are additional flags which may be
+        set when calling the callback:
+
+        \li \c EV_HUP: The other end has closed the connection
+        \li \c EV_ERR: Transport error
+
+        The file descriptor is specified using an arbitrary handle type which supports the \c
+        retrieve_filehandle() protocol: There must be a global function \c retrieve_filehandle
+        callable with the handle type. This function must return the file descriptor associated with
+        the handle. Implementations for integer numbers (explicit file descriptors) and senf socket
+        handles are provided.
+
+        The FdEvent class is an implementation of the RAII idiom: The event will be automatically
+        unregistered in the FdEvent destructor. The TimerEvent instance should be created
+        within the same scope or on a scope below where the callback is defined (e.g. if the
+        callback is a member function it should be defined as a class member).
+     */
+    class FdEvent
+       : public FIFORunner::TaskInfo,
+         public detail::FdSetBase,
+         public FdManager::Event
+    {
+    public: 
+        ///////////////////////////////////////////////////////////////////////////
+        // Types
+
+       typedef boost::function<void (int)> Callback;
+
+        enum Events { 
+            EV_READ = FdManager::EV_READ, EV_PRIO = FdManager::EV_PRIO, EV_WRITE = FdManager::EV_WRITE,
+            EV_HUP = FdManager::EV_HUP, EV_ERR = FdManager::EV_ERR,
+            EV_ALL = FdManager::EV_READ | FdManager::EV_WRITE | FdManager::EV_PRIO
+        };
+
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Structors and default members
+        ///@{
+
+        template <class Handle>
+       FdEvent(std::string const & name, Callback const & cb, Handle const & handle, int events,
+               bool initiallyEnabled = true);
+                                        ///< Register a file descriptor event
+                                        /**< Registers \a cb to be called when any of the \a events
+                                             occurs on \a handle. If \a initiallyEnabled is set \c
+                                             false, the callback will not be enabled
+                                             automatically. Use enable() to do so.
+                                             \param[in] name Descriptive event name (purely
+                                                 informational)
+                                             \param[in] cb Callback to call
+                                             \param[in] handle Handle (file descriptor) to watch
+                                             \param[in] events Events to watch for (see Events enum)
+                                             \param[in] initiallyEnabled if set \c false, do not
+                                                 enable callback automatically. */
+        FdEvent(std::string const & name, Callback const & cb);
+                                        ///< Create a file descriptor event
+                                        /**< Creates a file descriptor event for callback \a cb. The
+                                             event is initially disabled. Use the other members to
+                                             set the missing parameters and enable the event.
+                                             \param[in] name Descriptive event name (purely
+                                                 informational)
+                                             \param[in] cb Callback to call. This callback may \e
+                                                 explicitly be set to \c 0 if the value cannot be
+                                                 initialized. */
+       ~FdEvent();
+        
+        ///@}
+        ///////////////////////////////////////////////////////////////////////////
+
+       void disable();                 ///< Disable event
+       void enable();                  ///< Enable event
+       bool enabled();                 ///< \c true if event enabled, \c false otherwise
+
+       FdEvent & action(Callback const & cb); ///< Change event callback
+
+       FdEvent & events(int events);   ///< Change event mask
+        FdEvent & addEvents(int events); ///< Add additional events to event mask
+        FdEvent & removeEvents(int events); ///< Remove events from event mask
+        int events();                   ///< Current event mask
+        
+        template <class Handle>
+        FdEvent & handle(Handle const & handle); ///< Change event file handle
+
+        struct DuplicateEventRegistrationException : public Exception
+        { DuplicateEventRegistrationException() : Exception("duplicate fd event registration") {} };
+
+    protected:
+
+    private:
+       virtual void signal(int events);
+       virtual void run();
+
+       Callback cb_;
+       int fd_;
+        bool pollable_;
+       int events_;
+       int signaledEvents_;
+
+        friend class detail::FdSetCompare;
+        friend class detail::FindFd;
+        friend class detail::FdDispatcher;
+        friend class detail::FileDispatcher;
+    };
+
+    int retrieve_filehandle(int fd);
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "FdEvent.cci"
+#include "FdEvent.ct"
+#include "FdEvent.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Scheduler/FdEvent.ih b/Scheduler/FdEvent.ih
new file mode 100644 (file)
index 0000000..15d106c
--- /dev/null
@@ -0,0 +1,132 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.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 FdDispatcher internal header */
+
+#ifndef IH_FdDispatcher_
+#define IH_FdDispatcher_ 1
+
+// Custom includes
+#include "../boost/intrusive/iset.hpp"
+
+///////////////////////////////ih.p////////////////////////////////////////
+
+namespace senf {
+
+    class Scheduler;
+
+namespace scheduler {
+namespace detail {
+
+    struct FdSetCompare {
+       bool operator()(FdEvent const & a, FdEvent const & b) const
+       { return a.fd_ < b.fd_; }
+    };
+
+    struct FindFd {
+       bool operator()(FdEvent const & a, int b) const
+       { return a.fd_ < b; }
+       bool operator()(int a, FdEvent const & b) const
+       { return a < b.fd_; }
+    };
+    
+    class FdDispatcher
+       : public senf::singleton<FdDispatcher>
+    {
+    public:
+       using senf::singleton<FdDispatcher>::instance;
+       using senf::singleton<FdDispatcher>::alive;
+       
+        bool add(FdEvent & event);
+        void remove(FdEvent & event);
+
+        bool empty() const;
+
+    protected:
+
+    private:
+        FdDispatcher();
+        ~FdDispatcher();
+
+       typedef boost::intrusive::imultiset< FdSetBase::value_traits<FdEvent>,
+                                            FdSetCompare,
+                                            false > FdSet;
+
+        FdSet fds_;
+
+        friend class senf::Scheduler;
+        friend class singleton<FdDispatcher>;
+        friend class senf::scheduler::FdEvent;
+    };
+
+    class FileDispatcher
+       : public senf::singleton<FileDispatcher>
+    {
+    public:
+       using senf::singleton<FileDispatcher>::instance;
+       using senf::singleton<FileDispatcher>::alive;
+
+        void add(FdEvent & event);
+        void remove(FdEvent & event);
+
+        void prepareRun();
+
+        void timeout(int t);
+        int timeout() const;
+
+        bool empty() const;
+
+    protected:
+
+    private:
+        FileDispatcher();
+        ~FileDispatcher();
+
+        // We really only need a list here but we need to use the same event structure used by
+        // the FdEvent.
+       typedef boost::intrusive::imultiset< FdSetBase::value_traits<FdEvent>,
+                                            FdSetCompare,
+                                            false > FdSet;
+
+        FdSet fds_;
+        int managerTimeout_;
+
+        friend class senf::Scheduler;
+        friend class singleton<FileDispatcher>;
+    };
+
+}}}
+
+///////////////////////////////ih.e////////////////////////////////////////
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
similarity index 58%
rename from Scheduler/FdDispatcher.test.cc
rename to Scheduler/FdEvent.test.cc
index 6e20cc8..39c0acf 100644 (file)
 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 /** \file
-    \brief FdDispatcher.test unit tests */
+    \brief FdEvent.test unit tests */
 
-//#include "FdDispatcher.test.hh"
-//#include "FdDispatcher.test.ih"
+//#include "FdEvent.test.hh"
+//#include "FdEvent.test.ih"
 
 // Custom includes
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <sys/wait.h>
 #include <unistd.h>
 #include <sys/socket.h>
@@ -36,7 +38,7 @@
 #include <string.h>
 #include <iostream>
 
-#include "FdDispatcher.hh"
+#include "FdEvent.hh"
 
 #include <boost/bind.hpp>
 
@@ -145,14 +147,14 @@ namespace {
     {
         ++calls;
         event = ev;
-        switch (event & senf::scheduler::FdDispatcher::EV_ALL) {
-        case senf::scheduler::FdDispatcher::EV_READ:
+        switch (event & senf::scheduler::FdEvent::EV_ALL) {
+        case senf::scheduler::FdEvent::EV_READ:
             size = recv(fd,buffer,1024,0);
             break;
-        case senf::scheduler::FdDispatcher::EV_PRIO:
+        case senf::scheduler::FdEvent::EV_PRIO:
             size = recv(fd,buffer,1024,MSG_OOB);
             break;
-        case senf::scheduler::FdDispatcher::EV_WRITE:
+        case senf::scheduler::FdEvent::EV_WRITE:
             size = write(fd,buffer,size);
             break;
         }
@@ -162,7 +164,6 @@ namespace {
 
 BOOST_AUTO_UNIT_TEST(fdDispatcher)
 {
-    senf::scheduler::FdDispatcher dispatcher (senf::scheduler::FdManager::instance(), senf::scheduler::FIFORunner::instance());
     senf::scheduler::FdManager::instance().timeout(1000);
 
     int pid (start_server());
@@ -182,50 +183,102 @@ BOOST_AUTO_UNIT_TEST(fdDispatcher)
         error("connect");
         BOOST_FAIL("connect");
     }
+    
+    {
+        senf::scheduler::FdEvent sockread ("testHandler",  boost::bind(&callback, sock, _1),
+                                           sock, senf::scheduler::FdEvent::EV_READ);
+        senf::scheduler::FdEvent sockwrite ("testHandler", boost::bind(&callback, sock, _1),
+                                            sock, senf::scheduler::FdEvent::EV_WRITE, false);
+        event = 0;
+        SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
+        SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+        BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_READ );
+        BOOST_CHECK_EQUAL( size, 4 );
+        buffer[size] = 0;
+        BOOST_CHECK_EQUAL( buffer, "READ" );
+
+        strcpy(buffer,"WRITE");
+        size=5;
+        SENF_CHECK_NO_THROW( sockwrite.enable() );
+        event = 0;
+        sleep(1);
+        SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
+        SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+        BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_WRITE );
+
+        SENF_CHECK_NO_THROW( sockwrite.disable() );
+        event = 0;
+        sleep(1);
+        SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
+        SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+        BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_HUP | senf::scheduler::FdEvent::EV_READ );
+        BOOST_CHECK_EQUAL( size, 2 );
+        buffer[size]=0;
+        BOOST_CHECK_EQUAL( buffer, "OK" );
+
+        BOOST_CHECK_EQUAL( calls, 3 );
+        SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+        BOOST_CHECK_EQUAL( calls, 3 );
+    
+        // Ensure, removing an already closed file-descriptor doesn't wreak havoc
+        close(sock);
+    }
 
-    BOOST_CHECK( dispatcher.add("testHandler", sock, boost::bind(&callback, sock, _1),
-                                senf::scheduler::FdDispatcher::EV_READ) );
-    event = 0;
-    SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
-    SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
-    BOOST_CHECK_EQUAL( event, senf::scheduler::FdDispatcher::EV_READ );
-    BOOST_CHECK_EQUAL( size, 4 );
-    buffer[size] = 0;
-    BOOST_CHECK_EQUAL( buffer, "READ" );
-
-    strcpy(buffer,"WRITE");
-    size=5;
-    BOOST_CHECK( dispatcher.add("testHandler", sock, boost::bind(&callback, sock, _1),
-                                senf::scheduler::FdDispatcher::EV_WRITE) );
-    event = 0;
-    sleep(1);
-    SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
     SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
-    BOOST_CHECK_EQUAL( event, senf::scheduler::FdDispatcher::EV_WRITE );
+    BOOST_CHECK_EQUAL( calls, 3 );
 
-    SENF_CHECK_NO_THROW( dispatcher.remove(sock, senf::scheduler::FdDispatcher::EV_WRITE) );
-    event = 0;
-    sleep(1);
-    SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
-    SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
-    BOOST_CHECK_EQUAL( event, senf::scheduler::FdDispatcher::EV_HUP | senf::scheduler::FdDispatcher::EV_READ );
-    BOOST_CHECK_EQUAL( size, 2 );
-    buffer[size]=0;
-    BOOST_CHECK_EQUAL( buffer, "OK" );
+    BOOST_CHECK (stop_server(pid));
+}
 
-    BOOST_CHECK_EQUAL( calls, 3 );
-    SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
-    BOOST_CHECK_EQUAL( calls, 3 );
+namespace {
+
+    bool is_close(senf::ClockService::clock_type a, senf::ClockService::clock_type b)
+    {
+        return (a<b ? b-a : a-b) < senf::ClockService::milliseconds(100);
+    }
+
+    bool called (false);
+    void handler(int events)
+    {
+        called=true;
+    }
+}
+
+BOOST_AUTO_UNIT_TEST(fileDispatcher)
+{
+    senf::scheduler::detail::FileDispatcher::instance().timeout(500);
+
+    int fd (open("test.empty.file", O_RDWR|O_CREAT|O_TRUNC, 0600));
     
-    // Ensure, removing an already closed file-descriptor doesn't wreak havoc
-    close(sock);
-    SENF_CHECK_NO_THROW( dispatcher.remove(sock) );
+    senf::ClockService::clock_type t (senf::ClockService::now());
+    try {
+        senf::scheduler::FdEvent fde ("testHandler", &handler, 
+                                      fd, senf::scheduler::FdEvent::EV_READ);
+        SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
+        SENF_CHECK_NO_THROW( senf::scheduler::detail::FileDispatcher::instance().prepareRun() );
+        SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+        
+        BOOST_CHECK( called );
+        BOOST_CHECK_PREDICATE( is_close, (t)(senf::ClockService::now()) );
+    }
+    catch (std::exception const & ex) {
+        std::cerr << "Exception:\n" << ex.what() << "\n";
+        throw;
+    }
+    close(fd);
 
+    called = false;
+    t = senf::ClockService::now();
+    SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
+    SENF_CHECK_NO_THROW( senf::scheduler::detail::FileDispatcher::instance().prepareRun() );
     SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
-    BOOST_CHECK_EQUAL( calls, 3 );
 
+    BOOST_CHECK( ! called );
+    BOOST_CHECK_PREDICATE( 
+        is_close, (t+senf::ClockService::milliseconds(500))(senf::ClockService::now()) );
 
-    BOOST_CHECK (stop_server(pid));
+    unlink("test.empty.file");
+    senf::scheduler::detail::FileDispatcher::instance().timeout(-1);
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
diff --git a/Scheduler/FileDispatcher.cc b/Scheduler/FileDispatcher.cc
deleted file mode 100644 (file)
index 6ada898..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2008 
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-//     Stefan Bund <g0dil@berlios.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 FileDispatcher non-inline non-template implementation */
-
-#include "FileDispatcher.hh"
-//#include "FileDispatcher.ih"
-
-// Custom includes
-
-//#include "FileDispatcher.mpp"
-#define prefix_
-///////////////////////////////cc.p////////////////////////////////////////
-
-prefix_ senf::scheduler::FileDispatcher::FileDispatcher(FdManager & manager,
-                                                        FIFORunner & runner)
-    : manager_ (manager), runner_ (runner), managerTimeout_ (manager.timeout())
-{}
-
-prefix_ senf::scheduler::FileDispatcher::~FileDispatcher()
-{
-    manager_.timeout(-1);
-
-    for (FileMap::iterator i (files_.begin()); i != files_.end(); ++i) {
-        runner_.dequeue(static_cast<FileEvent::ReadTask*>(&i->second));
-        runner_.dequeue(static_cast<FileEvent::WriteTask*>(&i->second));
-    }
-}
-
-prefix_ void senf::scheduler::FileDispatcher::add(std::string const & name, int fd,
-                                                  Callback const & cb, int events)
-{
-    if (events == 0)
-        return;
-    
-    FileMap::iterator i (files_.find(fd));
-    if (i == files_.end()) {
-        i = files_.insert(std::make_pair(fd, FileEvent(name))).first;
-        runner_.enqueue(static_cast<FileEvent::ReadTask*>(&i->second));
-        runner_.enqueue(static_cast<FileEvent::WriteTask*>(&i->second));
-    }
-    FileEvent & event (i->second);
-
-    if (events & EV_READ)
-        event.FileEvent::ReadTask::cb = cb;
-    if (events & EV_WRITE)
-        event.FileEvent::WriteTask::cb = cb;
-    
-    manager_.timeout(0);
-}
-
-prefix_ void senf::scheduler::FileDispatcher::remove(int fd, int events)
-{
-    if (events == 0)
-        return;
-
-    FileMap::iterator i (files_.find(fd));
-    if (i == files_.end()) 
-        return;
-    FileEvent & event (i->second);
-
-    if (events & EV_READ) event.FileEvent::ReadTask::cb = 0;
-    if (events & EV_WRITE) event.FileEvent::WriteTask::cb = 0;
-
-    int activeEvents (event.activeEvents());
-    if (! activeEvents) {
-        runner_.dequeue(static_cast<FileEvent::ReadTask*>(&i->second));
-        runner_.dequeue(static_cast<FileEvent::WriteTask*>(&i->second));
-        files_.erase(fd);
-    }
-    
-    if (files_.empty())
-        manager_.timeout(managerTimeout_);
-}
-
-prefix_ void senf::scheduler::FileDispatcher::prepareRun()
-{
-    for (FileMap::iterator i (files_.begin()); i != files_.end(); ++i) {
-        i->second.events = i->second.activeEvents();
-        if (i->second.FileEvent::ReadTask::cb)
-            i->second.FileEvent::ReadTask::runnable = true;
-        if (i->second.FileEvent::WriteTask::cb)
-            i->second.FileEvent::WriteTask::runnable = true;
-    }
-}
-
-///////////////////////////////cc.e////////////////////////////////////////
-#undef prefix_
-//#include "FileDispatcher.mpp"
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
diff --git a/Scheduler/FileDispatcher.hh b/Scheduler/FileDispatcher.hh
deleted file mode 100644 (file)
index f81e3df..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2008 
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-//     Stefan Bund <g0dil@berlios.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 FileDispatcher public header */
-
-#ifndef HH_FileDispatcher_
-#define HH_FileDispatcher_ 1
-
-// Custom includes
-#include <map>
-#include "FdManager.hh"
-#include "FIFORunner.hh"
-#include "FdDispatcher.hh"
-
-//#include "FileDispatcher.mpp"
-///////////////////////////////hh.p////////////////////////////////////////
-
-namespace senf {
-namespace scheduler {
-
-    /** \brief Scheduler dispatcher managing disc files
-
-        This dispatcher manages file descriptors which are connected to disc files. Since disc files
-        do not support select() / poll() / epoll(), they are considered to be always ready (which is
-        especially untrue for remote files e.g. vie NFS).
-
-        The FileDispatcher will change the FdManager's event timeout value to 0 (from -1) whenever
-        there is at least one file registered.
-      */
-    class FileDispatcher
-    {
-    public:
-        ///////////////////////////////////////////////////////////////////////////
-        // Types
-
-        typedef boost::function<void (int)> Callback;
-
-        enum Events { 
-            EV_READ = FdManager::EV_READ, EV_WRITE = FdManager::EV_WRITE,
-            EV_HUP = FdManager::EV_HUP, EV_ERR = FdManager::EV_ERR,
-            EV_ALL = FdManager::EV_READ | FdManager::EV_WRITE
-        };
-
-        ///////////////////////////////////////////////////////////////////////////
-        ///\name Structors and default members
-        ///@{
-
-        FileDispatcher(FdManager & manager, FIFORunner & runner);
-        ~FileDispatcher();
-
-        ///@}
-        ///////////////////////////////////////////////////////////////////////////
-        
-        void add(std::string const & name, int fd, Callback const & cb, int events = EV_ALL);
-                                        ///< Add file descriptor callback
-                                        /**< There is always one active callback for each
-                                             combination of file descriptor and event. Registering a
-                                             new callback will overwrite the old callback.
-                                             \param[in] name descriptive name
-                                             \param[in] fd file descriptor
-                                             \param[in] cb callback
-                                             \param[in] events Events to call \a cb for */
-
-        void remove(int fd, int events = EV_ALL);
-                                        /**< \param[in] fd file descriptor
-                                             \param[in] events Events for which to remove the
-                                                 callback */
-
-        void prepareRun();              ///< Prepare tasks
-                                        /**< This must be called after the FdManager returns before
-                                             running the runnable tasks. */
-
-        void timeout(int t);            ///< Change FdManager timeout
-                                        /**< Since the FileDispatcher must be able to change the
-                                             timeout value, the value must be set here and not
-                                             directly in the FdManager. */
-        int timeout() const;            ///< Retrieve current timeout value
-
-        bool empty() const;             ///< \c true, if no files are registered.
-
-    protected:
-
-    private:
-        /// Internal: Disk file event
-        struct FileEvent
-            : public detail::FdTask<0, FileEvent>,
-              public detail::FdTask<1, FileEvent>
-        {
-            typedef detail::FdTask<0, FileEvent> ReadTask;
-            typedef detail::FdTask<1, FileEvent> WriteTask;
-
-            explicit FileEvent(std::string const & name)
-                : ReadTask (name), WriteTask (name) {}
-
-            int activeEvents() const;
-            int events;
-        };
-
-        typedef std::map<int, FileEvent> FileMap;
-
-        FileMap files_;
-        FdManager & manager_;
-        FIFORunner & runner_;
-        int managerTimeout_;
-    };
-
-
-}}
-
-///////////////////////////////hh.e////////////////////////////////////////
-#include "FileDispatcher.cci"
-//#include "FileDispatcher.ct"
-//#include "FileDispatcher.cti"
-#endif
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
diff --git a/Scheduler/FileDispatcher.test.cc b/Scheduler/FileDispatcher.test.cc
deleted file mode 100644 (file)
index b3c2bcd..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2008 
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-//     Stefan Bund <g0dil@berlios.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 FileDispatcher.test unit tests */
-
-//#include "FileDispatcher.test.hh"
-//#include "FileDispatcher.test.ih"
-
-// Custom includes
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include "FileDispatcher.hh"
-#include "ClockService.hh"
-
-#include "../Utils/auto_unit_test.hh"
-#include <boost/test/test_tools.hpp>
-
-#define prefix_
-///////////////////////////////cc.p////////////////////////////////////////
-
-namespace {
-
-    bool is_close(senf::ClockService::clock_type a, senf::ClockService::clock_type b)
-    {
-        return (a<b ? b-a : a-b) < senf::ClockService::milliseconds(100);
-    }
-
-    bool called (false);
-    void handler(int events)
-    {
-        called=true;
-    }
-}
-
-BOOST_AUTO_UNIT_TEST(fileDispatcher)
-{
-    senf::scheduler::FileDispatcher dispatcher (senf::scheduler::FdManager::instance(), senf::scheduler::FIFORunner::instance());
-    dispatcher.timeout(500);
-
-    // It's not necessary for the cb to be a real file .. it can be anything. The only thing is,
-    // it's always called without delay.
-    int fd (open("/dev/null", O_RDWR));
-    
-    senf::ClockService::clock_type t (senf::ClockService::now());
-    SENF_CHECK_NO_THROW( dispatcher.add("testHandler", fd, &handler, 
-                                        senf::scheduler::FileDispatcher::EV_READ) );
-    SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
-    SENF_CHECK_NO_THROW( dispatcher.prepareRun() );
-    SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
-    
-    BOOST_CHECK( called );
-    BOOST_CHECK_PREDICATE( is_close, (t)(senf::ClockService::now()) );
-
-    SENF_CHECK_NO_THROW( dispatcher.remove(fd) );
-    close(fd);
-
-    called = false;
-    t = senf::ClockService::now();
-    SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
-    SENF_CHECK_NO_THROW( dispatcher.prepareRun() );
-    SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
-
-    BOOST_CHECK( ! called );
-    BOOST_CHECK_PREDICATE( 
-        is_close, (t+senf::ClockService::milliseconds(500))(senf::ClockService::now()) );
-}
-
-///////////////////////////////cc.e////////////////////////////////////////
-#undef prefix_
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
index 3948a22..41a4c08 100644 (file)
@@ -50,7 +50,13 @@ template <class Value>
 prefix_ void senf::scheduler::Poller<Value>::remove(int fd)
 {
     if (epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, 0) == -1)
-        if (errno != ENOENT && errno != EBADF)
+        if (errno != ENOENT && errno != EBADF && errno != EPERM)
+            // Calling remove() on a file descriptor which is not registered
+            // is no error, it shall be ignored:
+            // ENOENT: Not part of the poller but a valid (open) fd
+            // EBADF: The fd has been closed already. The kernel automatically removes such fds
+            //     from epoll structures
+            // EPERM: The fd does not support epoll and thus can never have been added
             SENF_THROW_SYSTEM_EXCEPTION("epoll_ctl()");
 }
 
index 42d068a..a3947ea 100644 (file)
 template <class Handle>
 prefix_ senf::ReadHelper<Handle>::ReadHelper(Handle handle, std::string::size_type maxSize,
                                                     InternalPredicate * predicate, Callback cb)
-    : handle_(handle), maxSize_(maxSize), predicate_(predicate), callback_(cb),
-      errno_(0), complete_(false)
+    : handle_(handle), 
+      fde_("ReadHelper", boost::bind(&ReadHelper::dispatchProcess,ptr(this), handle, _1),
+           handle, senf::scheduler::FdEvent::EV_READ),
+      maxSize_(maxSize), predicate_(predicate), callback_(cb), errno_(0), complete_(false)
 {
     // Here we add a *static* member taking a *smart* pointer as first
     // argumnet instead of a simple bound-member as callback to the
     // scheduler. This ensures, that the refcount is at least 1 as
     // long as the helper is registered with the scheduler.
-    senf::Scheduler::instance()
-        .add(handle,boost::bind(&ReadHelper::dispatchProcess,ptr(this), handle, _1),
-             senf::Scheduler::EV_READ);
 }
 
 template <class Handle>
 prefix_ void senf::ReadHelper<Handle>::revoke()
 {
     ptr guard (this); // To ensure, 'this' is deleted only after this method terminates ...
-    senf::Scheduler::instance()
-        .remove(handle_,senf::Scheduler::EV_READ);
+    fde_.disable();
+    fde_.action(0); // Remove smart pointer reference to this
 }
 
 template <class Handle>
index d43afd7..0b43431 100644 (file)
@@ -136,6 +136,7 @@ namespace senf {
         void done();
 
         Handle handle_;
+        scheduler::FdEvent fde_;
         std::string::size_type maxSize_;
         boost::scoped_ptr<InternalPredicate> predicate_;
         Callback callback_;
index 1d0a107..2d13781 100644 (file)
 prefix_ void senf::Scheduler::process()
 {
     terminate_ = false;
-    while(! terminate_ && ! (fdDispatcher_.empty() &&
+    while(! terminate_ && ! (scheduler::detail::FdDispatcher::instance().empty() &&
                              scheduler::detail::TimerDispatcher::instance().empty() &&
-                             fileDispatcher_.empty())) {
+                             scheduler::detail::FileDispatcher::instance().empty())) {
         scheduler::detail::SignalDispatcher::instance().unblockSignals();
         scheduler::detail::TimerDispatcher::instance().unblockSignals();
         scheduler::FdManager::instance().processOnce();
         scheduler::detail::TimerDispatcher::instance().blockSignals();
         scheduler::detail::SignalDispatcher::instance().blockSignals();
-        fileDispatcher_.prepareRun();
+        scheduler::detail::FileDispatcher::instance().prepareRun();
         scheduler::FIFORunner::instance().run();
     }
 }
@@ -60,10 +60,10 @@ prefix_ void senf::Scheduler::restart()
 {
     scheduler::FdManager* fdm (&scheduler::FdManager::instance());
     scheduler::FIFORunner* ffr (&scheduler::FIFORunner::instance());
-    scheduler::FdDispatcher* fdd (&fdDispatcher_);
+    scheduler::detail::FdDispatcher* fdd (&scheduler::detail::FdDispatcher::instance());
     scheduler::detail::TimerDispatcher* td (&scheduler::detail::TimerDispatcher::instance());
     scheduler::detail::SignalDispatcher* sd (&scheduler::detail::SignalDispatcher::instance());
-    scheduler::FileDispatcher* fld (&fileDispatcher_);
+    scheduler::detail::FileDispatcher* fld (&scheduler::detail::FileDispatcher::instance());
     
     fld->~FileDispatcher();
     sd->~SignalDispatcher();
@@ -74,10 +74,10 @@ prefix_ void senf::Scheduler::restart()
     
     new (fdm) scheduler::FdManager();
     new (ffr) scheduler::FIFORunner();
-    new (fdd) scheduler::FdDispatcher(*fdm, *ffr);
+    new (fdd) scheduler::detail::FdDispatcher();
     new (td) scheduler::detail::TimerDispatcher();
     new (sd) scheduler::detail::SignalDispatcher();
-    new (fld) scheduler::FileDispatcher(*fdm, *ffr);
+    new (fld) scheduler::detail::FileDispatcher();
 }
 
 ///////////////////////////////////////////////////////////////////////////
index 27f463e..7fe4f53 100644 (file)
 #define prefix_ inline
 ///////////////////////////////cci.p///////////////////////////////////////
 
-// private members
-
-prefix_ void senf::Scheduler::do_add(int fd, FdCallback const & cb, int eventMask)
-{
-    do_add((boost::format("<anon fd %d>") % fd).str(), fd, cb, eventMask);
-}
-
-prefix_ void senf::Scheduler::do_add(std::string const & name, int fd, FdCallback const & cb,
-                                     int eventMask)
-{
-    if (! fdDispatcher_.add(name, fd, cb, eventMask))
-        fileDispatcher_.add(name, fd, cb, eventMask);
-}
-
-prefix_ void senf::Scheduler::do_remove(int fd, int eventMask)
-{
-    // We don't know, where the descriptor is registered. However, this is no problem since removing
-    // a non-registered fd is a no-opp
-    fdDispatcher_.remove(fd, eventMask);
-    fileDispatcher_.remove(fd, eventMask);
-}
-
 // public members
 
 prefix_ senf::Scheduler::Scheduler & senf::Scheduler::instance()
@@ -62,11 +40,6 @@ prefix_ senf::Scheduler::Scheduler & senf::Scheduler::instance()
     return instance;
 }
 
-prefix_ int senf::retrieve_filehandle(int fd)
-{
-    return fd;
-}
-
 prefix_ void senf::Scheduler::terminate()
 {
     terminate_ = true;
@@ -96,9 +69,7 @@ prefix_ unsigned senf::Scheduler::hangCount()
 }
 
 prefix_ senf::Scheduler::Scheduler()
-    : terminate_ (false), 
-      fdDispatcher_ (scheduler::FdManager::instance(), scheduler::FIFORunner::instance()),
-      fileDispatcher_ (scheduler::FdManager::instance(), scheduler::FIFORunner::instance())
+    : terminate_ (false)
 {}
 
 ///////////////////////////////cci.e///////////////////////////////////////
diff --git a/Scheduler/Scheduler.cti b/Scheduler/Scheduler.cti
deleted file mode 100644 (file)
index aff6271..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2006
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-//     Stefan Bund <g0dil@berlios.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 inline template implementation
- */
-
-//#include "Scheduler.ih"
-
-// Custom includes
-#include <boost/bind.hpp>
-
-#define prefix_ inline
-///////////////////////////////cti.p///////////////////////////////////////
-
-template <class Handle>
-prefix_ void senf::Scheduler::add(Handle const & handle, FdCallback const & cb, int eventMask)
-{
-    // retrieve_filehandle is found via ADL
-    do_add(retrieve_filehandle(handle),cb,eventMask);
-}
-
-template <class Handle>
-prefix_ void senf::Scheduler::add(std::string const & name, Handle const & handle,
-                                  FdCallback const & cb, int eventMask)
-{
-    do_add(name, retrieve_filehandle(handle),cb,eventMask);
-}
-
-template <class Handle>
-prefix_ void senf::Scheduler::remove(Handle const & handle, int eventMask)
-{
-    // retrieve_filehandle is found via ADL
-    do_remove(retrieve_filehandle(handle),eventMask);
-}
-
-///////////////////////////////cti.e///////////////////////////////////////
-#undef prefix_
-
-\f
-// 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
-// End:
index c0c02bc..7f66821 100644 (file)
 
 // Custom includes
 #include "../Utils/Logger/SenfLog.hh"
-#include "FdDispatcher.hh"
+#include "FdEvent.hh"
 #include "TimerEvent.hh"
 #include "SignalEvent.hh"
-#include "FileDispatcher.hh"
 #include "../Utils/Logger/SenfLog.hh"
 
 //#include "scheduler.mpp"
@@ -210,46 +209,6 @@ namespace senf {
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
-        ///\name File Descriptors
-        ///\{
-
-        template <class Handle>
-        void add(std::string const & name, Handle const & handle, FdCallback const & cb,
-                 int eventMask = EV_ALL);  ///< Add file handle event callback
-                                        /**< add() will add a callback to the %scheduler. The
-                                             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
-                                             registered for one of the events requested, the new
-                                             handler will replace the old one.
-                                             \param[in] name descriptive name to identify the
-                                                 callback.
-                                             \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 \ref senf::Scheduler::EventId "EventId"
-                                                 designators. */
-        template <class Handle>        
-        void add(Handle const & handle, FdCallback const & cb,
-                 int eventMask = EV_ALL); ///< Add file handle event callback
-                                        /**< \see add() */
-
-
-        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 \ref senf::Scheduler::EventId "EventId"
-                                                 designators. */
-
-        ///\}
-
         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
@@ -279,26 +238,9 @@ namespace senf {
     private:
         Scheduler();
 
-        void do_add(int fd, FdCallback const & cb, int eventMask = EV_ALL);
-        void do_add(std::string const & name, int fd, FdCallback const & cb, 
-                    int eventMask = EV_ALL);
-        void do_remove(int fd, int eventMask);
-
         bool terminate_;
-
-        scheduler::FdDispatcher fdDispatcher_;
-        scheduler::FileDispatcher fileDispatcher_;
     };
 
-    /** \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);
-
     /** \brief %scheduler specific time source for Utils/Logger framework
 
         This time source may be used to provide timing information for log messages within the
@@ -315,7 +257,7 @@ namespace senf {
 ///////////////////////////////hh.e////////////////////////////////////////
 #include "Scheduler.cci"
 //#include "Scheduler.ct"
-#include "Scheduler.cti"
+//#include "Scheduler.cti"
 #endif
 
 \f
index 9efd343..95ff5bd 100644 (file)
@@ -36,6 +36,7 @@
 #include <errno.h>
 #include <string.h>
 #include <iostream>
+#include <boost/bind.hpp>
 
 #include "Scheduler.hh"
 
@@ -239,14 +240,34 @@ BOOST_AUTO_UNIT_TEST(testScheduler)
 
     BOOST_CHECK_NO_THROW( Scheduler::instance() );
 
-    BOOST_CHECK_NO_THROW( Scheduler::instance().add(sock,boost::bind(&callback, sock, _1),
-                                                    Scheduler::EV_READ) );
-    event = Scheduler::EV_NONE;
-    BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
-    BOOST_CHECK_EQUAL( event, Scheduler::EV_READ );
-    BOOST_REQUIRE_EQUAL( size, 4 );
-    buffer[size]=0;
-    BOOST_CHECK_EQUAL( buffer, "READ" );
+    {
+        senf::scheduler::FdEvent fde1 ("testFdEvent", boost::bind(&callback, sock, _1),
+                                      sock, senf::scheduler::FdEvent::EV_READ);
+        event = Scheduler::EV_NONE;
+        BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
+        BOOST_CHECK_EQUAL( event, Scheduler::EV_READ );
+        BOOST_REQUIRE_EQUAL( size, 4 );
+        buffer[size]=0;
+        BOOST_CHECK_EQUAL( buffer, "READ" );
+
+        HandleWrapper handle(sock,"TheTag");
+        senf::scheduler::FdEvent fde2 ("testFdEvent", boost::bind(&handleCallback,handle,_1),
+                                      handle, senf::scheduler::FdEvent::EV_WRITE);
+        strcpy(buffer,"WRITE");
+        size=5;
+        event = Scheduler::EV_NONE;
+        BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
+        BOOST_CHECK_EQUAL( event, Scheduler::EV_WRITE );
+
+        SENF_CHECK_NO_THROW( fde2.disable() );
+        event = Scheduler::EV_NONE;
+        sleep(1);
+        BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
+        BOOST_CHECK_EQUAL( event, Scheduler::EventId(Scheduler::EV_READ|Scheduler::EV_HUP) );
+        BOOST_REQUIRE_EQUAL( size, 2 );
+        buffer[size]=0;
+        BOOST_CHECK_EQUAL( buffer, "OK" );
+    }
     
     {
         senf::scheduler::TimerEvent timer1 ("testTimer1", &timeout, 
@@ -276,26 +297,6 @@ BOOST_AUTO_UNIT_TEST(testScheduler)
         BOOST_CHECK_EQUAL( Scheduler::instance().hangCount(), 1u );
     }
 
-    HandleWrapper handle(sock,"TheTag");
-    BOOST_CHECK_NO_THROW( Scheduler::instance().add(handle,
-                                                    boost::bind(&handleCallback,handle,_1),
-                                                    Scheduler::EV_WRITE) );
-    strcpy(buffer,"WRITE");
-    size=5;
-    event = Scheduler::EV_NONE;
-    BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
-    BOOST_CHECK_EQUAL( event, Scheduler::EV_WRITE );
-
-    BOOST_CHECK_NO_THROW( Scheduler::instance().remove(handle,Scheduler::EV_WRITE) );
-    event = Scheduler::EV_NONE;
-    sleep(1);
-    BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
-    BOOST_CHECK_EQUAL( event, Scheduler::EventId(Scheduler::EV_READ|Scheduler::EV_HUP) );
-    BOOST_REQUIRE_EQUAL( size, 2 );
-    buffer[size]=0;
-    BOOST_CHECK_EQUAL( buffer, "OK" );
-    BOOST_CHECK_NO_THROW( Scheduler::instance().remove(handle) );
-
     {
         senf::scheduler::TimerEvent timer ("testWatchdog", &timeout,
                                            ClockService::now()+ClockService::milliseconds(400));
index f083852..46ebd22 100644 (file)
@@ -106,7 +106,7 @@ prefix_ void senf::scheduler::detail::SignalDispatcher::signal(int events)
     if (i == handlers_.end())
         return;
     i->siginfo_ = info;
-    i->runnable = true;
+    i->setRunnable();
 }
 
 prefix_ void senf::scheduler::detail::SignalDispatcher::sigHandler(int signal, ::siginfo_t * siginfo,
index 1a49800..7c3278b 100644 (file)
@@ -119,7 +119,7 @@ prefix_ void senf::scheduler::detail::TimerDispatcher::signal(int events)
     TimerSet::iterator const i_end (timers_.end());
     ClockService::clock_type now (senf::scheduler::FdManager::instance().eventTime());
     for (; i != i_end && i->timeout_ <= now ; ++i)
-        i->runnable = true;
+        i->setRunnable();
 }
 
 prefix_ void senf::scheduler::detail::TimerDispatcher::sigHandler(int signal, 
index fa01767..cbbb230 100644 (file)
@@ -49,7 +49,7 @@ namespace scheduler {
 
     /** \brief Deadline timer event
 
-        The TimerEvent class registeres a deadline timer callback which will be called when the
+        The TimerEvent class registers a deadline timer callback which will be called when the
         timer expires.
 
         Timer events are implemented using POSIX timers. Depending on kernel features, the timer
index 8bae8d1..7062de2 100644 (file)
@@ -49,10 +49,6 @@ namespace detail {
     {
         SENF_LOG_CLASS_AREA();
         
-        typedef boost::intrusive::imultiset< TimerSetBase::value_traits<TimerEvent>,
-                                             TimerSetCompare,
-                                             false > TimerSet;
-
     public:
         using singleton<TimerDispatcher>::instance;
         using singleton<TimerDispatcher>::alive;
@@ -75,6 +71,10 @@ namespace detail {
         static void sigHandler(int signal, ::siginfo_t * siginfo, void *);
         void reschedule();
 
+        typedef boost::intrusive::imultiset< TimerSetBase::value_traits<TimerEvent>,
+                                             TimerSetCompare,
+                                             false > TimerSet;
+
         TimerSet timers_;
 
         int timerPipe_[2];
index fadb65f..16f386b 100644 (file)
@@ -25,6 +25,7 @@
 
 // Custom includes
 #include <errno.h>
+#include <boost/bind.hpp>
 #include "../Utils/Exception.hh"
 #include "Scheduler.hh"
 
 template <class Handle>
 prefix_ senf::WriteHelper<Handle>::WriteHelper(Handle handle, std::string const & data,
                                                       Callback callback)
-    : handle_(handle), data_(data), callback_(callback),
-      offset_(data_.begin()), errno_(0)
-{
-    senf::Scheduler::instance()
-        .add(handle_, boost::bind(&WriteHelper::dispatchProcess, ptr(this), _1, _2),
-             senf::Scheduler::EV_WRITE);
-}
+    : handle_(handle), 
+      fde_("WriteHelper", boost::bind(&WriteHelper::dispatchProcess, ptr(this), _1, _2), 
+           handle, scheduler::FdEvent::EV_WRITE),
+      data_(data), callback_(callback), offset_(data_.begin()), errno_(0)
+{}
 
 template <class Handle>
 prefix_ std::string const & senf::WriteHelper<Handle>::data()
@@ -57,8 +56,8 @@ template <class Handle>
 prefix_ void senf::WriteHelper<Handle>::revoke()
 {
     ptr guard (this); // To ensure, 'this' is deleted only after this method terminates ...
-    senf::Scheduler::instance()
-        .remove(handle_, senf::Scheduler::EV_WRITE);
+    fde_.disable();
+    fde_.action(0); // To remove the smart pointer reference to this
 }
 
 template <class Handle>
index c0bf145..c48aed5 100644 (file)
@@ -102,6 +102,7 @@ namespace senf {
         void done();
 
         Handle handle_;
+        scheduler::FdEvent fde_;
         mutable std::string data_;
         Callback callback_;
 
index 89dbcec..b04eef7 100644 (file)
@@ -630,26 +630,19 @@ prefix_ void senf::detail::DaemonWatcher::childOk()
 // senf::detail::DaemonWatcher::Forwarder
 
 prefix_ senf::detail::DaemonWatcher::Forwarder::Forwarder(int src, Callback cb)
-    : src_(src), cb_(cb)
-{
-    Scheduler::instance().add(src_, senf::membind(&Forwarder::readData, this),
-                              Scheduler::EV_READ);
-}
+    : src_(src), cb_(cb), 
+      readevent_("DaemanWatcher::Forwarder", senf::membind(&Forwarder::readData, this),
+                 src_, scheduler::FdEvent::EV_READ)
+{}
 
 prefix_ senf::detail::DaemonWatcher::Forwarder::~Forwarder()
 {
-    if (src_ != -1)
-        Scheduler::instance().remove(src_);
-    
-    for (Targets::iterator i (targets_.begin()); i != targets_.end(); ++i)
-        if (i->offset >= buffer_.size())
-            Scheduler::instance().remove(i->fd);
+    targets_.clear_and_destroy(DestroyDelete());
 }
 
 prefix_ void senf::detail::DaemonWatcher::Forwarder::addTarget(int fd)
 {
-    Target target = { fd, 0 };
-    targets_.push_back(target);
+    targets_.push_back(*(new Target(*this, fd)));
 }
 
 prefix_ void senf::detail::DaemonWatcher::Forwarder::readData(int event)
@@ -660,17 +653,18 @@ prefix_ void senf::detail::DaemonWatcher::Forwarder::readData(int event)
     while (1) {
         n = ::read(src_,buf,1024);
         if (n<0) {
-            if (errno != EINTR) SENF_THROW_SYSTEM_EXCEPTION("::read()");
-        } else 
+            if (errno != EINTR) 
+                SENF_THROW_SYSTEM_EXCEPTION("::read()");
+        } 
+        else 
             break;
     }
 
     if (n == 0) {
-        // Hangup
-        Scheduler::instance().remove(src_);
         if (buffer_.empty())
             cb_(); 
         src_ = -1;
+        readevent_.disable();
         return;
     }
 
@@ -679,20 +673,16 @@ prefix_ void senf::detail::DaemonWatcher::Forwarder::readData(int event)
 
     for (Targets::iterator i (targets_.begin()); i != targets_.end(); ++i)
         if (i->offset >= buffer_.size())
-            Scheduler::instance().add( i->fd, 
-                                       boost::bind(&Forwarder::writeData, this, _1, i),
-                                       Scheduler::EV_WRITE );
+            i->writeevent.enable();
 
     buffer_.insert(buffer_.end(), buf, buf+n);
 }
 
-prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(int event,
-                                                               Targets::iterator target)
+prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(int event, Target * target)
 {    
     if (event != Scheduler::EV_WRITE) {
         // Broken pipe while writing data ? Not much, we can do here, we just drop the data
-        Scheduler::instance().remove(target->fd);
-        targets_.erase(target);
+        targets_.erase_and_destroy(Targets::current(*target),DestroyDelete());
         if (targets_.empty() && src_ == -1)
             cb_();
         return;
@@ -719,7 +709,7 @@ prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(int event,
         i->offset -= n;
 
     if (target->offset >= buffer_.size())
-        Scheduler::instance().remove(target->fd);
+        target->writeevent.disable();
     if (src_ == -1 && (buffer_.empty() || targets_.empty()))
         cb_();
 }
similarity index 68%
rename from Scheduler/FileDispatcher.cci
rename to Utils/Daemon/Daemon.cci
index a18ea27..36e0f2f 100644 (file)
 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 /** \file
-    \brief FileDispatcher inline non-template implementation */
+    \brief Daemon inline non-template implementation */
 
-//#include "FileDispatcher.ih"
+#include "Daemon.ih"
 
 // Custom includes
+#include <boost/bind.hpp>
 
 #define prefix_ inline
 ///////////////////////////////cci.p///////////////////////////////////////
 
-prefix_ int senf::scheduler::FileDispatcher::FileEvent::activeEvents()
-    const
-{
-    return 
-        (ReadTask::cb ? EV_READ : 0) | 
-        (WriteTask::cb ? EV_WRITE : 0);
-}
-
-prefix_ void senf::scheduler::FileDispatcher::timeout(int t)
-{
-    managerTimeout_ = t;
-    if (files_.empty())
-        manager_.timeout(managerTimeout_);
-}
-
-prefix_ int senf::scheduler::FileDispatcher::timeout()
-    const
-{
-    return managerTimeout_;
-}
-
-prefix_ bool senf::scheduler::FileDispatcher::empty()
-    const
-{
-    return files_.empty();
-}
+prefix_ senf::detail::DaemonWatcher::Forwarder::Target::Target(Forwarder & fwd, int fd_)
+    : fd (fd_), offset (0),
+      writeevent ("DaemonWatcher::Forwarder::Target",
+                  boost::bind(&Forwarder::writeData, &fwd, _1, this),
+                  fd, scheduler::FdEvent::EV_WRITE, false)
+{}
 
 ///////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
index 89e2d53..f0c45c0 100644 (file)
@@ -243,7 +243,7 @@ namespace senf {
 }
 
 ///////////////////////////////hh.e////////////////////////////////////////
-//#include "Daemon.cci"
+#include "Daemon.cci"
 //#include "Daemon.ct"
 //#include "Daemon.cti"
 #endif
index 795008a..f6ec463 100644 (file)
@@ -28,7 +28,8 @@
 
 // Custom includes
 #include <deque>
-#include <list>
+#include "../boost/intrusive/iset.hpp"
+#include "../boost/intrusive/iset_hook.hpp"
 #include <boost/utility.hpp>
 #include <boost/function.hpp>
 #include "../../Scheduler/Scheduler.hh"
@@ -63,23 +64,37 @@ namespace detail {
 
         private:
 
+            // This is awkward ... we'll need to erase an element from the target list given
+            // only the target object. This is best implement using an intrusive container.
+            // However, this makes memory-management explicit and we'll need to be careful.
             typedef std::deque<char> Buffer;
-            struct Target
+            struct TargetListTag;
+            typedef boost::intrusive::ilist_base_hook<TargetListTag> TargetListBase;
+
+            struct Target : public TargetListBase
             {
+                Target(Forwarder & fwd, int fd);
+
                 int fd;
                 Buffer::size_type offset;
+                scheduler::FdEvent writeevent;
+            };
+            typedef boost::intrusive::ilist<TargetListBase::value_traits<Target>,false> Targets;
+
+            struct DestroyDelete
+            {
+                template <class T>
+                void operator()(T * t) { delete t; }
             };
-            typedef std::list<Target> Targets;
 
             void readData(int event);
-            void writeData(int event, Targets::iterator target);
+            void writeData(int event, Target * target);
 
             Buffer buffer_;
             int src_;
-
             Targets targets_;
-
             Callback cb_;
+            scheduler::FdEvent readevent_;
         };
         
         void pipeClosed(int id);