PPI: Implement joins
g0dil [Fri, 17 Aug 2007 20:19:41 +0000 (20:19 +0000)]
Packets: Silence PacketRegistry warnings with final=1
Utils: Remove MicroTime
Scheduler: Sart implementing more reliable timing mechanism

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@397 270642c3-0616-0410-b53a-bc976706d245

16 files changed:
PPI/Connectors.cci
PPI/Joins.cc [new file with mode: 0644]
PPI/Joins.cci [moved from Utils/MicroTime.cc with 52% similarity]
PPI/Joins.cti [new file with mode: 0644]
PPI/Joins.hh [new file with mode: 0644]
PPI/Joins.test.cc [new file with mode: 0644]
PPI/SocketReader.test.cc
PPI/SocketWriter.test.cc
PPI/predecl.hh
Packets/PacketRegistry.ct
Scheduler/Scheduler.cc
Scheduler/Scheduler.cci
Scheduler/Scheduler.hh
Scheduler/Scheduler.test.cc
Utils/MicroTime.hh [deleted file]
Utils/MicroTime.test.cc [deleted file]

index 1f3f192..5dcb08e 100644 (file)
@@ -60,6 +60,7 @@ prefix_ senf::ppi::connector::Connector::~Connector()
 
 prefix_ void senf::ppi::connector::Connector::connect(Connector & target)
 {
+    BOOST_ASSERT( ! peer_ && ! target.peer_ );
     peer_ = & target;
     target.peer_ = this;
 }
@@ -89,9 +90,10 @@ prefix_ bool senf::ppi::connector::PassiveConnector::nativeThrottled()
 
 prefix_ void senf::ppi::connector::PassiveConnector::throttle()
 {
-    if (!throttled())
+    if (!throttled()) {
+        nativeThrottled_ = true;
         emitThrottle();
-    nativeThrottled_ = true;
+    }
 }
 
 prefix_ void senf::ppi::connector::PassiveConnector::unthrottle()
