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));
+ 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);
typedef detail::FdTask<2, FdEvent> WriteTask;
virtual void signal(int events);
-
int activeEvents() const;
-
int events;
};
--- /dev/null
+// $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(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())).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:
--- /dev/null
+// $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 inline non-template implementation */
+
+//#include "FileDispatcher.ih"
+
+// Custom includes
+
+#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_;
+}
+
+///////////////////////////////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:
--- /dev/null
+// $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
+ */
+ 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(int fd, Callback const & cb, int events = EV_ALL);
+ void remove(int fd, int events = EV_ALL);
+
+ void prepareRun();
+
+ void timeout(int t);
+ int timeout() const;
+
+ protected:
+
+ private:
+ struct FileEvent
+ : public detail::FdTask<0, FileEvent>,
+ public detail::FdTask<1, FileEvent>
+ {
+ typedef detail::FdTask<0, FileEvent> ReadTask;
+ typedef detail::FdTask<1, FileEvent> WriteTask;
+
+ 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:
--- /dev/null
+// $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::FdManager manager;
+ senf::scheduler::FIFORunner runner;
+ senf::scheduler::FileDispatcher dispatcher (manager, runner);
+ 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(fd, &handler, senf::scheduler::FileDispatcher::EV_READ) );
+ SENF_CHECK_NO_THROW( manager.processOnce() );
+ SENF_CHECK_NO_THROW( dispatcher.prepareRun() );
+ SENF_CHECK_NO_THROW( runner.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( manager.processOnce() );
+ SENF_CHECK_NO_THROW( dispatcher.prepareRun() );
+ SENF_CHECK_NO_THROW( runner.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: