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)
_rl_bell_preference = 0; // Set this *after* the config file has been read
- schedBinding_.enable();
+ readevent_.enable();
}
prefix_ senf::console::detail::ReadlineClientReader::~ReadlineClientReader()
#include "Server.hh"
#include "../Utils/Exception.hh"
#include "../Scheduler/Scheduler.hh"
-#include "../Scheduler/Binding.hh"
//#include "Readline.mpp"
///////////////////////////////hh.p////////////////////////////////////////
unsigned skipChars_;
char nameBuffer_[256];
char promptBuffer_[1024];
- SchedulerBinding schedBinding_;
+ scheduler::FdEvent readevent_;
bool terminate_;
char * savedLineBuffer_;
}
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)
{
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()
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),
setNoninteractive();
break;
case Server::Automatic :
- binding_.enable();
+ readevent_.enable();
timer_.enable();
break;
}
prefix_ void senf::console::Client::setInteractive()
{
- binding_.disable();
+ readevent_.disable();
timer_.disable();
mode_ = Server::Interactive;
reader_.reset(new detail::SafeReadlineClientReader (*this));
prefix_ void senf::console::Client::setNoninteractive()
{
- binding_.disable();
+ readevent_.disable();
timer_.disable();
mode_ = Server::Noninteractive;
reader_.reset(new detail::NoninteractiveClientReader(*this));
#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"
///////////////////////////////////////////////////////////////////////////
- ~Server();
-
static Server & start(senf::INet4SocketAddress const & address);
///< Start server on given IPv4 address/port
static Server & start(senf::INet6SocketAddress const & address);
void removeClient(Client & client);
ServerHandle handle_;
+ scheduler::FdEvent event_;
DirectoryNode::ptr root_;
Mode mode_;
Server & server_;
ClientHandle handle_;
- SchedulerBinding binding_;
+ scheduler::FdEvent readevent_;
scheduler::TimerEvent timer_;
CommandParser parser_;
Executor executor_;
void newData(int event);
- SchedulerBinding binding_;
+ scheduler::FdEvent readevent_;
std::string buffer_;
};
{
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:
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();
}
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();
}
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());
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();
}
}
return 0;
}
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u"
+// End:
// Custom includes
#include "../Utils/senfassert.hh"
-#include <boost/bind.hpp>
//#include "IOEvent.mpp"
#define prefix_
prefix_ void senf::ppi::IOEvent::v_enable()
{
- Scheduler::instance().add(fd_, boost::bind(&IOEvent::cb,this,_1),
- Scheduler::EventId(events_));
+ event_.enable();
}
prefix_ void senf::ppi::IOEvent::v_disable()
{
- Scheduler::instance().remove(fd_, Scheduler::EventId(events_));
+ event_.disable();
}
prefix_ void senf::ppi::IOEvent::cb(int event)
{
- if ((event & ~events_) != 0) {
+ if ((event & ~event_.events()) != 0) {
if (event & Err)
throw ErrorException();
else if (event & Hup)
//#include "IOEvent.ih"
// Custom includes
+#include <boost/bind.hpp>
#define prefix_ inline
///////////////////////////////cti.p///////////////////////////////////////
template <class Handle>
prefix_ senf::ppi::IOEvent::IOEvent(Handle handle, unsigned events)
- : fd_(retrieve_filehandle(handle)), events_(events)
+ : fd_ (retrieve_filehandle(handle)),
+ event_ ("senf::ppi::IOEvent", boost::bind(&IOEvent::cb,this,_1), fd_, events, false)
{}
///////////////////////////////cti.e///////////////////////////////////////
private:
virtual void v_enable();
- virtual void v_disable();
+ virtual void v_disable();
void cb(int event);
int fd_;
- unsigned events_;
+ scheduler::FdEvent event_;
};
+++ /dev/null
-// $Id$
-//
-// Copyright (C) 2008
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-/** \file
- \brief Binding inline non-template implementation */
-
-//#include "Binding.ih"
-
-// Custom includes
-
-#define prefix_ inline
-///////////////////////////////cci.p///////////////////////////////////////
-
-prefix_ void senf::SchedulerBinding::enable()
-{
- if (! enabled_) {
- senf::Scheduler::instance().add(fd_, cb_, eventMask_);
- enabled_ = true;
- }
-}
-
-prefix_ void senf::SchedulerBinding::disable()
-{
- if (enabled_) {
- senf::Scheduler::instance().remove(fd_);
- enabled_ = false;
- }
-}
-
-prefix_ bool senf::SchedulerBinding::enabled()
-{
- return enabled_;
-}
-
-prefix_ senf::SchedulerBinding::~SchedulerBinding()
-{
- disable();
-}
-
-///////////////////////////////cci.e///////////////////////////////////////
-#undef prefix_
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
+++ /dev/null
-// $Id$
-//
-// Copyright (C) 2008
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-/** \file
- \brief Binding inline template implementation */
-
-//#include "Binding.ih"
-
-// Custom includes
-
-#define prefix_ inline
-///////////////////////////////cti.p///////////////////////////////////////
-
-template <class Handle>
-prefix_ senf::SchedulerBinding::SchedulerBinding(Handle const & handle,
- Scheduler::FdCallback cb, int eventMask,
- bool enabled)
- : fd_ (retrieve_filehandle(handle)), cb_ (cb), eventMask_ (eventMask), enabled_ (false)
-{
- if (enabled)
- enable();
-}
-
-///////////////////////////////cti.e///////////////////////////////////////
-#undef prefix_
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
+++ /dev/null
-// $Id$
-//
-// Copyright (C) 2008
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-/** \file
- \brief Binding public header */
-
-#ifndef HH_Binding_
-#define HH_Binding_ 1
-
-// Custom includes
-#include <boost/utility.hpp>
-#include "Scheduler.hh"
-
-//#include "Binding.mpp"
-///////////////////////////////hh.p////////////////////////////////////////
-
-namespace senf {
-
- /** \brief Manage scheduler handle binding
-
- This class will manage the binding of an arbitrary handle to the scheduler: The handle will
- automatically be removed from the Scheduler when this instance is destroyed. Example using a
- SocketHandle instance for the handle:
- \code
- class Foo
- {
- public:
- Foo(SocketHandle handle) : binding_ (handle, senf::membind(&cb, this),
- senf::Scheduler::EV_READ) {}
-
- void blarf() { binding_.disable(); }
-
- private:
- void cb(Scheduler::EventId event);
-
- senf::SchedulerBinding binding_;
- };
- \endcode
-
- The handle will be registered automatically in the constructor and will be unregistered in
- the destructor. Additionally, the helper has enable() and disable() members to register or
- remove the handle to/from the Scheduler.
- */
- class SchedulerBinding
- : boost::noncopyable
- {
- public:
- template <class Handle>
- SchedulerBinding(Handle const & handle, Scheduler::FdCallback cb,
- int eventMask = Scheduler::EV_ALL, bool enabled = true);
- ///< Register handle with the Scheduler
- /**< This constructor is like calling Scheduler::add()
- unless \a enabled is \c false, in which case the handle
- is \e not initially registered (it may be registered by
- caling enable()
- \param[in] handle Handle to register
- \param[in] cb Callback
- \param[in] eventMask type of events to register for
- \param[in] enabled wether to add handle to Scheduler
- automatically */
-
- ~SchedulerBinding(); ///< Remove scheduler registration
-
- void enable(); ///< Add handle to Scheduler
- /**< Adds the handle if it is not already registered */
- void disable(); ///< Remove handle from Scheduler
- /**< Remove handle from Scheduler if registered */
-
- bool enabled(); ///< \c true, if handle is registered
-
- protected:
-
- private:
- int fd_;
- Scheduler::FdCallback cb_;
- int eventMask_;
- bool enabled_;
- };
-}
-
-///////////////////////////////hh.e////////////////////////////////////////
-#include "Binding.cci"
-//#include "Binding.ct"
-#include "Binding.cti"
-#endif
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
+++ /dev/null
-// $Id$
-//
-// Copyright (C) 2008
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-/** \file
- \brief Binding.test unit tests */
-
-//#include "Binding.test.hh"
-//#include "Binding.test.ih"
-
-// Custom includes
-#include "Binding.hh"
-
-#include "../Utils/auto_unit_test.hh"
-#include <boost/test/test_tools.hpp>
-
-#define prefix_
-///////////////////////////////cc.p////////////////////////////////////////
-
-BOOST_AUTO_UNIT_TEST(binding)
-{
-}
-
-///////////////////////////////cc.e////////////////////////////////////////
-#undef prefix_
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
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_;
#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
}
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;
};
///////////////////////////////////////////////////////////////////////////
friend class senf::Scheduler;
};
-
}}
///////////////////////////////hh.e////////////////////////////////////////
+++ /dev/null
-// $Id$
-//
-// Copyright (C) 2008
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-// Stefan Bund <g0dil@berlios.de>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-/** \file
- \brief FdDispatcher non-inline non-template implementation */
-
-#include "FdDispatcher.hh"
-#include "FdDispatcher.ih"
-
-// Custom includes
-#include "../Utils/senfassert.hh"
-
-//#include "FdDispatcher.mpp"
-#define prefix_
-///////////////////////////////cc.p////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////
-// senf::scheduler::FdDispatcher
-
-prefix_ senf::scheduler::FdDispatcher::~FdDispatcher()
-{
- for (FdMap::iterator i (fds_.begin()); i != fds_.end(); ++i) {
- manager_.remove(i->first);
- runner_.dequeue(static_cast<FdEvent::ReadTask*>(&i->second));
- runner_.dequeue(static_cast<FdEvent::PrioTask*>(&i->second));
- runner_.dequeue(static_cast<FdEvent::WriteTask*>(&i->second));
- }
-}
-
-prefix_ bool senf::scheduler::FdDispatcher::add(std::string const & name, int fd,
- Callback const & cb, int events)
-{
- if (events == 0)
- return true;
-
- FdMap::iterator i (fds_.find(fd));
- if (i == fds_.end()) {
- i = fds_.insert(std::make_pair(fd, FdEvent(name))).first;
- runner_.enqueue(static_cast<FdEvent::ReadTask*>(&i->second));
- runner_.enqueue(static_cast<FdEvent::PrioTask*>(&i->second));
- runner_.enqueue(static_cast<FdEvent::WriteTask*>(&i->second));
- }
- FdEvent & event (i->second);
-
- if (events & EV_READ)
- event.FdEvent::ReadTask::cb = cb;
- if (events & EV_PRIO)
- event.FdEvent::PrioTask::cb = cb;
- if (events & EV_WRITE)
- event.FdEvent::WriteTask::cb = cb;
-
- if (! manager_.set(fd, event.activeEvents(), &event)) {
- runner_.dequeue(static_cast<FdEvent::ReadTask*>(&i->second));
- runner_.dequeue(static_cast<FdEvent::PrioTask*>(&i->second));
- runner_.dequeue(static_cast<FdEvent::WriteTask*>(&i->second));
- fds_.erase(i);
- return false;
- }
- else
- return true;
-}
-
-prefix_ void senf::scheduler::FdDispatcher::remove(int fd, int events)
-{
- if (events == 0)
- return;
-
- FdMap::iterator i (fds_.find(fd));
- if (i == fds_.end())
- return;
- FdEvent & event (i->second);
-
- if (events & EV_READ)
- event.FdEvent::ReadTask::cb = 0;
- if (events & EV_PRIO)
- event.FdEvent::PrioTask::cb = 0;
- if (events & EV_WRITE)
- event.FdEvent::WriteTask::cb = 0;
-
- int activeEvents (event.activeEvents());
- if (! activeEvents) {
- manager_.remove(fd);
- runner_.dequeue(static_cast<FdEvent::ReadTask*>(&i->second));
- runner_.dequeue(static_cast<FdEvent::PrioTask*>(&i->second));
- runner_.dequeue(static_cast<FdEvent::WriteTask*>(&i->second));
- fds_.erase(fd);
- } else
- manager_.set(fd, activeEvents, &event);
-}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::scheduler::FdDispatcher::FdEvent
-
-prefix_ void senf::scheduler::FdDispatcher::FdEvent::signal(int e)
-{
- events = e;
-
- if (events & EV_READ)
- ReadTask::runnable = true;
- if (events & EV_PRIO)
- PrioTask::runnable = true;
- if (events & EV_WRITE)
- WriteTask::runnable = true;
-
- if ((events & (EV_ERR | EV_HUP)) && ! (events & (EV_READ | EV_PRIO | EV_WRITE))) {
- if (ReadTask::cb) ReadTask::runnable = true;
- if (PrioTask::cb) PrioTask::runnable = true;
- if (WriteTask::cb) WriteTask::runnable = true;
- }
-}
-
-///////////////////////////////cc.e////////////////////////////////////////
-#undef prefix_
-//#include "FdDispatcher.mpp"
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
+++ /dev/null
-// $Id$
-//
-// Copyright (C) 2008
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-// Stefan Bund <g0dil@berlios.de>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-/** \file
- \brief FdDispatcher inline non-template implementation */
-
-#include "FdDispatcher.ih"
-
-// Custom includes
-
-#define prefix_ inline
-///////////////////////////////cci.p///////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////
-// senf::scheduler::FdDispatcher
-
-prefix_ senf::scheduler::FdDispatcher::FdDispatcher(FdManager & manager, FIFORunner & runner)
- : manager_ (manager), runner_ (runner)
-{}
-
-prefix_ bool senf::scheduler::FdDispatcher::empty()
- const
-{
- return fds_.empty();
-}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::scheduler::FdDispatcher::FdEvent
-
-prefix_ int senf::scheduler::FdDispatcher::FdEvent::activeEvents()
- const
-{
- return
- (ReadTask::cb ? EV_READ : 0) |
- (PrioTask::cb ? EV_PRIO : 0) |
- (WriteTask::cb ? EV_WRITE : 0);
-}
-
-///////////////////////////////cci.e///////////////////////////////////////
-#undef prefix_
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
+++ /dev/null
-// $Id$
-//
-// Copyright (C) 2008
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-// Stefan Bund <g0dil@berlios.de>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-/** \file
- \brief FdDispatcher public header */
-
-#ifndef HH_FdDispatcher_
-#define HH_FdDispatcher_ 1
-
-// Custom includes
-#include <map>
-#include "FdManager.hh"
-#include "FIFORunner.hh"
-
-//#include "FdDispatcher.mpp"
-#include "FdDispatcher.ih"
-///////////////////////////////hh.p////////////////////////////////////////
-
-namespace senf {
-namespace scheduler {
-
- /** \brief Scheduler dispatcher managing poll-able file descriptors
-
- File descriptors are added directly to the event loop.
- */
- class FdDispatcher
- {
- public:
- ///////////////////////////////////////////////////////////////////////////
- // Types
-
- typedef boost::function<void (int)> Callback;
-
- enum Events {
- EV_READ = FdManager::EV_READ, EV_PRIO = FdManager::EV_PRIO, EV_WRITE = FdManager::EV_WRITE,
- EV_HUP = FdManager::EV_HUP, EV_ERR = FdManager::EV_ERR,
- EV_ALL = FdManager::EV_READ | FdManager::EV_WRITE | FdManager::EV_PRIO
- };
-
- ///////////////////////////////////////////////////////////////////////////
- ///\name Structors and default members
- ///@{
-
- FdDispatcher(FdManager & manager, FIFORunner & runner);
- ~FdDispatcher();
-
- ///@}
- ///////////////////////////////////////////////////////////////////////////
-
- bool add(std::string const & name, int fd, Callback const & cb, int events = EV_ALL);
- ///< Add file descriptor callback
- /**< There is always one active callback for each
- combination of file descriptor and event. Registering a
- new callback will overwrite the old callback.
- \param[in] name descriptive name
- \param[in] fd file descriptor
- \param[in] cb callback
- \param[in] events Events to call \a cb for */
-
- void remove(int fd, int events = EV_ALL); ///< Remove callback
- /**< \param[in] fd file descriptor
- \param[in] events Events for which to remove the
- callback */
-
- bool empty() const; ///< \c true, if no file descriptors are registered.
-
- protected:
-
- private:
- /// Internal: File descriptor event
- struct FdEvent
- : public detail::FdTask<0, FdEvent>,
- public detail::FdTask<1, FdEvent>,
- public detail::FdTask<2, FdEvent>,
- public FdManager::Event
- {
- typedef detail::FdTask<0, FdEvent> ReadTask;
- typedef detail::FdTask<1, FdEvent> PrioTask;
- typedef detail::FdTask<2, FdEvent> WriteTask;
-
- explicit FdEvent(std::string const & name)
- : ReadTask (name), PrioTask (name), WriteTask (name) {}
-
- virtual void signal(int events);
- int activeEvents() const;
- int events;
- };
-
- typedef std::map<int, FdEvent> FdMap;
-
- FdMap fds_;
- FdManager & manager_;
- FIFORunner & runner_;
- };
-
-}}
-
-///////////////////////////////hh.e////////////////////////////////////////
-#include "FdDispatcher.cci"
-#include "FdDispatcher.ct"
-#include "FdDispatcher.cti"
-#endif
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
+++ /dev/null
-// $Id$
-//
-// Copyright (C) 2008
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-// Stefan Bund <g0dil@berlios.de>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-/** \file
- \brief FdDispatcher internal header */
-
-#ifndef IH_FdDispatcher_
-#define IH_FdDispatcher_ 1
-
-// Custom includes
-
-///////////////////////////////ih.p////////////////////////////////////////
-
-namespace senf {
-namespace scheduler {
-namespace detail {
-
- /** \brief Internal: File descriptor task
-
- \implementation This class allows to inherit FIFORunner::TaskInfo multiple times to add
- multiple tasks to one event and still allows efficient access to the event class
- */
- template <unsigned index, class Self>
- struct FdTask
- : public FIFORunner::TaskInfo
- {
- explicit FdTask(std::string const & name)
- : FIFORunner::TaskInfo (name) {}
-
- typedef boost::function<void (int)> Callback;
- virtual void run();
- Self & self();
- Callback cb;
- };
-
-}}}
-
-///////////////////////////////ih.e////////////////////////////////////////
-#endif
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief FdDispatcher non-inline non-template implementation */
+
+#include "FdEvent.hh"
+#include "FdEvent.ih"
+
+// Custom includes
+#include "../Utils/senfassert.hh"
+
+//#include "FdEvent.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::detail::FdDispatcher
+
+prefix_ senf::scheduler::detail::FdDispatcher::~FdDispatcher()
+{
+ for (FdSet::iterator i (fds_.begin()); i != fds_.end(); ++i) {
+ FdManager::instance().remove(i->fd_);
+ FIFORunner::instance().dequeue(&(*i));
+ }
+}
+
+prefix_ bool senf::scheduler::detail::FdDispatcher::add(FdEvent & event)
+{
+ std::pair<FdSet::iterator,FdSet::iterator> range (fds_.equal_range(event));
+ int events (0);
+ for (FdSet::iterator i (range.first); i != range.second; ++i)
+ events |= i->events_;
+ if (event.events_ & events)
+ throw FdEvent::DuplicateEventRegistrationException();
+
+ if (! FdManager::instance().set(event.fd_, events | event.events_, &event))
+ return false;
+
+ FIFORunner::instance().enqueue(&event);
+ fds_.insert(range.first, event);
+
+ return true;
+}
+
+prefix_ void senf::scheduler::detail::FdDispatcher::remove(FdEvent & event)
+{
+ fds_.erase(FdSet::current(event));
+ FIFORunner::instance().dequeue(&event);
+
+ std::pair<FdSet::iterator,FdSet::iterator> range (fds_.equal_range(event));
+ if (range.first == range.second)
+ FdManager::instance().remove(event.fd_);
+ else {
+ int events (0);
+ for (FdSet::iterator i (range.first); i != range.second; ++i)
+ events |= i->events_;
+ FdManager::instance().set(event.fd_, events, &(*range.first));
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::detail::FileDispatcher
+
+prefix_ void senf::scheduler::detail::FileDispatcher::add(FdEvent & event)
+{
+ std::pair<FdSet::iterator,FdSet::iterator> range (fds_.equal_range(event));
+ int events (0);
+ for (FdSet::iterator i (range.first); i != range.second; ++i)
+ events |= i->events_;
+ if (event.events_ & events)
+ throw FdEvent::DuplicateEventRegistrationException();
+
+ FIFORunner::instance().enqueue(&event);
+ fds_.insert(range.first, event);
+
+ FdManager::instance().timeout(0);
+}
+
+prefix_ senf::scheduler::detail::FileDispatcher::FileDispatcher()
+ : managerTimeout_ (scheduler::FdManager::instance().timeout())
+{}
+
+prefix_ senf::scheduler::detail::FileDispatcher::~FileDispatcher()
+{
+ FdManager::instance().timeout(-1);
+ for (FdSet::iterator i (fds_.begin()); i != fds_.end(); ++i)
+ FIFORunner::instance().dequeue(&(*i));
+}
+
+prefix_ void senf::scheduler::detail::FileDispatcher::prepareRun()
+{
+ for (FdSet::iterator i (fds_.begin()); i != fds_.end(); ++i) {
+ i->signaledEvents_ = i->events_;
+ i->setRunnable();
+ }
+}
+
+prefix_ void senf::scheduler::detail::FileDispatcher::remove(FdEvent & event)
+{
+ fds_.erase(FdSet::current(event));
+ FIFORunner::instance().dequeue(&event);
+ if (fds_.empty())
+ FdManager::instance().timeout(managerTimeout_);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::FdEvent
+
+prefix_ void senf::scheduler::FdEvent::disable()
+{
+ if (enabled()) {
+ if (pollable_)
+ detail::FdDispatcher::instance().remove(*this);
+ else
+ detail::FileDispatcher::instance().remove(*this);
+ }
+}
+
+prefix_ void senf::scheduler::FdEvent::enable()
+{
+ if (! enabled() && events_ && fd_ != -1) {
+ if (pollable_ && detail::FdDispatcher::instance().add(*this))
+ return;
+ detail::FileDispatcher::instance().add(*this);
+ pollable_ = false;
+ }
+}
+
+prefix_ senf::scheduler::FdEvent & senf::scheduler::FdEvent::events(int events)
+{
+ bool en = enabled();
+ disable();
+ events_ = events;
+ if (en)
+ enabled();
+ return *this;
+}
+
+prefix_ void senf::scheduler::FdEvent::signal(int events)
+{
+ detail::FdDispatcher::FdSet::iterator i (detail::FdDispatcher::FdSet::current(*this));
+ detail::FdDispatcher::FdSet::iterator const i_end (detail::FdDispatcher::instance().fds_.end());
+ bool all ((events & (EV_ERR | EV_HUP)) && ! (events & (EV_READ | EV_PRIO | EV_WRITE)));
+ for (; i != i_end && fd_ == i->fd_; ++i) {
+ i->signaledEvents_ = events;
+ if (i->events_ & events || all)
+ i->setRunnable();
+ }
+}
+
+prefix_ void senf::scheduler::FdEvent::run()
+{
+ cb_(signaledEvents_);
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "FdEvent.mpp"
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief FdDispatcher inline non-template implementation */
+
+#include "FdEvent.ih"
+
+// Custom includes
+#include "../Utils/senfassert.hh"
+#include "FdManager.hh"
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::FdEvent
+
+prefix_ senf::scheduler::FdEvent::FdEvent(std::string const & name, Callback const & cb)
+ : FIFORunner::TaskInfo (name), cb_ (cb), fd_ (-1), pollable_ (true), events_ (0)
+{}
+
+prefix_ senf::scheduler::FdEvent::~FdEvent()
+{
+ if (detail::FdDispatcher::alive())
+ disable();
+}
+
+prefix_ bool senf::scheduler::FdEvent::enabled()
+{
+ return detail::FdSetBase::linked();
+}
+
+prefix_ senf::scheduler::FdEvent & senf::scheduler::FdEvent::action(Callback const & cb)
+{
+ cb_ = cb;
+ return *this;
+}
+
+prefix_ senf::scheduler::FdEvent & senf::scheduler::FdEvent::addEvents(int e)
+{
+ events( events() | e );
+ return *this;
+}
+
+prefix_ senf::scheduler::FdEvent & senf::scheduler::FdEvent::removeEvents(int e)
+{
+ events( events() & ~e );
+ return *this;
+}
+
+prefix_ int senf::scheduler::FdEvent::events()
+{
+ return events_;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::detail::FdDispatcher
+
+prefix_ senf::scheduler::detail::FdDispatcher::FdDispatcher()
+{}
+
+prefix_ bool senf::scheduler::detail::FdDispatcher::empty()
+ const
+{
+ return fds_.empty();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::detail::FileDispatcher
+
+prefix_ void senf::scheduler::detail::FileDispatcher::timeout(int t)
+{
+ managerTimeout_ = t;
+ if (fds_.empty())
+ FdManager::instance().timeout(managerTimeout_);
+}
+
+prefix_ int senf::scheduler::detail::FileDispatcher::timeout()
+ const
+{
+ return managerTimeout_;
+}
+
+prefix_ bool senf::scheduler::detail::FileDispatcher::empty()
+ const
+{
+ return fds_.empty();
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+prefix_ int senf::scheduler::retrieve_filehandle(int fd)
+{
+ return fd;
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
/** \file
\brief FdDispatcher non-inline template implementation */
-#include "FdDispatcher.ih"
+#include "FdEvent.ih"
// Custom includes
#define prefix_
///////////////////////////////ct.p////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::FdEvent
+
+template <class Handle>
+prefix_ senf::scheduler::FdEvent & senf::scheduler::FdEvent::handle(Handle const & handle)
+{
+ bool en (enabled());
+ fd_ = retrieve_filehandle(handle);
+ pollable_ = true;
+ if (en)
+ enable();
+ return *this;
+}
+
///////////////////////////////ct.e////////////////////////////////////////
#undef prefix_
/** \file
\brief FdDispatcher inline template implementation */
-#include "FdDispatcher.ih"
+#include "FdEvent.ih"
// Custom includes
///////////////////////////////cti.p///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-// senf::scheduler::detail::FdTask<index,Self>
-
-template <unsigned index, class Self>
-prefix_ void senf::scheduler::detail::FdTask<index,Self>::run()
-{
- cb(self().events);
-}
-
-template <unsigned index, class Self>
-prefix_ Self & senf::scheduler::detail::FdTask<index,Self>::self()
+// senf::scheduler::FdEvent
+
+template <class Handle>
+prefix_ senf::scheduler::FdEvent::FdEvent(std::string const & name, Callback const & cb,
+ Handle const & handle, int events,
+ bool initiallyEnabled)
+ : FIFORunner::TaskInfo (name), cb_ (cb), fd_ (retrieve_filehandle(handle)), pollable_ (true),
+ events_ (events)
{
- return static_cast<Self&>(*this);
+ if (initiallyEnabled)
+ enable();
}
///////////////////////////////cti.e///////////////////////////////////////
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief FdDispatcher public header */
+
+#ifndef HH_FdDispatcher_
+#define HH_FdDispatcher_ 1
+
+// Custom includes
+#include "../boost/intrusive/iset_hook.hpp"
+#include "../Utils/Exception.hh"
+#include "FdManager.hh"
+#include "FIFORunner.hh"
+
+//#include "FdEvent.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace scheduler {
+
+ namespace detail {
+ struct FdSetTag;
+ typedef boost::intrusive::iset_base_hook<FdSetTag> FdSetBase;
+ struct FdSetCompare;
+ struct FindFd;
+ class FdDispatcher;
+ class FileDispatcher;
+ }
+
+ /** \brief File descriptor event
+
+ The FdEvent class registers a file descriptor for read or write events.
+
+ The type of event is specified using an event mask. Possible events are
+
+ \li \c EV_READ: File descriptor is readable (or at EOF)
+ \li \c EV_PRIO: There is out-of-band data available to be read on the file descriptor
+ \li \c EV_WRITE: File descriptor is writable
+
+ These event flags can be or-ed together to form an event mask. The callback will be called
+ with those flags set which are currently signaled. There are additional flags which may be
+ set when calling the callback:
+
+ \li \c EV_HUP: The other end has closed the connection
+ \li \c EV_ERR: Transport error
+
+ The file descriptor is specified using an arbitrary handle type which supports the \c
+ retrieve_filehandle() protocol: There must be a global function \c retrieve_filehandle
+ callable with the handle type. This function must return the file descriptor associated with
+ the handle. Implementations for integer numbers (explicit file descriptors) and senf socket
+ handles are provided.
+
+ The FdEvent class is an implementation of the RAII idiom: The event will be automatically
+ unregistered in the FdEvent destructor. The TimerEvent instance should be created
+ within the same scope or on a scope below where the callback is defined (e.g. if the
+ callback is a member function it should be defined as a class member).
+ */
+ class FdEvent
+ : public FIFORunner::TaskInfo,
+ public detail::FdSetBase,
+ public FdManager::Event
+ {
+ public:
+ ///////////////////////////////////////////////////////////////////////////
+ // Types
+
+ typedef boost::function<void (int)> Callback;
+
+ enum Events {
+ EV_READ = FdManager::EV_READ, EV_PRIO = FdManager::EV_PRIO, EV_WRITE = FdManager::EV_WRITE,
+ EV_HUP = FdManager::EV_HUP, EV_ERR = FdManager::EV_ERR,
+ EV_ALL = FdManager::EV_READ | FdManager::EV_WRITE | FdManager::EV_PRIO
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ ///\name Structors and default members
+ ///@{
+
+ template <class Handle>
+ FdEvent(std::string const & name, Callback const & cb, Handle const & handle, int events,
+ bool initiallyEnabled = true);
+ ///< Register a file descriptor event
+ /**< Registers \a cb to be called when any of the \a events
+ occurs on \a handle. If \a initiallyEnabled is set \c
+ false, the callback will not be enabled
+ automatically. Use enable() to do so.
+ \param[in] name Descriptive event name (purely
+ informational)
+ \param[in] cb Callback to call
+ \param[in] handle Handle (file descriptor) to watch
+ \param[in] events Events to watch for (see Events enum)
+ \param[in] initiallyEnabled if set \c false, do not
+ enable callback automatically. */
+ FdEvent(std::string const & name, Callback const & cb);
+ ///< Create a file descriptor event
+ /**< Creates a file descriptor event for callback \a cb. The
+ event is initially disabled. Use the other members to
+ set the missing parameters and enable the event.
+ \param[in] name Descriptive event name (purely
+ informational)
+ \param[in] cb Callback to call. This callback may \e
+ explicitly be set to \c 0 if the value cannot be
+ initialized. */
+ ~FdEvent();
+
+ ///@}
+ ///////////////////////////////////////////////////////////////////////////
+
+ void disable(); ///< Disable event
+ void enable(); ///< Enable event
+ bool enabled(); ///< \c true if event enabled, \c false otherwise
+
+ FdEvent & action(Callback const & cb); ///< Change event callback
+
+ FdEvent & events(int events); ///< Change event mask
+ FdEvent & addEvents(int events); ///< Add additional events to event mask
+ FdEvent & removeEvents(int events); ///< Remove events from event mask
+ int events(); ///< Current event mask
+
+ template <class Handle>
+ FdEvent & handle(Handle const & handle); ///< Change event file handle
+
+ struct DuplicateEventRegistrationException : public Exception
+ { DuplicateEventRegistrationException() : Exception("duplicate fd event registration") {} };
+
+ protected:
+
+ private:
+ virtual void signal(int events);
+ virtual void run();
+
+ Callback cb_;
+ int fd_;
+ bool pollable_;
+ int events_;
+ int signaledEvents_;
+
+ friend class detail::FdSetCompare;
+ friend class detail::FindFd;
+ friend class detail::FdDispatcher;
+ friend class detail::FileDispatcher;
+ };
+
+ int retrieve_filehandle(int fd);
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "FdEvent.cci"
+#include "FdEvent.ct"
+#include "FdEvent.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief FdDispatcher internal header */
+
+#ifndef IH_FdDispatcher_
+#define IH_FdDispatcher_ 1
+
+// Custom includes
+#include "../boost/intrusive/iset.hpp"
+
+///////////////////////////////ih.p////////////////////////////////////////
+
+namespace senf {
+
+ class Scheduler;
+
+namespace scheduler {
+namespace detail {
+
+ struct FdSetCompare {
+ bool operator()(FdEvent const & a, FdEvent const & b) const
+ { return a.fd_ < b.fd_; }
+ };
+
+ struct FindFd {
+ bool operator()(FdEvent const & a, int b) const
+ { return a.fd_ < b; }
+ bool operator()(int a, FdEvent const & b) const
+ { return a < b.fd_; }
+ };
+
+ class FdDispatcher
+ : public senf::singleton<FdDispatcher>
+ {
+ public:
+ using senf::singleton<FdDispatcher>::instance;
+ using senf::singleton<FdDispatcher>::alive;
+
+ bool add(FdEvent & event);
+ void remove(FdEvent & event);
+
+ bool empty() const;
+
+ protected:
+
+ private:
+ FdDispatcher();
+ ~FdDispatcher();
+
+ typedef boost::intrusive::imultiset< FdSetBase::value_traits<FdEvent>,
+ FdSetCompare,
+ false > FdSet;
+
+ FdSet fds_;
+
+ friend class senf::Scheduler;
+ friend class singleton<FdDispatcher>;
+ friend class senf::scheduler::FdEvent;
+ };
+
+ class FileDispatcher
+ : public senf::singleton<FileDispatcher>
+ {
+ public:
+ using senf::singleton<FileDispatcher>::instance;
+ using senf::singleton<FileDispatcher>::alive;
+
+ void add(FdEvent & event);
+ void remove(FdEvent & event);
+
+ void prepareRun();
+
+ void timeout(int t);
+ int timeout() const;
+
+ bool empty() const;
+
+ protected:
+
+ private:
+ FileDispatcher();
+ ~FileDispatcher();
+
+ // We really only need a list here but we need to use the same event structure used by
+ // the FdEvent.
+ typedef boost::intrusive::imultiset< FdSetBase::value_traits<FdEvent>,
+ FdSetCompare,
+ false > FdSet;
+
+ FdSet fds_;
+ int managerTimeout_;
+
+ friend class senf::Scheduler;
+ friend class singleton<FileDispatcher>;
+ };
+
+}}}
+
+///////////////////////////////ih.e////////////////////////////////////////
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
- \brief FdDispatcher.test unit tests */
+ \brief FdEvent.test unit tests */
-//#include "FdDispatcher.test.hh"
-//#include "FdDispatcher.test.ih"
+//#include "FdEvent.test.hh"
+//#include "FdEvent.test.ih"
// Custom includes
#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/socket.h>
#include <string.h>
#include <iostream>
-#include "FdDispatcher.hh"
+#include "FdEvent.hh"
#include <boost/bind.hpp>
{
++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;
}
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());
error("connect");
BOOST_FAIL("connect");
}
+
+ {
+ senf::scheduler::FdEvent sockread ("testHandler", boost::bind(&callback, sock, _1),
+ sock, senf::scheduler::FdEvent::EV_READ);
+ senf::scheduler::FdEvent sockwrite ("testHandler", boost::bind(&callback, sock, _1),
+ sock, senf::scheduler::FdEvent::EV_WRITE, false);
+ event = 0;
+ SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
+ SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+ BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_READ );
+ BOOST_CHECK_EQUAL( size, 4 );
+ buffer[size] = 0;
+ BOOST_CHECK_EQUAL( buffer, "READ" );
+
+ strcpy(buffer,"WRITE");
+ size=5;
+ SENF_CHECK_NO_THROW( sockwrite.enable() );
+ event = 0;
+ sleep(1);
+ SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
+ SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+ BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_WRITE );
+
+ SENF_CHECK_NO_THROW( sockwrite.disable() );
+ event = 0;
+ sleep(1);
+ SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
+ SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+ BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_HUP | senf::scheduler::FdEvent::EV_READ );
+ BOOST_CHECK_EQUAL( size, 2 );
+ buffer[size]=0;
+ BOOST_CHECK_EQUAL( buffer, "OK" );
+
+ BOOST_CHECK_EQUAL( calls, 3 );
+ SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+ BOOST_CHECK_EQUAL( calls, 3 );
+
+ // Ensure, removing an already closed file-descriptor doesn't wreak havoc
+ close(sock);
+ }
- BOOST_CHECK( dispatcher.add("testHandler", sock, boost::bind(&callback, sock, _1),
- senf::scheduler::FdDispatcher::EV_READ) );
- event = 0;
- SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
- SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
- BOOST_CHECK_EQUAL( event, senf::scheduler::FdDispatcher::EV_READ );
- BOOST_CHECK_EQUAL( size, 4 );
- buffer[size] = 0;
- BOOST_CHECK_EQUAL( buffer, "READ" );
-
- strcpy(buffer,"WRITE");
- size=5;
- BOOST_CHECK( dispatcher.add("testHandler", sock, boost::bind(&callback, sock, _1),
- senf::scheduler::FdDispatcher::EV_WRITE) );
- event = 0;
- sleep(1);
- SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
- BOOST_CHECK_EQUAL( event, senf::scheduler::FdDispatcher::EV_WRITE );
+ BOOST_CHECK_EQUAL( calls, 3 );
- SENF_CHECK_NO_THROW( dispatcher.remove(sock, senf::scheduler::FdDispatcher::EV_WRITE) );
- event = 0;
- sleep(1);
- SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
- SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
- BOOST_CHECK_EQUAL( event, senf::scheduler::FdDispatcher::EV_HUP | senf::scheduler::FdDispatcher::EV_READ );
- BOOST_CHECK_EQUAL( size, 2 );
- buffer[size]=0;
- BOOST_CHECK_EQUAL( buffer, "OK" );
+ BOOST_CHECK (stop_server(pid));
+}
- BOOST_CHECK_EQUAL( calls, 3 );
- SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
- BOOST_CHECK_EQUAL( calls, 3 );
+namespace {
+
+ bool is_close(senf::ClockService::clock_type a, senf::ClockService::clock_type b)
+ {
+ return (a<b ? b-a : a-b) < senf::ClockService::milliseconds(100);
+ }
+
+ bool called (false);
+ void handler(int events)
+ {
+ called=true;
+ }
+}
+
+BOOST_AUTO_UNIT_TEST(fileDispatcher)
+{
+ senf::scheduler::detail::FileDispatcher::instance().timeout(500);
+
+ int fd (open("test.empty.file", O_RDWR|O_CREAT|O_TRUNC, 0600));
- // Ensure, removing an already closed file-descriptor doesn't wreak havoc
- close(sock);
- SENF_CHECK_NO_THROW( dispatcher.remove(sock) );
+ senf::ClockService::clock_type t (senf::ClockService::now());
+ try {
+ senf::scheduler::FdEvent fde ("testHandler", &handler,
+ fd, senf::scheduler::FdEvent::EV_READ);
+ SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FileDispatcher::instance().prepareRun() );
+ SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+
+ BOOST_CHECK( called );
+ BOOST_CHECK_PREDICATE( is_close, (t)(senf::ClockService::now()) );
+ }
+ catch (std::exception const & ex) {
+ std::cerr << "Exception:\n" << ex.what() << "\n";
+ throw;
+ }
+ close(fd);
+ called = false;
+ t = senf::ClockService::now();
+ SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FileDispatcher::instance().prepareRun() );
SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
- BOOST_CHECK_EQUAL( calls, 3 );
+ BOOST_CHECK( ! called );
+ BOOST_CHECK_PREDICATE(
+ is_close, (t+senf::ClockService::milliseconds(500))(senf::ClockService::now()) );
- BOOST_CHECK (stop_server(pid));
+ unlink("test.empty.file");
+ senf::scheduler::detail::FileDispatcher::instance().timeout(-1);
}
///////////////////////////////cc.e////////////////////////////////////////
+++ /dev/null
-// $Id$
-//
-// Copyright (C) 2008
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-// Stefan Bund <g0dil@berlios.de>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-/** \file
- \brief FileDispatcher non-inline non-template implementation */
-
-#include "FileDispatcher.hh"
-//#include "FileDispatcher.ih"
-
-// Custom includes
-
-//#include "FileDispatcher.mpp"
-#define prefix_
-///////////////////////////////cc.p////////////////////////////////////////
-
-prefix_ senf::scheduler::FileDispatcher::FileDispatcher(FdManager & manager,
- FIFORunner & runner)
- : manager_ (manager), runner_ (runner), managerTimeout_ (manager.timeout())
-{}
-
-prefix_ senf::scheduler::FileDispatcher::~FileDispatcher()
-{
- manager_.timeout(-1);
-
- for (FileMap::iterator i (files_.begin()); i != files_.end(); ++i) {
- runner_.dequeue(static_cast<FileEvent::ReadTask*>(&i->second));
- runner_.dequeue(static_cast<FileEvent::WriteTask*>(&i->second));
- }
-}
-
-prefix_ void senf::scheduler::FileDispatcher::add(std::string const & name, int fd,
- Callback const & cb, int events)
-{
- if (events == 0)
- return;
-
- FileMap::iterator i (files_.find(fd));
- if (i == files_.end()) {
- i = files_.insert(std::make_pair(fd, FileEvent(name))).first;
- runner_.enqueue(static_cast<FileEvent::ReadTask*>(&i->second));
- runner_.enqueue(static_cast<FileEvent::WriteTask*>(&i->second));
- }
- FileEvent & event (i->second);
-
- if (events & EV_READ)
- event.FileEvent::ReadTask::cb = cb;
- if (events & EV_WRITE)
- event.FileEvent::WriteTask::cb = cb;
-
- manager_.timeout(0);
-}
-
-prefix_ void senf::scheduler::FileDispatcher::remove(int fd, int events)
-{
- if (events == 0)
- return;
-
- FileMap::iterator i (files_.find(fd));
- if (i == files_.end())
- return;
- FileEvent & event (i->second);
-
- if (events & EV_READ) event.FileEvent::ReadTask::cb = 0;
- if (events & EV_WRITE) event.FileEvent::WriteTask::cb = 0;
-
- int activeEvents (event.activeEvents());
- if (! activeEvents) {
- runner_.dequeue(static_cast<FileEvent::ReadTask*>(&i->second));
- runner_.dequeue(static_cast<FileEvent::WriteTask*>(&i->second));
- files_.erase(fd);
- }
-
- if (files_.empty())
- manager_.timeout(managerTimeout_);
-}
-
-prefix_ void senf::scheduler::FileDispatcher::prepareRun()
-{
- for (FileMap::iterator i (files_.begin()); i != files_.end(); ++i) {
- i->second.events = i->second.activeEvents();
- if (i->second.FileEvent::ReadTask::cb)
- i->second.FileEvent::ReadTask::runnable = true;
- if (i->second.FileEvent::WriteTask::cb)
- i->second.FileEvent::WriteTask::runnable = true;
- }
-}
-
-///////////////////////////////cc.e////////////////////////////////////////
-#undef prefix_
-//#include "FileDispatcher.mpp"
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
+++ /dev/null
-// $Id$
-//
-// Copyright (C) 2008
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-// Stefan Bund <g0dil@berlios.de>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-/** \file
- \brief FileDispatcher public header */
-
-#ifndef HH_FileDispatcher_
-#define HH_FileDispatcher_ 1
-
-// Custom includes
-#include <map>
-#include "FdManager.hh"
-#include "FIFORunner.hh"
-#include "FdDispatcher.hh"
-
-//#include "FileDispatcher.mpp"
-///////////////////////////////hh.p////////////////////////////////////////
-
-namespace senf {
-namespace scheduler {
-
- /** \brief Scheduler dispatcher managing disc files
-
- This dispatcher manages file descriptors which are connected to disc files. Since disc files
- do not support select() / poll() / epoll(), they are considered to be always ready (which is
- especially untrue for remote files e.g. vie NFS).
-
- The FileDispatcher will change the FdManager's event timeout value to 0 (from -1) whenever
- there is at least one file registered.
- */
- class FileDispatcher
- {
- public:
- ///////////////////////////////////////////////////////////////////////////
- // Types
-
- typedef boost::function<void (int)> Callback;
-
- enum Events {
- EV_READ = FdManager::EV_READ, EV_WRITE = FdManager::EV_WRITE,
- EV_HUP = FdManager::EV_HUP, EV_ERR = FdManager::EV_ERR,
- EV_ALL = FdManager::EV_READ | FdManager::EV_WRITE
- };
-
- ///////////////////////////////////////////////////////////////////////////
- ///\name Structors and default members
- ///@{
-
- FileDispatcher(FdManager & manager, FIFORunner & runner);
- ~FileDispatcher();
-
- ///@}
- ///////////////////////////////////////////////////////////////////////////
-
- void add(std::string const & name, int fd, Callback const & cb, int events = EV_ALL);
- ///< Add file descriptor callback
- /**< There is always one active callback for each
- combination of file descriptor and event. Registering a
- new callback will overwrite the old callback.
- \param[in] name descriptive name
- \param[in] fd file descriptor
- \param[in] cb callback
- \param[in] events Events to call \a cb for */
-
- void remove(int fd, int events = EV_ALL);
- /**< \param[in] fd file descriptor
- \param[in] events Events for which to remove the
- callback */
-
- void prepareRun(); ///< Prepare tasks
- /**< This must be called after the FdManager returns before
- running the runnable tasks. */
-
- void timeout(int t); ///< Change FdManager timeout
- /**< Since the FileDispatcher must be able to change the
- timeout value, the value must be set here and not
- directly in the FdManager. */
- int timeout() const; ///< Retrieve current timeout value
-
- bool empty() const; ///< \c true, if no files are registered.
-
- protected:
-
- private:
- /// Internal: Disk file event
- struct FileEvent
- : public detail::FdTask<0, FileEvent>,
- public detail::FdTask<1, FileEvent>
- {
- typedef detail::FdTask<0, FileEvent> ReadTask;
- typedef detail::FdTask<1, FileEvent> WriteTask;
-
- explicit FileEvent(std::string const & name)
- : ReadTask (name), WriteTask (name) {}
-
- int activeEvents() const;
- int events;
- };
-
- typedef std::map<int, FileEvent> FileMap;
-
- FileMap files_;
- FdManager & manager_;
- FIFORunner & runner_;
- int managerTimeout_;
- };
-
-
-}}
-
-///////////////////////////////hh.e////////////////////////////////////////
-#include "FileDispatcher.cci"
-//#include "FileDispatcher.ct"
-//#include "FileDispatcher.cti"
-#endif
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
+++ /dev/null
-// $Id$
-//
-// Copyright (C) 2008
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-// Stefan Bund <g0dil@berlios.de>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-/** \file
- \brief FileDispatcher.test unit tests */
-
-//#include "FileDispatcher.test.hh"
-//#include "FileDispatcher.test.ih"
-
-// Custom includes
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include "FileDispatcher.hh"
-#include "ClockService.hh"
-
-#include "../Utils/auto_unit_test.hh"
-#include <boost/test/test_tools.hpp>
-
-#define prefix_
-///////////////////////////////cc.p////////////////////////////////////////
-
-namespace {
-
- bool is_close(senf::ClockService::clock_type a, senf::ClockService::clock_type b)
- {
- return (a<b ? b-a : a-b) < senf::ClockService::milliseconds(100);
- }
-
- bool called (false);
- void handler(int events)
- {
- called=true;
- }
-}
-
-BOOST_AUTO_UNIT_TEST(fileDispatcher)
-{
- senf::scheduler::FileDispatcher dispatcher (senf::scheduler::FdManager::instance(), senf::scheduler::FIFORunner::instance());
- dispatcher.timeout(500);
-
- // It's not necessary for the cb to be a real file .. it can be anything. The only thing is,
- // it's always called without delay.
- int fd (open("/dev/null", O_RDWR));
-
- senf::ClockService::clock_type t (senf::ClockService::now());
- SENF_CHECK_NO_THROW( dispatcher.add("testHandler", fd, &handler,
- senf::scheduler::FileDispatcher::EV_READ) );
- SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
- SENF_CHECK_NO_THROW( dispatcher.prepareRun() );
- SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
-
- BOOST_CHECK( called );
- BOOST_CHECK_PREDICATE( is_close, (t)(senf::ClockService::now()) );
-
- SENF_CHECK_NO_THROW( dispatcher.remove(fd) );
- close(fd);
-
- called = false;
- t = senf::ClockService::now();
- SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
- SENF_CHECK_NO_THROW( dispatcher.prepareRun() );
- SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
-
- BOOST_CHECK( ! called );
- BOOST_CHECK_PREDICATE(
- is_close, (t+senf::ClockService::milliseconds(500))(senf::ClockService::now()) );
-}
-
-///////////////////////////////cc.e////////////////////////////////////////
-#undef prefix_
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
prefix_ void senf::scheduler::Poller<Value>::remove(int fd)
{
if (epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, 0) == -1)
- if (errno != ENOENT && errno != EBADF)
+ if (errno != ENOENT && errno != EBADF && errno != EPERM)
+ // Calling remove() on a file descriptor which is not registered
+ // is no error, it shall be ignored:
+ // ENOENT: Not part of the poller but a valid (open) fd
+ // EBADF: The fd has been closed already. The kernel automatically removes such fds
+ // from epoll structures
+ // EPERM: The fd does not support epoll and thus can never have been added
SENF_THROW_SYSTEM_EXCEPTION("epoll_ctl()");
}
template <class Handle>
prefix_ senf::ReadHelper<Handle>::ReadHelper(Handle handle, std::string::size_type maxSize,
InternalPredicate * predicate, Callback cb)
- : handle_(handle), maxSize_(maxSize), predicate_(predicate), callback_(cb),
- errno_(0), complete_(false)
+ : handle_(handle),
+ fde_("ReadHelper", boost::bind(&ReadHelper::dispatchProcess,ptr(this), handle, _1),
+ handle, senf::scheduler::FdEvent::EV_READ),
+ maxSize_(maxSize), predicate_(predicate), callback_(cb), errno_(0), complete_(false)
{
// Here we add a *static* member taking a *smart* pointer as first
// argumnet instead of a simple bound-member as callback to the
// scheduler. This ensures, that the refcount is at least 1 as
// long as the helper is registered with the scheduler.
- senf::Scheduler::instance()
- .add(handle,boost::bind(&ReadHelper::dispatchProcess,ptr(this), handle, _1),
- senf::Scheduler::EV_READ);
}
template <class Handle>
prefix_ void senf::ReadHelper<Handle>::revoke()
{
ptr guard (this); // To ensure, 'this' is deleted only after this method terminates ...
- senf::Scheduler::instance()
- .remove(handle_,senf::Scheduler::EV_READ);
+ fde_.disable();
+ fde_.action(0); // Remove smart pointer reference to this
}
template <class Handle>
void done();
Handle handle_;
+ scheduler::FdEvent fde_;
std::string::size_type maxSize_;
boost::scoped_ptr<InternalPredicate> predicate_;
Callback callback_;
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();
}
}
{
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();
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();
}
///////////////////////////////////////////////////////////////////////////
#define prefix_ inline
///////////////////////////////cci.p///////////////////////////////////////
-// private members
-
-prefix_ void senf::Scheduler::do_add(int fd, FdCallback const & cb, int eventMask)
-{
- do_add((boost::format("<anon fd %d>") % fd).str(), fd, cb, eventMask);
-}
-
-prefix_ void senf::Scheduler::do_add(std::string const & name, int fd, FdCallback const & cb,
- int eventMask)
-{
- if (! fdDispatcher_.add(name, fd, cb, eventMask))
- fileDispatcher_.add(name, fd, cb, eventMask);
-}
-
-prefix_ void senf::Scheduler::do_remove(int fd, int eventMask)
-{
- // We don't know, where the descriptor is registered. However, this is no problem since removing
- // a non-registered fd is a no-opp
- fdDispatcher_.remove(fd, eventMask);
- fileDispatcher_.remove(fd, eventMask);
-}
-
// public members
prefix_ senf::Scheduler::Scheduler & senf::Scheduler::instance()
return instance;
}
-prefix_ int senf::retrieve_filehandle(int fd)
-{
- return fd;
-}
-
prefix_ void senf::Scheduler::terminate()
{
terminate_ = true;
}
prefix_ senf::Scheduler::Scheduler()
- : terminate_ (false),
- fdDispatcher_ (scheduler::FdManager::instance(), scheduler::FIFORunner::instance()),
- fileDispatcher_ (scheduler::FdManager::instance(), scheduler::FIFORunner::instance())
+ : terminate_ (false)
{}
///////////////////////////////cci.e///////////////////////////////////////
+++ /dev/null
-// $Id$
-//
-// Copyright (C) 2006
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-// Stefan Bund <g0dil@berlios.de>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-/** \file
- \brief Scheduler inline template implementation
- */
-
-//#include "Scheduler.ih"
-
-// Custom includes
-#include <boost/bind.hpp>
-
-#define prefix_ inline
-///////////////////////////////cti.p///////////////////////////////////////
-
-template <class Handle>
-prefix_ void senf::Scheduler::add(Handle const & handle, FdCallback const & cb, int eventMask)
-{
- // retrieve_filehandle is found via ADL
- do_add(retrieve_filehandle(handle),cb,eventMask);
-}
-
-template <class Handle>
-prefix_ void senf::Scheduler::add(std::string const & name, Handle const & handle,
- FdCallback const & cb, int eventMask)
-{
- do_add(name, retrieve_filehandle(handle),cb,eventMask);
-}
-
-template <class Handle>
-prefix_ void senf::Scheduler::remove(Handle const & handle, int eventMask)
-{
- // retrieve_filehandle is found via ADL
- do_remove(retrieve_filehandle(handle),eventMask);
-}
-
-///////////////////////////////cti.e///////////////////////////////////////
-#undef prefix_
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// comment-column: 40
-// End:
// 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"
///@}
///////////////////////////////////////////////////////////////////////////
- ///\name File Descriptors
- ///\{
-
- template <class Handle>
- void add(std::string const & name, Handle const & handle, FdCallback const & cb,
- int eventMask = EV_ALL); ///< Add file handle event callback
- /**< add() will add a callback to the %scheduler. The
- callback will be called for the given type of event on
- the given arbitrary file-descriptor or
- handle-like object. If there already is a Callback
- registered for one of the events requested, the new
- handler will replace the old one.
- \param[in] name descriptive name to identify the
- callback.
- \param[in] handle file descriptor or handle providing
- the Handle interface defined above.
- \param[in] cb callback
- \param[in] eventMask arbitrary combination via '|'
- operator of \ref senf::Scheduler::EventId "EventId"
- designators. */
-
- template <class Handle>
- void add(Handle const & handle, FdCallback const & cb,
- int eventMask = EV_ALL); ///< Add file handle event callback
- /**< \see add() */
-
-
- template <class Handle>
- void remove(Handle const & handle, int eventMask = EV_ALL); ///< Remove event callback
- /**< remove() will remove any callback registered for any of
- the given events on the given file descriptor or handle
- like object.
- \param[in] handle file descriptor or handle providing
- the Handle interface defined above.
- \param[in] eventMask arbitrary combination via '|'
- operator of \ref senf::Scheduler::EventId "EventId"
- designators. */
-
- ///\}
-
void process(); ///< Event handler main loop
/**< This member must be called at some time to enter the
event handler main loop. Only while this function is
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
///////////////////////////////hh.e////////////////////////////////////////
#include "Scheduler.cci"
//#include "Scheduler.ct"
-#include "Scheduler.cti"
+//#include "Scheduler.cti"
#endif
\f
#include <errno.h>
#include <string.h>
#include <iostream>
+#include <boost/bind.hpp>
#include "Scheduler.hh"
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,
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));
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,
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,
/** \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
{
SENF_LOG_CLASS_AREA();
- typedef boost::intrusive::imultiset< TimerSetBase::value_traits<TimerEvent>,
- TimerSetCompare,
- false > TimerSet;
-
public:
using singleton<TimerDispatcher>::instance;
using singleton<TimerDispatcher>::alive;
static void sigHandler(int signal, ::siginfo_t * siginfo, void *);
void reschedule();
+ typedef boost::intrusive::imultiset< TimerSetBase::value_traits<TimerEvent>,
+ TimerSetCompare,
+ false > TimerSet;
+
TimerSet timers_;
int timerPipe_[2];
// Custom includes
#include <errno.h>
+#include <boost/bind.hpp>
#include "../Utils/Exception.hh"
#include "Scheduler.hh"
template <class Handle>
prefix_ senf::WriteHelper<Handle>::WriteHelper(Handle handle, std::string const & data,
Callback callback)
- : handle_(handle), data_(data), callback_(callback),
- offset_(data_.begin()), errno_(0)
-{
- senf::Scheduler::instance()
- .add(handle_, boost::bind(&WriteHelper::dispatchProcess, ptr(this), _1, _2),
- senf::Scheduler::EV_WRITE);
-}
+ : handle_(handle),
+ fde_("WriteHelper", boost::bind(&WriteHelper::dispatchProcess, ptr(this), _1, _2),
+ handle, scheduler::FdEvent::EV_WRITE),
+ data_(data), callback_(callback), offset_(data_.begin()), errno_(0)
+{}
template <class Handle>
prefix_ std::string const & senf::WriteHelper<Handle>::data()
prefix_ void senf::WriteHelper<Handle>::revoke()
{
ptr guard (this); // To ensure, 'this' is deleted only after this method terminates ...
- senf::Scheduler::instance()
- .remove(handle_, senf::Scheduler::EV_WRITE);
+ fde_.disable();
+ fde_.action(0); // To remove the smart pointer reference to this
}
template <class Handle>
void done();
Handle handle_;
+ scheduler::FdEvent fde_;
mutable std::string data_;
Callback callback_;
// 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)
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;
}
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;
i->offset -= n;
if (target->offset >= buffer_.size())
- Scheduler::instance().remove(target->fd);
+ target->writeevent.disable();
if (src_ == -1 && (buffer_.empty() || targets_.empty()))
cb_();
}
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
- \brief FileDispatcher inline non-template implementation */
+ \brief Daemon inline non-template implementation */
-//#include "FileDispatcher.ih"
+#include "Daemon.ih"
// Custom includes
+#include <boost/bind.hpp>
#define prefix_ inline
///////////////////////////////cci.p///////////////////////////////////////
-prefix_ int senf::scheduler::FileDispatcher::FileEvent::activeEvents()
- const
-{
- return
- (ReadTask::cb ? EV_READ : 0) |
- (WriteTask::cb ? EV_WRITE : 0);
-}
-
-prefix_ void senf::scheduler::FileDispatcher::timeout(int t)
-{
- managerTimeout_ = t;
- if (files_.empty())
- manager_.timeout(managerTimeout_);
-}
-
-prefix_ int senf::scheduler::FileDispatcher::timeout()
- const
-{
- return managerTimeout_;
-}
-
-prefix_ bool senf::scheduler::FileDispatcher::empty()
- const
-{
- return files_.empty();
-}
+prefix_ senf::detail::DaemonWatcher::Forwarder::Target::Target(Forwarder & fwd, int fd_)
+ : fd (fd_), offset (0),
+ writeevent ("DaemonWatcher::Forwarder::Target",
+ boost::bind(&Forwarder::writeData, &fwd, _1, this),
+ fd, scheduler::FdEvent::EV_WRITE, false)
+{}
///////////////////////////////cci.e///////////////////////////////////////
#undef prefix_
}
///////////////////////////////hh.e////////////////////////////////////////
-//#include "Daemon.cci"
+#include "Daemon.cci"
//#include "Daemon.ct"
//#include "Daemon.cti"
#endif
// Custom includes
#include <deque>
-#include <list>
+#include "../boost/intrusive/iset.hpp"
+#include "../boost/intrusive/iset_hook.hpp"
#include <boost/utility.hpp>
#include <boost/function.hpp>
#include "../../Scheduler/Scheduler.hh"
private:
+ // This is awkward ... we'll need to erase an element from the target list given
+ // only the target object. This is best implement using an intrusive container.
+ // However, this makes memory-management explicit and we'll need to be careful.
typedef std::deque<char> Buffer;
- struct Target
+ struct TargetListTag;
+ typedef boost::intrusive::ilist_base_hook<TargetListTag> TargetListBase;
+
+ struct Target : public TargetListBase
{
+ Target(Forwarder & fwd, int fd);
+
int fd;
Buffer::size_type offset;
+ scheduler::FdEvent writeevent;
+ };
+ typedef boost::intrusive::ilist<TargetListBase::value_traits<Target>,false> Targets;
+
+ struct DestroyDelete
+ {
+ template <class T>
+ void operator()(T * t) { delete t; }
};
- typedef std::list<Target> Targets;
void readData(int event);
- void writeData(int event, Targets::iterator target);
+ void writeData(int event, Target * target);
Buffer buffer_;
int src_;
-
Targets targets_;
-
Callback cb_;
+ scheduler::FdEvent readevent_;
};
void pipeClosed(int id);