diff --git a/PPI/Joins.cc b/PPI/Joins.cc
new file mode 100644 (file)
index 0000000..4be6c97
--- /dev/null
@@ -0,0 +1,130 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     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 Joins non-inline non-template implementation */
+
+#include "Joins.hh"
+//#include "Joins.ih"
+
+// Custom includes
+#include <algorithm>
+#include <boost/bind.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
+
+//#include "Joins.mpp"
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::ppi::module::PassiveJoin
+
+////////////////////////////////////////
+// private members
+
+prefix_ senf::ppi::connector::PassiveInput & senf::ppi::module::PassiveJoin::newInput()
+{
+    inputs_.push_back(new connector::PassiveInput());
+    connector::PassiveInput & input (inputs_.back());
+
+    noroute(input);
+    input.onRequest(boost::bind(&PassiveJoin::request,this,boost::ref(input)));
+
+    return input;
+}
+
+prefix_ void senf::ppi::module::PassiveJoin::request(connector::PassiveInput & input)
+{
+    output(input());
+}
+
+prefix_ void senf::ppi::module::PassiveJoin::onThrottle()
+{
+    using boost::lambda::_1;
+    using boost::lambda::bind;
+    std::for_each(inputs_.begin(), inputs_.end(),
+                  bind(&connector::PassiveInput::throttle, _1));
+}
+
+prefix_ void senf::ppi::module::PassiveJoin::onUnthrottle()
+{
+    using boost::lambda::_1;
+    using boost::lambda::bind;
+    std::for_each(inputs_.begin(), inputs_.end(),
+                  bind(&connector::PassiveInput::unthrottle, _1));
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::ppi::module::PriorityJoin
+
+////////////////////////////////////////
+// private members
+
+prefix_ senf::ppi::connector::ActiveInput & senf::ppi::module::PriorityJoin::newInput()
+{
+    inputs_.push_back(new connector::ActiveInput());
+    connector::ActiveInput & input (inputs_.back());
+
+    noroute(input);
+    input.onThrottle(&PriorityJoin::onThrottle);
+    input.onUnthrottle(&PriorityJoin::onUnthrottle);
+
+    return input;
+}
+
+prefix_ void senf::ppi::module::PriorityJoin::request()
+{
+    using boost::lambda::_1;
+    using boost::lambda::bind;
+    Inputs::iterator i (std::find_if(inputs_.begin(), inputs_.end(),
+                                     ! bind(&connector::ActiveInput::throttled, _1)));
+    if (i != inputs_.end())
+        output((*i)());
+}
+
+prefix_ void senf::ppi::module::PriorityJoin::onThrottle()
+{
+    if (std::find_if(inputs_.begin(), inputs_.end(),
+                     ! bind(&connector::ActiveInput::throttled, _1)) == inputs_.end())
+        output.throttle();
+}
+
+prefix_ void senf::ppi::module::PriorityJoin::onUnthrottle()
+{
+    output.unthrottle();
+}
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+//#include "Joins.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:
similarity index 52%
rename from Utils/MicroTime.cc
rename to PPI/Joins.cci
index 4a19fdf..00c7c9a 100644 (file)
@@ -1,6 +1,9 @@
 // $Id$
 //
-// Copyright (C) 2006 Stefan Bund <g0dil@senf.berlios.de>
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     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
 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 /** \file
-    \brief MicroTime non-inline non-template implementation */
-
-#include "MicroTime.hh"
-//#include "MicroTime.ih"
+    \brief Joins inline non-template implementation */
 
 // Custom includes
-#include <sys/time.h>
-#include <time.h>
-#include <errno.h>
 
-#include "Utils/Exception.hh"
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
 
-//#include "MicroTime.mpp"
-#define prefix_
-///////////////////////////////cc.p////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+// senf::ppi::module::PassiveJoin
 
-prefix_ senf::MicroTime senf::now()
+prefix_ senf::ppi::module::PassiveJoin::PassiveJoin()
 {
-    struct timeval tv;
-    if (gettimeofday(&tv,0) < 0)
-        throw SystemException(errno);
-    return 1000000*MicroTime(tv.tv_sec) + tv.tv_usec;
+    noroute(output);
+    output.onThrottle(&PassiveJoin::onThrottle);
+    output.onUnthrottle(&PassiveJoin::onUnthrottle);
 }
 
+///////////////////////////////////////////////////////////////////////////
+// senf::ppi::module::PriorityJoin
+
+prefix_ senf::ppi::module::PriorityJoin::PriorityJoin()
+{
+    noroute(output);
+    output.onRequest(&PriorityJoin::request);
+}
 
-///////////////////////////////cc.e////////////////////////////////////////
+///////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
-//#include "MicroTime.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"
-// comment-column: 40
 // End:
diff --git a/PPI/Joins.cti b/PPI/Joins.cti
new file mode 100644 (file)
index 0000000..e100b08
--- /dev/null
@@ -0,0 +1,87 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     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 Joins inline template implementation */
+
+//#include "Joins.ih"
+
+// Custom includes
+#include "Setup.hh"
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::ppi::module::PassiveJoin
+
+template <class Source>
+prefix_ senf::ppi::connector::PassiveInput &
+senf::ppi::module::PassiveJoin::connect(Source & source)
+{
+    connector::PassiveInput & input (newInput());
+    ppi::connect(source,input);
+    return input;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::ppi::module::PriorityJoin
+
+template <class Source>
+prefix_ senf::ppi::connector::ActiveInput &
+senf::ppi::module::PriorityJoin::connect(Source & source)
+{
+    connector::ActiveInput & input (newInput());
+    ppi::connect(source,input);
+    return input;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// namespace members
+
+template <class Source>
+prefix_ senf::ppi::connector::PassiveInput & senf::ppi::connect(Source & source,
+                                                                module::PassiveJoin & target)
+{
+    return target.connect(source);
+}
+
+template <class Source>
+prefix_ senf::ppi::connector::ActiveInput & senf::ppi::connect(Source & source,
+                                                               module::PriorityJoin & target)
+{
+    return target.connect(source);
+}
+
+///////////////////////////////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:
diff --git a/PPI/Joins.hh b/PPI/Joins.hh
new file mode 100644 (file)
index 0000000..7276384
--- /dev/null
@@ -0,0 +1,112 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     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 Joins public header */
+
+#ifndef HH_Joins_
+#define HH_Joins_ 1
+
+// Custom includes
+#include <boost/ptr_container/ptr_vector.hpp>
+#include "predecl.hh"
+#include "Connectors.hh"
+#include "Module.hh"
+
+//#include "Joins.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace ppi {
+
+    template <class Source>
+    connector::PassiveInput & connect(Source & source, module::PassiveJoin & target);
+    
+    template <class Source>
+    connector::ActiveInput & connect(Source & source, module::PriorityJoin & target);
+
+namespace module {
+
+    class PassiveJoin
+        : public Module
+    {
+        SENF_PPI_MODULE(PassiveJoin);
+    public:
+        connector::ActiveOutput output;
+
+        PassiveJoin();
+
+        template <class Source>
+        connector::PassiveInput & connect(Source & source);
+
+    private:
+        connector::PassiveInput & newInput();
+
+        void request(connector::PassiveInput & input);
+        void onThrottle();
+        void onUnthrottle();
+
+        typedef boost::ptr_vector<connector::PassiveInput> Inputs;
+        Inputs inputs_;
+    };
+
+    class PriorityJoin
+        : public Module
+    {
+        SENF_PPI_MODULE(PriorityJoin);
+    public:
+        connector::PassiveOutput output;
+
+        PriorityJoin();
+
+        template <class Source>
+        connector::ActiveInput & connect(Source & source);
+
+    private:
+        connector::ActiveInput & newInput();
+
+        void request();
+        void onThrottle();
+        void onUnthrottle();
+
+        typedef boost::ptr_vector<connector::ActiveInput> Inputs;
+        Inputs inputs_;
+    };
+
+}}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "Joins.cci"
+//#include "Joins.ct"
+#include "Joins.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:
diff --git a/PPI/Joins.test.cc b/PPI/Joins.test.cc
new file mode 100644 (file)
index 0000000..8e336bb
--- /dev/null
@@ -0,0 +1,123 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     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 Joins.test unit tests */
+
+//#include "Joins.test.hh"
+//#include "Joins.test.ih"
+
+// Custom includes
+#include "Joins.hh"
+#include "DebugModules.hh"
+#include "Setup.hh"
+#include "Packets/Packets.hh"
+
+#include <boost/test/auto_unit_test.hpp>
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+namespace ppi = senf::ppi;
+namespace connector = ppi::connector;
+namespace module = ppi::module;
+namespace debug = module::debug;
+
+BOOST_AUTO_UNIT_TEST(passiveJoin)
+{
+    debug::ActivePacketSource source1;
+    debug::ActivePacketSource source2;
+    module::PassiveJoin join;
+    debug::PassivePacketSink sink;
+
+    ppi::connect(source1, join);
+    ppi::connect(source2, join);
+    ppi::connect(join, sink);
+    ppi::init();
+
+    senf::Packet p (senf::DataPacket::create());
+
+    source1.submit(p);
+    BOOST_CHECK_EQUAL( sink.size(), 1u );
+    source2.submit(p);
+    BOOST_CHECK_EQUAL( sink.size(), 2u );
+
+    sink.input.throttle();
+    BOOST_CHECK( ! source1 );
+    BOOST_CHECK( ! source2 );
+    
+    source1.submit(p);
+    source2.submit(p);
+    BOOST_CHECK_EQUAL( sink.size(), 2u );
+    sink.input.unthrottle();
+    BOOST_CHECK_EQUAL( sink.size(), 4u );
+}
+
+BOOST_AUTO_UNIT_TEST(priorityJoin)
+{
+    debug::PassivePacketSource source1;
+    debug::PassivePacketSource source2;
+    module::PriorityJoin join;
+    debug::ActivePacketSink sink;
+
+    ppi::connect(source1, join);
+    ppi::connect(source2, join);
+    ppi::connect(join,sink);
+    ppi::init();
+
+    BOOST_CHECK( ! sink );
+
+    senf::Packet p1 (senf::DataPacket::create());
+    senf::Packet p2 (senf::DataPacket::create());
+    
+    source1.submit(p1);
+    BOOST_CHECK( sink );
+    source2.submit(p2);
+    BOOST_CHECK( sink );
+    BOOST_CHECK( sink.request() == p1 );
+    BOOST_CHECK( sink );
+    BOOST_CHECK( sink.request() == p2 );
+    BOOST_CHECK( ! sink );
+
+    source1.submit(p1);
+    source2.submit(p2);
+    source1.submit(p1);
+    BOOST_CHECK( sink.request() == p1 );
+    BOOST_CHECK( sink.request() == p1 );
+    BOOST_CHECK( sink.request() == p2 );
+    BOOST_CHECK( ! sink );
+}
+
+///////////////////////////////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:
index 8a28946..b17d6bc 100644 (file)
@@ -64,7 +64,7 @@ BOOST_AUTO_UNIT_TEST(socketReader)
 
     senf::UDPv4ClientSocketHandle outputSocket;
     outputSocket.writeto(senf::INet4SocketAddress("localhost:44344"),data);
-    senf::Scheduler::instance().timeout(100, &timeout);
+    senf::Scheduler::instance().timeout(100000, &timeout);
     senf::ppi::run();
 
     BOOST_REQUIRE( ! sink.empty() );
index 25c1a5d..64687ef 100644 (file)
@@ -84,7 +84,7 @@ BOOST_AUTO_UNIT_TEST(activeSocketWriter)
 
     senf::UDPv4ClientSocketHandle inputSocket;
     inputSocket.bind(senf::INet4SocketAddress("localhost:44344"));
-    senf::Scheduler::instance().timeout(100, &timeout);
+    senf::Scheduler::instance().timeout(100000, &timeout);
     source.submit(p);
     senf::ppi::run();
 
index 2b8f6ea..49eae2b 100644 (file)
@@ -64,6 +64,8 @@ namespace ppi {
         namespace detail {
             template <class Source, class Target> class RouteHelper;
         }
+        class PassiveJoin;
+        class PriorityJoin;
     }
 
     namespace connector {
index 2147023..a0bf61c 100644 (file)
@@ -42,6 +42,10 @@ template <class KeyType>
 template <class PacketType>
 prefix_ void senf::detail::PacketRegistryImpl<KeyType>::registerPacket(key_t key)
 {
+#ifdef NDEBUG
+    registry_.insert(std::make_pair(key, Entry_ptr(new detail::PkReg_EntryImpl<PacketType>())));
+    reverseRegistry_.insert(std::make_pair(senf::typeIdValue<PacketType>(), key));
+#else
     bool isUnique (
         registry_.insert(
             std::make_pair(key, Entry_ptr(new detail::PkReg_EntryImpl<PacketType>()))).second);
@@ -52,6 +56,7 @@ prefix_ void senf::detail::PacketRegistryImpl<KeyType>::registerPacket(key_t key
             std::make_pair(senf::typeIdValue<PacketType>(), key)).second);
     // If this assertion fails, the same Packet was registered with two different keys
     BOOST_ASSERT( isNew );
+#endif
 }
 
 template <class KeyType>
index ed6649d..799c4a5 100644 (file)
@@ -79,7 +79,6 @@
 #include <errno.h>
 #include <sys/epoll.h>
 #include "Utils/Exception.hh"
-#include "Utils/MicroTime.hh"
 
 static const int EPollInitialSize = 16;
 
@@ -92,13 +91,14 @@ prefix_ senf::Scheduler::Scheduler & senf::Scheduler::instance()
     return instance;
 }
 
-prefix_ void senf::Scheduler::timeout(unsigned long timeout, TimerCallback const & cb)
+prefix_ void senf::Scheduler::timeout(sched_time timeout, TimerCallback const & cb)
 {
-    timerQueue_.push(TimerSpec(now()+1000*timeout,cb));
+    timerQueue_.push(TimerSpec(now()+timeout,cb));
 }
 
 prefix_ senf::Scheduler::Scheduler()
-    : epollFd_(epoll_create(EPollInitialSize))
+    : epollFd_ (epoll_create(EPollInitialSize)), 
+      epoch_ (boost::posix_time::microsec_clock::universal_time())
 {
     if (epollFd_<0)
         throw SystemException(errno);
@@ -166,20 +166,27 @@ prefix_ void senf::Scheduler::process()
 {
     terminate_ = false;
     while (! terminate_) {
+        sched_time timeNow = now();
 
-        MicroTime timeNow = now();
         while ( ! timerQueue_.empty() && timerQueue_.top().timeout <= timeNow ) {
             timerQueue_.top().cb();
             timerQueue_.pop();
         }
+
         if (terminate_)
             return;
-        int timeout = timerQueue_.empty() ? -1 : int((timerQueue_.top().timeout - timeNow)/1000);
+
+        int timeout (MinTimeout);
+        if (! timerQueue_.empty()) {
+            sched_time delta ((timerQueue_.top().timeout - timeNow)/1000000UL);
+            if (delta<MinTimeout)
+                timeout = int(delta);
+        }
 
         struct epoll_event ev;
         int events = epoll_wait(epollFd_, &ev, 1, timeout);
         if (events<0)
-            // Hmm ... man epoll says, it will NOT return with EINTR. I hope, this is true :-)
+            // 'man epoll' says, epoll will not return with EINTR.
             throw SystemException(errno);
         if (events==0)
             // Timeout .. the handler will be run when going back to the loop top
@@ -187,8 +194,6 @@ prefix_ void senf::Scheduler::process()
 
         FdTable::iterator i = fdTable_.find(ev.data.fd);
         BOOST_ASSERT (i != fdTable_.end() );
-        // \todo Make this more efficient. Instead of copying the event-spec it should be
-        // revalidated by monitoring add/remove calls
         EventSpec spec (i->second);
 
         unsigned extraFlags (0);
index 2308705..1c1e7ef 100644 (file)
@@ -36,6 +36,15 @@ prefix_ void senf::Scheduler::terminate()
     terminate_ = true;
 }
 
+prefix_ senf::Scheduler::sched_time senf::Scheduler::now()
+    const
+{
+    boost::posix_time::time_duration delta (
+        boost::posix_time::microsec_clock::universal_time() - epoch_);
+    return sched_time( delta.ticks() )
+        * sched_time( 1000000000UL / boost::posix_time::time_duration::ticks_per_second() );
+}
+
 prefix_ int senf::retrieve_filehandle(int fd)
 {
     return fd;
index 12b4b6c..ba077e4 100644 (file)
@@ -33,8 +33,8 @@
 #include <boost/function.hpp>
 #include <boost/utility.hpp>
 #include <boost/call_traits.hpp>
-
-#include "Utils/MicroTime.hh"
+#include <boost/integer.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
 
 //#include "scheduler.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
@@ -74,7 +74,7 @@ namespace senf {
         ///////////////////////////////////////////////////////////////////////////
         // Types
 
-        /// \brief Types of file descriptor events */
+        /** \brief Types of file descriptor events */
         enum EventId { EV_NONE=0,
                        EV_READ=1, EV_PRIO=2, EV_WRITE=4, 
                        EV_ALL=7,
@@ -92,6 +92,20 @@ namespace senf {
             typedef boost::function<void (typename boost::call_traits<Handle>::param_type,
                                           EventId) > Callback;
         };
+
+        /** \brief Scheduler time data type
+            
+            Unsigned integer type representing scheduler time. Scheduler time is measured in
+            nanoseconds relative to some implementation defined reference time.
+         */
+        typedef boost::uint_fast64_t sched_time;
+
+        /** \brief Absolute time data type
+
+            Boost.DateTime datatype used to represent absolute date/time values.
+         */
+        typedef boost::posix_time::ptime abs_time;
+
         /** \brief Callback type for timer events */
         typedef boost::function<void ()> TimerCallback;
 
@@ -146,8 +160,8 @@ namespace senf {
                                              \param[in] eventMask arbitrary combination via '|'
                                                  operator of EventId designators. */
 
-        void timeout(unsigned long timeout, TimerCallback const & cb); ///< Add timeout event
-                                        /**< \param[in] timeout timeout in milliseconds
+        void timeout(sched_time timeout, TimerCallback const & cb); ///< Add timeout event
+                                        /**< \param[in] timeout timeout in nanoseconds
                                              \param[in] cb callback to call after \a timeout
                                                  milliseconds
                                              \todo Return some kind of handle/pointer and add
@@ -163,12 +177,34 @@ namespace senf {
                                              main loop to terminate. The main loop will return to
                                              it's caller after the currently running callback
                                              returns. */
+        
+        abs_time abstime(sched_time time) const; ///< Convert scheduler time to absolute time
+                                        /**< This member converts a scheduler time value into an
+                                             absolute Boost.DateTime value. 
+                                             \note You should not base timeout calculations on this
+                                                 absolute time value. Scheduler time is guaranteed
+                                                 to be monotonous, absolute time may be
+                                                 non-monotonous if the system date/time is
+                                                 changed. */
+
+        sched_time schedtime(abs_time time) const; ///< Convert absolute time to scheduler time
+                                        /**< This member converst an absolute time value into the
+                                             corresponding scheduler time.
+                                             \see abstime */
+
+        sched_time now() const;         ///< Return current date/time
+                                        /**< The return value represents the current date/time in
+                                             scheduler time representation */
+
+        sched_time eventTime() const;   ///< Return date/time of last event
 
     protected:
 
     private:
         typedef boost::function<void (EventId)> SimpleCallback;
 
+        static unsigned const MinTimeout = 1000;
+
         Scheduler();
 
         void do_add(int fd, SimpleCallback const & cb, int eventMask = EV_ALL);
@@ -190,13 +226,13 @@ namespace senf {
         struct TimerSpec
         {
             TimerSpec() : timeout(), cb() {}
-            TimerSpec(unsigned long long timeout_, TimerCallback cb_)
+            TimerSpec(sched_time timeout_, TimerCallback cb_)
                 : timeout(timeout_), cb(cb_) {}
 
             bool operator< (TimerSpec const & other) const
                 { return timeout > other.timeout; }
 
-            unsigned long long timeout;
+            sched_time timeout;
             TimerCallback cb;
         };
 
@@ -207,6 +243,7 @@ namespace senf {
         TimerQueue timerQueue_;
         int epollFd_;
         bool terminate_;
+        abs_time epoch_;
     };
 
     /** \brief Default file descriptor accessor
index f0055a5..2521b4a 100644 (file)
@@ -184,9 +184,9 @@ namespace {
         callback(handle.fd_,event);
     }
 
-    bool is_close(MicroTime a, MicroTime b)
+    bool is_close(Scheduler::sched_time a, Scheduler::sched_time b)
     {
-        return (a<b ? b-a : a-b) < 10100; // a little bit over 10ms
+        return (a<b ? b-a : a-b) < 10100000UL; // a little bit over 10ms
     }
 
 }
@@ -223,13 +223,13 @@ BOOST_AUTO_UNIT_TEST(scheduler)
     buffer[size]=0;
     BOOST_CHECK_EQUAL( buffer, "READ" );
 
-    BOOST_CHECK_NO_THROW( Scheduler::instance().timeout(100,&timeout) );
-    BOOST_CHECK_NO_THROW( Scheduler::instance().timeout(200,&timeout) );
-    MicroTime t (now());
+    BOOST_CHECK_NO_THROW( Scheduler::instance().timeout(100000000UL,&timeout) );
+    BOOST_CHECK_NO_THROW( Scheduler::instance().timeout(200000000UL,&timeout) );
+    Scheduler::sched_time t (Scheduler::instance().now());
     BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
-    BOOST_CHECK_PREDICATE( is_close, (now()) (t+100*1000) );
+    BOOST_CHECK_PREDICATE( is_close, (Scheduler::instance().now()) (t+100000000UL) );
     BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
-    BOOST_CHECK_PREDICATE( is_close, (now()) (t+200*1000) );
+    BOOST_CHECK_PREDICATE( is_close, (Scheduler::instance().now()) (t+200000000UL) );
 
     HandleWrapper handle(sock,"TheTag");
     BOOST_CHECK_NO_THROW( Scheduler::instance().add(handle,&handleCallback,Scheduler::EV_WRITE) );
diff --git a/Utils/MicroTime.hh b/Utils/MicroTime.hh
deleted file mode 100644 (file)
index c9b537c..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2006 Stefan Bund <g0dil@senf.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 MicroTime public header */
-
-/** \defgroup time Microseconds Time
-
-    MicroTime provides extremely rudimentary support for a time data
-    type precise to 10<sup>-6</sup> seconds. Up to now, the only
-    supported members are the datatype (which just uses a 64 bit
-    integer) and the now() function to get the current UTC time in
-    microseconds since the Epoch.
-
-    \idea This thing only exists as a quick hack. We can probably make
-        use of Boost.Time or some such thing so it probably does not
-        make sense to extend this further. We should however check the
-        performance of Boost.Time since this is used heavily in the
-        Scheduler.
- */
-
-#ifndef HH_MicroTime_
-#define HH_MicroTime_ 1
-
-// Custom includes
-#include <boost/cstdint.hpp>
-
-//#include "MicroTime.mpp"
-///////////////////////////////hh.p////////////////////////////////////////
-
-namespace senf {
-
-    /// \addtogroup time
-    /// @{
-
-    typedef boost::uint64_t MicroTime; ///< Microsecond accurent time datatype
-
-    MicroTime now(); ///< Get current UTC time with microsecond accuracy
-
-    /// @}
-
-}
-
-///////////////////////////////hh.e////////////////////////////////////////
-//#include "MicroTime.cci"
-//#include "MicroTime.ct"
-//#include "MicroTime.cti"
-//#include "MicroTime.mpp"
-#endif
-
-\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:
diff --git a/Utils/MicroTime.test.cc b/Utils/MicroTime.test.cc
deleted file mode 100644 (file)
index fe9e183..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2006 Stefan Bund <g0dil@senf.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.
-
-// Unit tests
-
-//#include "MicroTime.test.hh"
-//#include "MicroTime.test.ih"
-
-// Custom includes
-#include "MicroTime.hh"
-
-#include <boost/test/auto_unit_test.hpp>
-#include <boost/test/test_tools.hpp>
-
-#define prefix_
-///////////////////////////////cc.p////////////////////////////////////////
-
-BOOST_AUTO_UNIT_TEST(microTime)
-{
-    BOOST_CHECK_NO_THROW( senf::now() );
-}
-
-///////////////////////////////cc.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: