--- /dev/null
+// $Id$
+//
+// Copyright (C) 2010
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Mathias Kretschmer <mtk@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 TimerEventProxy public header */
+
+#define prefix_
+
+template<class T>
+prefix_ senf::scheduler::TimerEventProxy<T>::TimerEventProxy() :
+ timer("timer", senf::membind(&TimerEventProxy<T>::timerEvent, this), 0,
+ false), entrySetById(entrySet.template get<Id> ()),
+ entrySetByTimeout(entrySet.template get<Timeout> ())
+{
+
+}
+
+template<class T>
+prefix_ senf::scheduler::TimerEventProxy<T>::TimerEventProxy( std::string const & name,
+ senf::console::DirectoryNode & node) :
+ timer("timer", senf::membind(&TimerEventProxy<T>::timerEvent, this), 0,
+ false), entrySetById(entrySet.template get<Id> ()),
+ entrySetByTimeout(entrySet.template get<Timeout> ())
+{
+ node.add(name, senf::console::factory::Command(
+ &TimerEventProxy<T>::listTimers, this) .doc("List active Timers"));
+}
+
+template<class T>
+prefix_ void senf::scheduler::TimerEventProxy<T>::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<T> 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<class T>
+prefix_ void senf::scheduler::TimerEventProxy<T>::add(
+ senf::ClockService::clock_type timeout, T const & id, Callback fkt)
+{
+ // insert new entry
+ entrySetByTimeout.insert(Entry<T> (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<class T>
+prefix_ bool senf::scheduler::TimerEventProxy<T>::del(T const & id)
+{
+ typename EntrySetById_t::iterator it(entrySetById.find(Entry<T> (0, id, NULL)));
+
+ if (it != entrySetById.end()) {
+ entrySetById.erase(it);
+ return true;
+ }
+ return false;
+}
+
+template<class T>
+prefix_ std::vector<std::pair<senf::ClockService::clock_type, T> > senf::scheduler::TimerEventProxy<T>::list()
+{
+ std::vector<std::pair<senf::ClockService::clock_type, T> > tmp;
+
+ typename EntrySetByTimeout_t::iterator it;
+ for (it = entrySetByTimeout.begin(); it != entrySetByTimeout.end(); ++it) {
+ tmp.push_back(std::make_pair<senf::ClockService::clock_type, T>( it->timeout, it->id));
+ }
+
+ return tmp;
+}
+
+#undef prefix_
+
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2010
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Mathias Kretschmer <mtk@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 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 <boost/range/iterator_range.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/hashed_index.hpp>
+#include <boost/multi_index/sequenced_index.hpp>
+#include <boost/multi_index/key_extractors.hpp>
+#include <boost/multi_index/random_access_index.hpp>
+#include <boost/multi_index/identity.hpp>
+#include <boost/multi_index/member.hpp>
+
+#include <senf/Scheduler/ClockService.hh>
+#include <senf/Scheduler/TimerEvent.hh>
+#include <senf/Utils/Console/Console.hh>
+
+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 T>
+ class TimerEventProxy {
+ private:
+
+ template<class T_>
+ struct Entry {
+ public:
+ senf::ClockService::clock_type timeout;
+ T id;
+ boost::function<void(senf::ClockService::clock_type, T_ const &)> fkt;
+
+ bool operator<(const Entry<T_> & e) const {
+ return id < e.id;
+ }
+ // bool operator==(const Entry<T> &e)const{return id == e.id;}
+ Entry(senf::ClockService::clock_type _timeout, T_ _id, boost::function<void(
+ senf::ClockService::clock_type, T_)> _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<Entry<T> ,
+ boost::multi_index::indexed_by<
+ boost::multi_index::ordered_non_unique<
+ boost::multi_index::tag<Timeout>,
+ boost::multi_index::member<Entry<T> ,
+ senf::ClockService::clock_type,
+ &Entry<T>::timeout> >,
+ boost::multi_index::ordered_unique<boost::multi_index::tag<
+ Id>, boost::multi_index::identity<Entry<T> > > > >
+ EntrySet;
+
+ typedef typename EntrySet::template index<Timeout>::type
+ EntrySetByTimeout_t;
+ typedef typename EntrySet::template index<Id>::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<void(senf::ClockService::clock_type, T const &)> 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<std::pair<senf::ClockService::clock_type, T> > list();
+ ///< Returns a vector of all active timers with timeout and id.
+ };
+}
+}
+
+#include "TimerEventProxy.ct"
+
+#endif
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2010
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Jens Moedeker <jens.moedeker@fokus.fraunhofer.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 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 <boost/bind.hpp>
+
+#include <senf/Utils/auto_unit_test.hh>
+#include <boost/test/test_tools.hpp>
+#include <boost/random.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+namespace {
+
+ int count = 0;
+
+ void handler( senf::ClockService::clock_type time, int const &id)
+ {
+ std::cerr << "TimerEventProxy handler count="<<count<<" id="<<id<<"\n";
+ ++count;
+ }
+
+ void myexit(){
+ std::cerr << "TimerEventProxy terminating\n";
+ senf::scheduler::terminate();
+ }
+
+}
+
+SENF_AUTO_UNIT_TEST(timerEventProxy)
+{
+
+// // abort on watchdog timeout
+// senf::scheduler::watchdogAbort( true);
+// senf::scheduler::watchdogTimeout(5000);
+
+ senf::ClockService::clock_type t (senf::ClockService::now());
+ {
+ senf::scheduler::TimerEventProxy<int> 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: