From: g0dil Date: Fri, 19 Sep 2008 10:52:03 +0000 (+0000) Subject: Scheduler: Implement new file descriptor event API X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=03516e8371a90f908ce54dedb3c874eec7dd08ff;p=senf.git Scheduler: Implement new file descriptor event API 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 --- diff --git a/Console/Readline.cc b/Console/Readline.cc index f1597d4..a02e2a8 100644 --- a/Console/Readline.cc +++ b/Console/Readline.cc @@ -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() diff --git a/Console/Readline.hh b/Console/Readline.hh index 09a9e61..69ae87d 100644 --- a/Console/Readline.hh +++ b/Console/Readline.hh @@ -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_; diff --git a/Console/Server.cc b/Console/Server.cc index 3148e76..df6c421 100644 --- a/Console/Server.cc +++ b/Console/Server.cc @@ -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)); diff --git a/Console/Server.hh b/Console/Server.hh index 66426a0..1974a74 100644 --- a/Console/Server.hh +++ b/Console/Server.hh @@ -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_; diff --git a/Console/Server.ih b/Console/Server.ih index 3ca80a1..c65a88f 100644 --- a/Console/Server.ih +++ b/Console/Server.ih @@ -173,7 +173,7 @@ namespace detail { void newData(int event); - SchedulerBinding binding_; + scheduler::FdEvent readevent_; std::string buffer_; }; diff --git a/Examples/MCSniffer/MCSniffer.cc b/Examples/MCSniffer/MCSniffer.cc index 211ebaf..0d6fb37 100644 --- a/Examples/MCSniffer/MCSniffer.cc +++ b/Examples/MCSniffer/MCSniffer.cc @@ -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: diff --git a/Examples/Sniffer/Sniffer.cc b/Examples/Sniffer/Sniffer.cc index 7f74806..48e17ed 100644 --- a/Examples/Sniffer/Sniffer.cc +++ b/Examples/Sniffer/Sniffer.cc @@ -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(); } diff --git a/Examples/TCPClientServer/server.cc b/Examples/TCPClientServer/server.cc index 4dbf274..6eab3a2 100644 --- a/Examples/TCPClientServer/server.cc +++ b/Examples/TCPClientServer/server.cc @@ -35,17 +35,19 @@ 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()); diff --git a/Examples/UDPClientServer/udpServer.cc b/Examples/UDPClientServer/udpServer.cc index d549a92..201ca3f 100644 --- a/Examples/UDPClientServer/udpServer.cc +++ b/Examples/UDPClientServer/udpServer.cc @@ -29,17 +29,18 @@ 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; } + + +// 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: diff --git a/PPI/IOEvent.cc b/PPI/IOEvent.cc index 73bcc5f..f63288d 100644 --- a/PPI/IOEvent.cc +++ b/PPI/IOEvent.cc @@ -28,7 +28,6 @@ // Custom includes #include "../Utils/senfassert.hh" -#include //#include "IOEvent.mpp" #define prefix_ @@ -42,18 +41,17 @@ 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) diff --git a/PPI/IOEvent.cti b/PPI/IOEvent.cti index 682d464..29c0fbb 100644 --- a/PPI/IOEvent.cti +++ b/PPI/IOEvent.cti @@ -26,6 +26,7 @@ //#include "IOEvent.ih" // Custom includes +#include #define prefix_ inline ///////////////////////////////cti.p/////////////////////////////////////// @@ -35,7 +36,8 @@ template 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/////////////////////////////////////// diff --git a/PPI/IOEvent.hh b/PPI/IOEvent.hh index 77c5d26..7707cfb 100644 --- a/PPI/IOEvent.hh +++ b/PPI/IOEvent.hh @@ -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 index bd8e3e9..0000000 --- a/Scheduler/Binding.cci +++ /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_ - - -// 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 index 3ae11e8..0000000 --- a/Scheduler/Binding.cti +++ /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 -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_ - - -// 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 index e8b535b..0000000 --- a/Scheduler/Binding.hh +++ /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 -#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 - 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 - - -// 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 index 662892b..0000000 --- a/Scheduler/Binding.test.cc +++ /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 - -#define prefix_ -///////////////////////////////cc.p//////////////////////////////////////// - -BOOST_AUTO_UNIT_TEST(binding) -{ -} - -///////////////////////////////cc.e//////////////////////////////////////// -#undef prefix_ - - -// 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 index 0e5d5be..35858a0 100644 --- a/Scheduler/FIFORunner.cc +++ b/Scheduler/FIFORunner.cc @@ -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_; diff --git a/Scheduler/FIFORunner.cci b/Scheduler/FIFORunner.cci index 4bea7ba..209bd99 100644 --- a/Scheduler/FIFORunner.cci +++ b/Scheduler/FIFORunner.cci @@ -34,20 +34,25 @@ #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 } diff --git a/Scheduler/FIFORunner.hh b/Scheduler/FIFORunner.hh index 2c04bc6..3887a3d 100644 --- a/Scheduler/FIFORunner.hh +++ b/Scheduler/FIFORunner.hh @@ -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 index 4d8007b..0000000 --- a/Scheduler/FdDispatcher.cc +++ /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 -// -// 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(&i->second)); - runner_.dequeue(static_cast(&i->second)); - runner_.dequeue(static_cast(&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(&i->second)); - runner_.enqueue(static_cast(&i->second)); - runner_.enqueue(static_cast(&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(&i->second)); - runner_.dequeue(static_cast(&i->second)); - runner_.dequeue(static_cast(&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(&i->second)); - runner_.dequeue(static_cast(&i->second)); - runner_.dequeue(static_cast(&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" - - -// 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 index d7c1034..0000000 --- a/Scheduler/FdDispatcher.cci +++ /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 -// -// 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_ - - -// 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 index bfca398..0000000 --- a/Scheduler/FdDispatcher.hh +++ /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 -// -// 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 -#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 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 FdMap; - - FdMap fds_; - FdManager & manager_; - FIFORunner & runner_; - }; - -}} - -///////////////////////////////hh.e//////////////////////////////////////// -#include "FdDispatcher.cci" -#include "FdDispatcher.ct" -#include "FdDispatcher.cti" -#endif - - -// 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 index b0c1c01..0000000 --- a/Scheduler/FdDispatcher.ih +++ /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 -// -// 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 - struct FdTask - : public FIFORunner::TaskInfo - { - explicit FdTask(std::string const & name) - : FIFORunner::TaskInfo (name) {} - - typedef boost::function Callback; - virtual void run(); - Self & self(); - Callback cb; - }; - -}}} - -///////////////////////////////ih.e//////////////////////////////////////// -#endif - - -// 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 index 0000000..58c3d7e --- /dev/null +++ b/Scheduler/FdEvent.cc @@ -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 +// +// 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 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 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 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" + + +// 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 index 0000000..5391f71 --- /dev/null +++ b/Scheduler/FdEvent.cci @@ -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 +// +// 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_ + + +// 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/FdEvent.ct similarity index 78% rename from Scheduler/FdDispatcher.ct rename to Scheduler/FdEvent.ct index 5451da7..c6dfbf9 100644 --- a/Scheduler/FdDispatcher.ct +++ b/Scheduler/FdEvent.ct @@ -23,13 +23,27 @@ /** \file \brief FdDispatcher non-inline template implementation */ -#include "FdDispatcher.ih" +#include "FdEvent.ih" // Custom includes #define prefix_ ///////////////////////////////ct.p//////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +// senf::scheduler::FdEvent + +template +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_ diff --git a/Scheduler/FdDispatcher.cti b/Scheduler/FdEvent.cti similarity index 76% rename from Scheduler/FdDispatcher.cti rename to Scheduler/FdEvent.cti index b82d411..f33ef1c 100644 --- a/Scheduler/FdDispatcher.cti +++ b/Scheduler/FdEvent.cti @@ -23,7 +23,7 @@ /** \file \brief FdDispatcher inline template implementation */ -#include "FdDispatcher.ih" +#include "FdEvent.ih" // Custom includes @@ -31,18 +31,17 @@ ///////////////////////////////cti.p/////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// -// senf::scheduler::detail::FdTask - -template -prefix_ void senf::scheduler::detail::FdTask::run() -{ - cb(self().events); -} - -template -prefix_ Self & senf::scheduler::detail::FdTask::self() +// senf::scheduler::FdEvent + +template +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(*this); + if (initiallyEnabled) + enable(); } ///////////////////////////////cti.e/////////////////////////////////////// diff --git a/Scheduler/FdEvent.hh b/Scheduler/FdEvent.hh new file mode 100644 index 0000000..736c3cf --- /dev/null +++ b/Scheduler/FdEvent.hh @@ -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 +// +// 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 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 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 + 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 + 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 + + +// 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 index 0000000..15d106c --- /dev/null +++ b/Scheduler/FdEvent.ih @@ -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 +// +// 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 + { + public: + using senf::singleton::instance; + using senf::singleton::alive; + + bool add(FdEvent & event); + void remove(FdEvent & event); + + bool empty() const; + + protected: + + private: + FdDispatcher(); + ~FdDispatcher(); + + typedef boost::intrusive::imultiset< FdSetBase::value_traits, + FdSetCompare, + false > FdSet; + + FdSet fds_; + + friend class senf::Scheduler; + friend class singleton; + friend class senf::scheduler::FdEvent; + }; + + class FileDispatcher + : public senf::singleton + { + public: + using senf::singleton::instance; + using senf::singleton::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, + FdSetCompare, + false > FdSet; + + FdSet fds_; + int managerTimeout_; + + friend class senf::Scheduler; + friend class singleton; + }; + +}}} + +///////////////////////////////ih.e//////////////////////////////////////// +#endif + + +// 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/FdEvent.test.cc similarity index 58% rename from Scheduler/FdDispatcher.test.cc rename to Scheduler/FdEvent.test.cc index 6e20cc8..39c0acf 100644 --- a/Scheduler/FdDispatcher.test.cc +++ b/Scheduler/FdEvent.test.cc @@ -21,13 +21,15 @@ // 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 +#include +#include #include #include #include @@ -36,7 +38,7 @@ #include #include -#include "FdDispatcher.hh" +#include "FdEvent.hh" #include @@ -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 -// -// 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(&i->second)); - runner_.dequeue(static_cast(&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(&i->second)); - runner_.enqueue(static_cast(&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(&i->second)); - runner_.dequeue(static_cast(&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" - - -// 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 index f81e3df..0000000 --- a/Scheduler/FileDispatcher.hh +++ /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 -// -// 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 -#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 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 FileMap; - - FileMap files_; - FdManager & manager_; - FIFORunner & runner_; - int managerTimeout_; - }; - - -}} - -///////////////////////////////hh.e//////////////////////////////////////// -#include "FileDispatcher.cci" -//#include "FileDispatcher.ct" -//#include "FileDispatcher.cti" -#endif - - -// 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 index b3c2bcd..0000000 --- a/Scheduler/FileDispatcher.test.cc +++ /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 -// -// 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 -#include -#include -#include -#include "FileDispatcher.hh" -#include "ClockService.hh" - -#include "../Utils/auto_unit_test.hh" -#include - -#define prefix_ -///////////////////////////////cc.p//////////////////////////////////////// - -namespace { - - bool is_close(senf::ClockService::clock_type a, senf::ClockService::clock_type b) - { - return (a prefix_ void senf::scheduler::Poller::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()"); } diff --git a/Scheduler/ReadHelper.ct b/Scheduler/ReadHelper.ct index 42d068a..a3947ea 100644 --- a/Scheduler/ReadHelper.ct +++ b/Scheduler/ReadHelper.ct @@ -35,24 +35,23 @@ template prefix_ senf::ReadHelper::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 prefix_ void senf::ReadHelper::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 diff --git a/Scheduler/ReadHelper.hh b/Scheduler/ReadHelper.hh index d43afd7..0b43431 100644 --- a/Scheduler/ReadHelper.hh +++ b/Scheduler/ReadHelper.hh @@ -136,6 +136,7 @@ namespace senf { void done(); Handle handle_; + scheduler::FdEvent fde_; std::string::size_type maxSize_; boost::scoped_ptr predicate_; Callback callback_; diff --git a/Scheduler/Scheduler.cc b/Scheduler/Scheduler.cc index 1d0a107..2d13781 100644 --- a/Scheduler/Scheduler.cc +++ b/Scheduler/Scheduler.cc @@ -43,15 +43,15 @@ 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(); } /////////////////////////////////////////////////////////////////////////// diff --git a/Scheduler/Scheduler.cci b/Scheduler/Scheduler.cci index 27f463e..7fe4f53 100644 --- a/Scheduler/Scheduler.cci +++ b/Scheduler/Scheduler.cci @@ -32,28 +32,6 @@ #define prefix_ inline ///////////////////////////////cci.p/////////////////////////////////////// -// private members - -prefix_ void senf::Scheduler::do_add(int fd, FdCallback const & cb, int eventMask) -{ - do_add((boost::format("") % 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 index aff6271..0000000 --- a/Scheduler/Scheduler.cti +++ /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 -// -// 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 - -#define prefix_ inline -///////////////////////////////cti.p/////////////////////////////////////// - -template -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 -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 -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_ - - -// 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: diff --git a/Scheduler/Scheduler.hh b/Scheduler/Scheduler.hh index c0c02bc..7f66821 100644 --- a/Scheduler/Scheduler.hh +++ b/Scheduler/Scheduler.hh @@ -29,10 +29,9 @@ // 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 - 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 - void add(Handle const & handle, FdCallback const & cb, - int eventMask = EV_ALL); ///< Add file handle event callback - /**< \see add() */ - - - template - 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 diff --git a/Scheduler/Scheduler.test.cc b/Scheduler/Scheduler.test.cc index 9efd343..95ff5bd 100644 --- a/Scheduler/Scheduler.test.cc +++ b/Scheduler/Scheduler.test.cc @@ -36,6 +36,7 @@ #include #include #include +#include #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)); diff --git a/Scheduler/SignalEvent.cc b/Scheduler/SignalEvent.cc index f083852..46ebd22 100644 --- a/Scheduler/SignalEvent.cc +++ b/Scheduler/SignalEvent.cc @@ -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, diff --git a/Scheduler/TimerEvent.cc b/Scheduler/TimerEvent.cc index 1a49800..7c3278b 100644 --- a/Scheduler/TimerEvent.cc +++ b/Scheduler/TimerEvent.cc @@ -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, diff --git a/Scheduler/TimerEvent.hh b/Scheduler/TimerEvent.hh index fa01767..cbbb230 100644 --- a/Scheduler/TimerEvent.hh +++ b/Scheduler/TimerEvent.hh @@ -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 diff --git a/Scheduler/TimerEvent.ih b/Scheduler/TimerEvent.ih index 8bae8d1..7062de2 100644 --- a/Scheduler/TimerEvent.ih +++ b/Scheduler/TimerEvent.ih @@ -49,10 +49,6 @@ namespace detail { { SENF_LOG_CLASS_AREA(); - typedef boost::intrusive::imultiset< TimerSetBase::value_traits, - TimerSetCompare, - false > TimerSet; - public: using singleton::instance; using singleton::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, + TimerSetCompare, + false > TimerSet; + TimerSet timers_; int timerPipe_[2]; diff --git a/Scheduler/WriteHelper.ct b/Scheduler/WriteHelper.ct index fadb65f..16f386b 100644 --- a/Scheduler/WriteHelper.ct +++ b/Scheduler/WriteHelper.ct @@ -25,6 +25,7 @@ // Custom includes #include +#include #include "../Utils/Exception.hh" #include "Scheduler.hh" @@ -34,13 +35,11 @@ template prefix_ senf::WriteHelper::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 prefix_ std::string const & senf::WriteHelper::data() @@ -57,8 +56,8 @@ template prefix_ void senf::WriteHelper::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 diff --git a/Scheduler/WriteHelper.hh b/Scheduler/WriteHelper.hh index c0bf145..c48aed5 100644 --- a/Scheduler/WriteHelper.hh +++ b/Scheduler/WriteHelper.hh @@ -102,6 +102,7 @@ namespace senf { void done(); Handle handle_; + scheduler::FdEvent fde_; mutable std::string data_; Callback callback_; diff --git a/Utils/Daemon/Daemon.cc b/Utils/Daemon/Daemon.cc index 89dbcec..b04eef7 100644 --- a/Utils/Daemon/Daemon.cc +++ b/Utils/Daemon/Daemon.cc @@ -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_(); } diff --git a/Scheduler/FileDispatcher.cci b/Utils/Daemon/Daemon.cci similarity index 68% rename from Scheduler/FileDispatcher.cci rename to Utils/Daemon/Daemon.cci index a18ea27..36e0f2f 100644 --- a/Scheduler/FileDispatcher.cci +++ b/Utils/Daemon/Daemon.cci @@ -21,41 +21,22 @@ // 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 #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_ diff --git a/Utils/Daemon/Daemon.hh b/Utils/Daemon/Daemon.hh index 89e2d53..f0c45c0 100644 --- a/Utils/Daemon/Daemon.hh +++ b/Utils/Daemon/Daemon.hh @@ -243,7 +243,7 @@ namespace senf { } ///////////////////////////////hh.e//////////////////////////////////////// -//#include "Daemon.cci" +#include "Daemon.cci" //#include "Daemon.ct" //#include "Daemon.cti" #endif diff --git a/Utils/Daemon/Daemon.ih b/Utils/Daemon/Daemon.ih index 795008a..f6ec463 100644 --- a/Utils/Daemon/Daemon.ih +++ b/Utils/Daemon/Daemon.ih @@ -28,7 +28,8 @@ // Custom includes #include -#include +#include "../boost/intrusive/iset.hpp" +#include "../boost/intrusive/iset_hook.hpp" #include #include #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 Buffer; - struct Target + struct TargetListTag; + typedef boost::intrusive::ilist_base_hook TargetListBase; + + struct Target : public TargetListBase { + Target(Forwarder & fwd, int fd); + int fd; Buffer::size_type offset; + scheduler::FdEvent writeevent; + }; + typedef boost::intrusive::ilist,false> Targets; + + struct DestroyDelete + { + template + void operator()(T * t) { delete t; } }; - typedef std::list 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);