From: jmo Date: Tue, 13 Apr 2010 09:51:58 +0000 (+0000) Subject: new timer event proxy to reduce scheduler load X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=acce6d54436fa760c0f4770ea3a6c76ae40e0bb8;p=senf.git new timer event proxy to reduce scheduler load the documentation need to be enriched git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1591 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/senf/Scheduler/TimerEventProxy.ct b/senf/Scheduler/TimerEventProxy.ct new file mode 100644 index 0000000..cb665b6 --- /dev/null +++ b/senf/Scheduler/TimerEventProxy.ct @@ -0,0 +1,114 @@ +// $Id$ +// +// Copyright (C) 2010 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Mathias Kretschmer +// +// 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 TimerEventProxy public header */ + +#define prefix_ + +template +prefix_ senf::scheduler::TimerEventProxy::TimerEventProxy() : + timer("timer", senf::membind(&TimerEventProxy::timerEvent, this), 0, + false), entrySetById(entrySet.template get ()), + entrySetByTimeout(entrySet.template get ()) +{ + +} + +template +prefix_ senf::scheduler::TimerEventProxy::TimerEventProxy( std::string const & name, + senf::console::DirectoryNode & node) : + timer("timer", senf::membind(&TimerEventProxy::timerEvent, this), 0, + false), entrySetById(entrySet.template get ()), + entrySetByTimeout(entrySet.template get ()) +{ + node.add(name, senf::console::factory::Command( + &TimerEventProxy::listTimers, this) .doc("List active Timers")); +} + +template +prefix_ void senf::scheduler::TimerEventProxy::timerEvent() { + + senf::ClockService::clock_type actual = senf::ClockService::now(); + typename EntrySetByTimeout_t::iterator it; + + // execute the timer callbacks first + + it = entrySetByTimeout.begin(); + while (it != entrySetByTimeout.end() && it->timeout <= actual) { + Entry item(*it); + // remove due entry from set + entrySetByTimeout.erase(it); + // call callback + item.fkt(actual, item.id); + + it = entrySetByTimeout.begin(); + } + + if (entrySet.size() > 0) { + timer.timeout(entrySetByTimeout.begin()->timeout); + } +} + +template +prefix_ void senf::scheduler::TimerEventProxy::add( + senf::ClockService::clock_type timeout, T const & id, Callback fkt) +{ + // insert new entry + entrySetByTimeout.insert(Entry (timeout, id, fkt)); + + // the scheduler time to the first earliest timeout (ordered index) + timer.timeout(entrySetByTimeout.begin()->timeout); + + // // if map was empty before, hence we need to activate the time event object + // if( entrySetByTimeout.size() >= 1){ + // timer.enable(); + // } +} + +template +prefix_ bool senf::scheduler::TimerEventProxy::del(T const & id) +{ + typename EntrySetById_t::iterator it(entrySetById.find(Entry (0, id, NULL))); + + if (it != entrySetById.end()) { + entrySetById.erase(it); + return true; + } + return false; +} + +template +prefix_ std::vector > senf::scheduler::TimerEventProxy::list() +{ + std::vector > tmp; + + typename EntrySetByTimeout_t::iterator it; + for (it = entrySetByTimeout.begin(); it != entrySetByTimeout.end(); ++it) { + tmp.push_back(std::make_pair( it->timeout, it->id)); + } + + return tmp; +} + +#undef prefix_ + diff --git a/senf/Scheduler/TimerEventProxy.hh b/senf/Scheduler/TimerEventProxy.hh new file mode 100644 index 0000000..ae77e58 --- /dev/null +++ b/senf/Scheduler/TimerEventProxy.hh @@ -0,0 +1,136 @@ +// $Id$ +// +// Copyright (C) 2010 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Mathias Kretschmer +// +// 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 TimerEventProxy public header */ + +#ifndef HH_SENF_Scheduler_TimerEventProxy_ +#define HH_SENF_Scheduler_TimerEventProxy_ 1 + +#ifdef SENF_DEBUG +# define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING +# define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace senf { +namespace scheduler { + + + /** \brief Deadline timer proxy + + The TimerEventProxy is meant to host long term deadline timers to reduce the load of the + Scheduler with a hugh count of TimerEvent items. It registers deadline timer callbacks which + will be called when the timer expires. + + The functionality is based on one TimerEvent instance per TimerEventProxy instance and could + host a big count of timers. + */ + template + class TimerEventProxy { + private: + + template + struct Entry { + public: + senf::ClockService::clock_type timeout; + T id; + boost::function fkt; + + bool operator<(const Entry & e) const { + return id < e.id; + } + // bool operator==(const Entry &e)const{return id == e.id;} + Entry(senf::ClockService::clock_type _timeout, T_ _id, boost::function _fkt) : + timeout(_timeout), id(_id), fkt(_fkt) { + } + }; + + + senf::scheduler::TimerEvent timer; + + // + // data structure to hold active timers + // + struct Timeout {}; + struct Id {}; + typedef boost::multi_index_container , + boost::multi_index::indexed_by< + boost::multi_index::ordered_non_unique< + boost::multi_index::tag, + boost::multi_index::member , + senf::ClockService::clock_type, + &Entry::timeout> >, + boost::multi_index::ordered_unique, boost::multi_index::identity > > > > + EntrySet; + + typedef typename EntrySet::template index::type + EntrySetByTimeout_t; + typedef typename EntrySet::template index::type EntrySetById_t; + + EntrySet entrySet; + EntrySetById_t & entrySetById; + EntrySetByTimeout_t & entrySetByTimeout; + + private: + // callback for the Scheduler timer event + void timerEvent(); + + public: + /////////////////////////////////////////////////////////////////////////// + // Types + typedef boost::function Callback; + + TimerEventProxy(); + ///< Instantiate a TimerEventProxy + + TimerEventProxy(std::string const & name, senf::console::DirectoryNode & node); + ///< Instantiate a TimerEventProxy and add the list command to the give DirectoryNode + + void add(senf::ClockService::clock_type timeout, T const &id, Callback cb); + ///< Add new deadline timer + bool del(T const & id); + ///< Remove timer by given \a id. + std::vector > list(); + ///< Returns a vector of all active timers with timeout and id. + }; +} +} + +#include "TimerEventProxy.ct" + +#endif diff --git a/senf/Scheduler/TimerEventProxy.test.cc b/senf/Scheduler/TimerEventProxy.test.cc new file mode 100644 index 0000000..eb07187 --- /dev/null +++ b/senf/Scheduler/TimerEventProxy.test.cc @@ -0,0 +1,100 @@ +// $Id$ +// +// Copyright (C) 2010 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Jens Moedeker +// +// 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 TimerEventProxy public header */ +// + +/** \file + \brief TimerEventProxy.test non-inline non-template implementation */ + +//#include "TimerEventProxy.test.hh" +//#include "TimerEventProxy.test.ih" + +// Custom includes +#include "TimerEventProxy.hh" +#include "Scheduler.hh" +#include + +#include +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// +namespace { + + int count = 0; + + void handler( senf::ClockService::clock_type time, int const &id) + { + std::cerr << "TimerEventProxy handler count="< timers; + + SENF_CHECK_NO_THROW( timers.add( t + senf::ClockService::milliseconds(10000), 0 , &handler)); + SENF_CHECK_NO_THROW( timers.add( t + senf::ClockService::milliseconds(800), 3, &handler)); + SENF_CHECK_NO_THROW( timers.add( t + senf::ClockService::milliseconds(200), 1, &handler)); + SENF_CHECK_NO_THROW( timers.del( 3)); + SENF_CHECK_NO_THROW( timers.add( t + senf::ClockService::milliseconds(700), 2, &handler)); + + // set timeout for termination + senf::scheduler::TimerEvent te_exit( "myexit", &myexit, t + senf::ClockService::milliseconds( 1000)); + + SENF_CHECK_NO_THROW( senf::scheduler::process() ); + + BOOST_CHECK( count == 2); + } +} + + +///////////////////////////////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: