Scheduler: begin new implementation
g0dil [Wed, 2 Jul 2008 11:10:21 +0000 (11:10 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@886 270642c3-0616-0410-b53a-bc976706d245

19 files changed:
Packets/Mainpage.dox
Scheduler/Dispatcher.cci [new file with mode: 0644]
Scheduler/FIFORunner.cc [new file with mode: 0644]
Scheduler/FIFORunner.cci [new file with mode: 0644]
Scheduler/FIFORunner.hh [new file with mode: 0644]
Scheduler/FdDispatcher.cc [new file with mode: 0644]
Scheduler/FdDispatcher.cci [new file with mode: 0644]
Scheduler/FdDispatcher.ct [new file with mode: 0644]
Scheduler/FdDispatcher.cti [new file with mode: 0644]
Scheduler/FdDispatcher.hh [new file with mode: 0644]
Scheduler/FdDispatcher.ih [new file with mode: 0644]
Scheduler/FdDispatcher.test.cc [new file with mode: 0644]
Scheduler/FdManager.cc [new file with mode: 0644]
Scheduler/FdManager.cci [new file with mode: 0644]
Scheduler/FdManager.hh [new file with mode: 0644]
Scheduler/Poller.ct [new file with mode: 0644]
Scheduler/Poller.cti [new file with mode: 0644]
Scheduler/Poller.hh [new file with mode: 0644]
Scheduler/Poller.test.cc [new file with mode: 0644]

index 9eaad45..0fae42e 100644 (file)
     The definition of senf::EthernetPacket is quite straight forward. This template works for most
     simple packet types.
 
-    \see \ref senf::PacletTypeMixin
-        \ref senf::PacketTypeBase
+    \see \ref senf::PacketTypeMixin \n
+        \ref senf::PacketTypeBase \n
         \ref senf::PacketRegistry
  */
 
diff --git a/Scheduler/Dispatcher.cci b/Scheduler/Dispatcher.cci
new file mode 100644 (file)
index 0000000..9364c47
--- /dev/null
@@ -0,0 +1,49 @@
+// $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 Dispatcher inline non-template implementation */
+
+//#include "Dispatcher.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+prefix_ senf::scheduler::Dispatcher::Dispatcher()
+    : fdDispatcher_ (fdManager_, runner_)
+{}
+
+///////////////////////////////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/FIFORunner.cc b/Scheduler/FIFORunner.cc
new file mode 100644 (file)
index 0000000..8a1293b
--- /dev/null
@@ -0,0 +1,95 @@
+// $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 FIFORunner non-inline non-template implementation */
+
+#include "FIFORunner.hh"
+//#include "FIFORunner.ih"
+
+// Custom includes
+
+//#include "FIFORunner.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+prefix_ void senf::scheduler::FIFORunner::dequeue(TaskInfo * task)
+{
+    TaskList::iterator i (TaskList::current(*task));
+    if (next_ == i)
+        ++next_;
+    tasks_.erase(i);
+}
+
+namespace {
+    struct NullTask 
+        : public senf::scheduler::FIFORunner::TaskInfo
+    {
+        void run() {};
+    };
+}
+
+prefix_ void senf::scheduler::FIFORunner::run()
+{
+    // This algorithm is carefully adjusted to make it work even when arbitrary tasks are removed
+    // from the queue
+    // - Before we begin, we add a NullTask to the queue. The only purpose of this node is, to mark
+    //   the current end of the queue. The iterator to this node becomes the end iterator of the
+    //   range to process
+    // - We update the TaskInfo and move it to the end of the queue before calling the callback so
+    //   we don't access the TaskInfo if it is removed while the callback is running
+    // - We keep the next to-be-processed node in a class variable which is checked and updated
+    //   whenever a node is removed.
+    NullTask null;
+    tasks_.push_back(null);
+    TaskList::iterator end (TaskList::current(null));
+    next_ = tasks_.begin();
+    while (next_ != end) {
+        TaskInfo & task (*next_);
+        if (task.runnable) {
+            task.runnable = false;
+            TaskList::iterator i (next_);
+            ++ next_;
+            tasks_.splice(tasks_.end(), tasks_, i);
+            task.run();
+        }
+        else
+            ++ next_;
+    }
+    tasks_.erase(end);
+    next_ = tasks_.end();
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "FIFORunner.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/FIFORunner.cci b/Scheduler/FIFORunner.cci
new file mode 100644 (file)
index 0000000..5247d5d
--- /dev/null
@@ -0,0 +1,61 @@
+// $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 FIFORunner inline non-template implementation */
+
+//#include "FIFORunner.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+prefix_ senf::scheduler::FIFORunner::TaskInfo::TaskInfo()
+    : runnable (false)
+{}
+
+prefix_ senf::scheduler::FIFORunner::TaskInfo::~TaskInfo()
+{}
+
+prefix_ senf::scheduler::FIFORunner::FIFORunner()
+    : tasks_ (), next_ (tasks_.end())
+{}
+
+prefix_ void senf::scheduler::FIFORunner::enqueue(TaskInfo * task)
+{
+    tasks_.push_back(*task);
+}
+
+///////////////////////////////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/FIFORunner.hh b/Scheduler/FIFORunner.hh
new file mode 100644 (file)
index 0000000..3ad8d7e
--- /dev/null
@@ -0,0 +1,107 @@
+// $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 FIFORunner public header */
+
+#ifndef HH_FIFORunner_
+#define HH_FIFORunner_ 1
+
+// Custom includes
+#include <boost/utility.hpp>
+#include "../boost/intrusive/ilist.hpp"
+#include "../boost/intrusive/ilist_hook.hpp"
+
+//#include "FIFORunner.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf { 
+namespace scheduler {
+
+    /** \brief
+      */
+    class FIFORunner
+        : boost::noncopyable
+    {
+    public:
+        struct TaskInfo;
+
+    private:
+        struct TaskListTag;
+        typedef boost::intrusive::ilist_base_hook<TaskListTag> TaskListBase;
+        typedef TaskListBase::value_traits<TaskInfo> TaskListType;
+        typedef boost::intrusive::ilist<TaskListType, false> TaskList;
+
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        // Types
+
+        struct TaskInfo 
+            : public TaskListBase
+        {
+            TaskInfo();
+            virtual ~TaskInfo();
+
+            bool runnable;
+            virtual void run() = 0;
+        };
+
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Structors and default members
+        ///@{
+
+        FIFORunner();
+
+        ///@}
+        ///////////////////////////////////////////////////////////////////////////
+
+        void enqueue(TaskInfo * task);
+        void dequeue(TaskInfo * task);
+        
+        void run();
+
+    protected:
+
+    private:
+        TaskList tasks_;
+        TaskList::iterator next_;
+    };
+
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "FIFORunner.cci"
+//#include "FIFORunner.ct"
+//#include "FIFORunner.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.cc b/Scheduler/FdDispatcher.cc
new file mode 100644 (file)
index 0000000..a393be5
--- /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 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_ void senf::scheduler::FdDispatcher::add(int fd, Callback const & cb, int events)
+{
+    if (events == 0)
+        return;
+    
+    FdMap::iterator i (fds_.find(fd));
+    if (i == fds_.end()) {
+        i = fds_.insert(std::make_pair(fd, FdEvent())).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;
+
+     manager_.set(fd, event.activeEvents(), &event);
+ }
+
+ 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
new file mode 100644 (file)
index 0000000..2222cee
--- /dev/null
@@ -0,0 +1,64 @@
+// $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)
+{}
+
+///////////////////////////////////////////////////////////////////////////
+// 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.ct b/Scheduler/FdDispatcher.ct
new file mode 100644 (file)
index 0000000..5451da7
--- /dev/null
@@ -0,0 +1,45 @@
+// $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 template implementation  */
+
+#include "FdDispatcher.ih"
+
+// Custom includes
+
+#define prefix_
+///////////////////////////////ct.p////////////////////////////////////////
+
+///////////////////////////////ct.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.cti b/Scheduler/FdDispatcher.cti
new file mode 100644 (file)
index 0000000..b82d411
--- /dev/null
@@ -0,0 +1,60 @@
+// $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 template implementation */
+
+#include "FdDispatcher.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////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()
+{
+    return static_cast<Self&>(*this);
+}
+
+///////////////////////////////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/FdDispatcher.hh b/Scheduler/FdDispatcher.hh
new file mode 100644 (file)
index 0000000..bb947ea
--- /dev/null
@@ -0,0 +1,114 @@
+// $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
+      */
+    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
+        ///@{
+        
+        explicit FdDispatcher(FdManager & manager, FIFORunner & runner);
+        ~FdDispatcher();
+
+        ///@}
+        ///////////////////////////////////////////////////////////////////////////
+
+        void add(int fd, Callback const & cb, int events = EV_ALL);
+        void remove(int fd, int events = EV_ALL);
+
+    protected:
+
+    private:
+        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;
+
+            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
new file mode 100644 (file)
index 0000000..81ea330
--- /dev/null
@@ -0,0 +1,61 @@
+// $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 {
+    
+    template <unsigned index, class Self>
+    struct FdTask
+        : public FIFORunner::TaskInfo
+    {
+        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/FdDispatcher.test.cc b/Scheduler/FdDispatcher.test.cc
new file mode 100644 (file)
index 0000000..62a6187
--- /dev/null
@@ -0,0 +1,246 @@
+// $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.test unit tests */
+
+//#include "FdDispatcher.test.hh"
+//#include "FdDispatcher.test.ih"
+
+// Custom includes
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <string.h>
+#include <iostream>
+
+#include "FdDispatcher.hh"
+
+#include <boost/bind.hpp>
+
+#include "../Utils/auto_unit_test.hh"
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+namespace {
+
+    char const * SOCK_PATH = "/tmp/sched_test.sock";
+
+    void error(char const * fn, char const * proc="")
+    {
+        std::cerr << "\n" << proc << fn << ": " << strerror(errno) << std::endl;
+    }
+
+    void fail(char const * fn)
+    {
+        error(fn,"server: ");
+        _exit(1);
+    }
+
+    void server()
+    {
+        int sock = socket(PF_UNIX,SOCK_STREAM,0);
+        if (sock<0) fail("socket");
+        struct sockaddr_un sun;
+        memset(&sun,0,sizeof(sun));
+        sun.sun_family = AF_UNIX;
+        strcpy(sun.sun_path,SOCK_PATH);
+        if (bind(sock,(struct sockaddr*)&sun,sizeof(sun))<0) fail("bind");
+        if (listen(sock,1)<0) fail("listen");
+        int conn = accept(sock,0,0);
+        if (conn < 0) fail("accept");
+
+        ///////////////////////////////////////////////////////////////////////////
+
+        if (write(conn,"READ",4)<0) fail("write");
+        char buffer[1024];
+        int size =  read(conn,buffer,1024);
+        if (size<0) fail("read");
+        if (size == 5) {
+            buffer[5] = 0;
+            if (strcmp(buffer,"WRITE")==0) {
+                if (write(conn,"OK",2)<0) fail("write");
+            } else
+                if (write(conn,"FAIL",4)<0) fail("write");
+        } else
+            if (write(conn,"FAIL",4)<0) fail("write");
+
+        ///////////////////////////////////////////////////////////////////////////
+
+        close(conn);
+        close(sock);
+    }
+
+    int start_server()
+    {
+        unlink(SOCK_PATH);
+        int pid = fork();
+        if (pid == 0) {
+            server();
+            _exit(0);
+        }
+        if (pid < 0) {
+            error("fork");
+            return 0;
+        }
+
+        sleep(1); // Wait for the server socket to be opened
+        return pid;
+    }
+
+    bool stop_server(int pid)
+    {
+        sleep(1); // Wait for the server to terminate
+        if (kill(pid,SIGTERM)<0) {
+            error("kill");
+            return false;
+        }
+        int status = 0;
+        if (waitpid(pid,&status,0)<0) {
+            error("waitpid");
+            return false;
+        }
+        unlink(SOCK_PATH);
+        if (WIFSIGNALED(status)) {
+            std::cerr << "\nserver terminated with signal " << WTERMSIG(status) << std::endl;
+            return false;
+        }
+        if (WEXITSTATUS(status)!=0) {
+            std::cerr << "\nserver terminated with exit status " << WEXITSTATUS(status) << std::endl;
+            return false;
+        }
+        return true;
+    }
+
+    char buffer[1024];
+    int size (0);
+    int event (0);
+    int calls (0);
+
+    void callback(int fd, int ev)
+    {
+        ++calls;
+        event = ev;
+        switch (event & senf::scheduler::FdDispatcher::EV_ALL) {
+        case senf::scheduler::FdDispatcher::EV_READ:
+            size = recv(fd,buffer,1024,0);
+            break;
+        case senf::scheduler::FdDispatcher::EV_PRIO:
+            size = recv(fd,buffer,1024,MSG_OOB);
+            break;
+        case senf::scheduler::FdDispatcher::EV_WRITE:
+            size = write(fd,buffer,size);
+            break;
+        }
+    }
+
+}
+
+BOOST_AUTO_UNIT_TEST(fdDispatcher)
+{
+    senf::scheduler::FdManager manager;
+    senf::scheduler::FIFORunner runner;
+    senf::scheduler::FdDispatcher dispatcher (manager, runner);
+
+    int pid (start_server());
+    BOOST_REQUIRE( pid );
+
+    int sock = socket(PF_UNIX,SOCK_STREAM,0);
+    if (sock<0) {
+        error("socket");
+        BOOST_FAIL("socket");
+    }
+    struct sockaddr_un sun;
+    memset(&sun,0,sizeof(sun));
+    sun.sun_family = AF_UNIX;
+    strcpy(sun.sun_path,SOCK_PATH);
+
+    if (connect(sock,(struct sockaddr*)&sun,sizeof(sun))<0) {
+        error("connect");
+        BOOST_FAIL("connect");
+    }
+
+    SENF_CHECK_NO_THROW( dispatcher.add(sock, boost::bind(&callback, sock, _1),
+                                        senf::scheduler::FdDispatcher::EV_READ) );
+    manager.timeout(1000);
+    event = 0;
+    SENF_CHECK_NO_THROW( manager.processOnce() );
+    SENF_CHECK_NO_THROW( runner.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;
+    SENF_CHECK_NO_THROW( dispatcher.add(sock, boost::bind(&callback, sock, _1),
+                                        senf::scheduler::FdDispatcher::EV_WRITE) );
+    event = 0;
+    sleep(1);
+    SENF_CHECK_NO_THROW( manager.processOnce() );
+    SENF_CHECK_NO_THROW( runner.run() );
+    BOOST_CHECK_EQUAL( event, senf::scheduler::FdDispatcher::EV_WRITE );
+
+    SENF_CHECK_NO_THROW( dispatcher.remove(sock, senf::scheduler::FdDispatcher::EV_WRITE) );
+    event = 0;
+    sleep(1);
+    SENF_CHECK_NO_THROW( manager.processOnce() );
+    SENF_CHECK_NO_THROW( runner.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_EQUAL( calls, 3 );
+    SENF_CHECK_NO_THROW( runner.run() );
+    BOOST_CHECK_EQUAL( calls, 3 );
+    
+    // Ensure, removing an already closed file-descriptor doesn't wreak havoc
+    close(sock);
+    SENF_CHECK_NO_THROW( dispatcher.remove(sock) );
+
+    SENF_CHECK_NO_THROW( runner.run() );
+    BOOST_CHECK_EQUAL( calls, 3 );
+
+
+    BOOST_CHECK (stop_server(pid));
+}
+
+///////////////////////////////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:
diff --git a/Scheduler/FdManager.cc b/Scheduler/FdManager.cc
new file mode 100644 (file)
index 0000000..323825d
--- /dev/null
@@ -0,0 +1,55 @@
+// $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 FdManager non-inline non-template implementation */
+
+#include "FdManager.hh"
+//#include "FdManager.ih"
+
+// Custom includes
+
+//#include "FdManager.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+prefix_ void senf::scheduler::FdManager::processOnce()
+{
+    Poller<Event>::range events (poller_.wait());
+    for (Poller<Event>::iterator i (events.begin()); i != events.end(); ++i)
+        i->second->signal(i->first);
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "FdManager.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/FdManager.cci b/Scheduler/FdManager.cci
new file mode 100644 (file)
index 0000000..5f7c175
--- /dev/null
@@ -0,0 +1,75 @@
+// $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 FdManager inline non-template implementation */
+
+//#include "FdManager.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::FdManager
+
+prefix_ void senf::scheduler::FdManager::set(int fd, int events, Event * entry)
+{
+    poller_.set(fd, events, entry);
+}
+
+prefix_ void senf::scheduler::FdManager::remove(int fd)
+{
+    poller_.remove(fd);
+}
+
+prefix_ void senf::scheduler::FdManager::timeout(int t)
+{
+    poller_.timeout(t);
+}
+
+prefix_ int senf::scheduler::FdManager::timeout()
+    const
+{
+    return poller_.timeout();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::FdManager::Event
+
+prefix_ senf::scheduler::FdManager::Event::~Event()
+{}
+
+///////////////////////////////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/FdManager.hh b/Scheduler/FdManager.hh
new file mode 100644 (file)
index 0000000..ecc7f98
--- /dev/null
@@ -0,0 +1,94 @@
+// $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 FdManager public header */
+
+#ifndef HH_FdManager_
+#define HH_FdManager_ 1
+
+// Custom includes
+#include "Poller.hh"
+
+//#include "FdManager.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace scheduler {
+
+    /** \brief
+      */
+    class FdManager
+    {
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        // Types
+
+        struct Event {
+            virtual ~Event();
+            virtual void signal(int events) = 0;
+        };
+
+        enum Events { 
+            EV_READ = Poller<Event>::EV_READ, EV_PRIO = Poller<Event>::EV_PRIO, EV_WRITE = Poller<Event>::EV_WRITE,
+            EV_HUP = Poller<Event>::EV_HUP, EV_ERR = Poller<Event>::EV_ERR 
+        };
+
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Structors and default members
+        ///@{
+
+        ///@}
+        ///////////////////////////////////////////////////////////////////////////
+
+        void set(int fd, int events, Event * entry);
+        void remove(int fd);
+
+        void timeout(int t);
+        int timeout() const;
+
+        void processOnce();
+
+    protected:
+
+    private:
+        Poller<Event> poller_;
+    };
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "FdManager.cci"
+//#include "FdManager.ct"
+//#include "FdManager.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/Poller.ct b/Scheduler/Poller.ct
new file mode 100644 (file)
index 0000000..d0737a8
--- /dev/null
@@ -0,0 +1,88 @@
+// $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 Poller non-inline template implementation  */
+
+//#include "Poller.ih"
+
+// Custom includes
+#include <errno.h>
+#include "../Utils/Exception.hh"
+
+#define prefix_
+///////////////////////////////ct.p////////////////////////////////////////
+
+template <class Value>
+prefix_ bool senf::scheduler::Poller<Value>::set(int fd, int events, Value * data)
+{
+    struct epoll_event ev = { events, { data } };
+    if (epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &ev) != -1) 
+        return true;
+    if (errno == EEXIST)
+        if (epoll_ctl(epollFd_, EPOLL_CTL_MOD, fd, &ev) != -1)
+            return true;
+    if (errno == EPERM)
+        return false;
+    throw SystemException("epolll_ctl");
+}
+
+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)
+            throw SystemException("epoll_ctl");
+}
+
+template <class Value>
+prefix_ typename senf::scheduler::Poller<Value>::range senf::scheduler::Poller<Value>::wait()
+{
+    static epoll_event events[NumEvents];
+    int rv (0);
+    for (;;) {
+        rv = epoll_wait(epollFd_, events, NumEvents, timeout_);
+        if (rv == -1) {
+            if (errno == EINTR)
+                continue;
+            throw SystemException("epoll_wait");
+        }
+        break;
+    }
+    return boost::make_iterator_range(
+        boost::make_transform_iterator(events, GetPollResult()),
+        boost::make_transform_iterator(events+rv, GetPollResult()) );
+}
+
+///////////////////////////////ct.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/Poller.cti b/Scheduler/Poller.cti
new file mode 100644 (file)
index 0000000..c05fe4a
--- /dev/null
@@ -0,0 +1,83 @@
+// $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 Poller inline template implementation */
+
+//#include "Poller.ih"
+
+// Custom includes
+#include <unistd.h>
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+template <class Value>
+prefix_ senf::scheduler::Poller<Value>::Poller()
+    : timeout_ (-1)
+{
+    epollFd_ = epoll_create(NumEvents);
+    if (epollFd_ == -1)
+        throw senf::SystemException("epoll_create");
+}
+
+template <class Value>
+prefix_ senf::scheduler::Poller<Value>::~Poller()
+{
+    close(epollFd_);
+}
+
+template <class Value>
+prefix_ void senf::scheduler::Poller<Value>::timeout(int t)
+{
+    timeout_ = t;
+}
+
+template <class Value>
+prefix_ int senf::scheduler::Poller<Value>::timeout()
+    const
+{
+    return timeout_;
+}
+
+template <class Value>
+prefix_ typename senf::scheduler::Poller<Value>::GetPollResult::result_type
+senf::scheduler::Poller<Value>::GetPollResult::operator()(epoll_event const & ev)
+    const
+
+{
+    return std::make_pair(ev.events, static_cast<Value*>(ev.data.ptr));
+}
+
+///////////////////////////////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/Poller.hh b/Scheduler/Poller.hh
new file mode 100644 (file)
index 0000000..0dc5504
--- /dev/null
@@ -0,0 +1,108 @@
+// $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 Poller public header */
+
+#ifndef HH_Poller_
+#define HH_Poller_ 1
+
+// Custom includes
+#include <sys/epoll.h>
+#include <boost/utility.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+#include <boost/range/iterator_range.hpp>
+
+//#include "Poller.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace scheduler {
+
+    /** \brief
+      */
+    template <class Value>
+    class Poller
+        : boost::noncopyable
+    {
+        struct GetPollResult
+        {
+            typedef std::pair<int, Value*> result_type;
+            result_type operator()(epoll_event const &) const;
+        };
+
+        static int const NumEvents = 8;
+
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        // Types
+        
+        typedef Value value_type;
+        typedef boost::transform_iterator<GetPollResult, epoll_event*> iterator;
+        typedef boost::iterator_range<iterator> range;
+
+        enum Events { 
+            EV_READ = EPOLLIN, EV_PRIO = EPOLLPRI, EV_WRITE = EPOLLOUT,
+            EV_HUP = EPOLLHUP, EV_ERR = EPOLLERR 
+};
+
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Structors and default members
+        ///@{
+
+        Poller();
+        ~Poller();
+
+        ///@}
+        ///////////////////////////////////////////////////////////////////////////
+
+        bool set(int fd, int events, Value * data);
+        void remove(int fd);
+        range wait();
+        
+        void timeout(int t);
+        int timeout() const;
+
+    private:
+        int epollFd_;
+        int timeout_;
+    };
+
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+//#include "Poller.cci"
+#include "Poller.ct"
+#include "Poller.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/Poller.test.cc b/Scheduler/Poller.test.cc
new file mode 100644 (file)
index 0000000..f36cdff
--- /dev/null
@@ -0,0 +1,53 @@
+// $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 Poller.test unit tests */
+
+//#include "Poller.test.hh"
+//#include "Poller.test.ih"
+
+// Custom includes
+#include "Poller.hh"
+
+#include "../Utils/auto_unit_test.hh"
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+BOOST_AUTO_UNIT_TEST(poller)
+{}
+
+///////////////////////////////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: