diff --git a/tools/src/librlink/RtimerFd.cpp b/tools/src/librlink/RtimerFd.cpp index 7e7364c5..f5caa2a7 100644 --- a/tools/src/librlink/RtimerFd.cpp +++ b/tools/src/librlink/RtimerFd.cpp @@ -1,6 +1,6 @@ -// $Id: RtimerFd.cpp 488 2013-02-16 18:49:47Z mueller $ +// $Id: RtimerFd.cpp 852 2017-02-18 12:43:31Z mueller $ // -// Copyright 2013- by Walter F.J. Mueller +// Copyright 2013-2017 by Walter F.J. Mueller // // This program is free software; you may redistribute and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -13,12 +13,13 @@ // // Revision History: // Date Rev Version Comment -// 2013-01-11 473 1.0 Initial version +// 2017-02-18 852 1.0 Initial version +// 2013-01-11 473 0.1 First draft // --------------------------------------------------------------------------- /*! \file - \version $Id: RtimerFd.cpp 488 2013-02-16 18:49:47Z mueller $ + \version $Id: RtimerFd.cpp 852 2017-02-18 12:43:31Z mueller $ \brief Implemenation of class RtimerFd. */ @@ -44,37 +45,109 @@ namespace Retro { //! FIXME_docs RtimerFd::RtimerFd() -{ - fFd = timerfd_create(CLOCK_MONOTONIC,0); // use MONOTONIC; no flags - if (fFd < 0) - throw Rexception("RtimerFd::", "timerfd() failed: ", errno); -} + : fFd(-1) +{} //------------------------------------------+----------------------------------- //! FIXME_docs RtimerFd::~RtimerFd() { - close(fFd); + Close(); } //------------------------------------------+----------------------------------- //! FIXME_docs -void RtimerFd::SetRelTimer(boost::posix_time::time_duration interval, - boost::posix_time::time_duration initial) +void RtimerFd::Open(clockid_t clkid) { - itimerspec its; - itimerspec old; - long sf = 1000000000/interval.ticks_per_second(); - its.it_interval.tv_sec = interval.total_seconds(); - its.it_interval.tv_nsec = interval.fractional_seconds() * sf; - its.it_value.tv_sec = initial.total_seconds(); - its.it_value.tv_nsec = initial.fractional_seconds() * sf; - int irc = timerfd_settime(fFd, 0, &its, &old); - if (irc < 0) - throw Rexception("RtimerFd::SetRelTimer()", "timerfd() failed: ", errno); + if (IsOpen()) + throw Rexception("RtimerFd::Open()", "bad state: already open"); + + fFd = ::timerfd_create(clkid, TFD_NONBLOCK); + if (!IsOpen()) + throw Rexception("RtimerFd::Open()", "timerfd_create() failed: ", errno); return; } +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void RtimerFd::Close() +{ + if (IsOpen()) { + ::close(fFd); + fFd = -1; + } + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void RtimerFd::SetRelative(const Rtime& dt) +{ + if (!IsOpen()) + throw Rexception("RtimerFd::SetRelative()", "bad state: not open"); + + if (dt.Sec() <= 0 || dt.NSec() <= 0) + throw Rexception("RtimerFd::SetRelative()", + "bad value: dt zero or negative "); + + struct itimerspec itspec; + itspec.it_interval.tv_sec = 0; + itspec.it_interval.tv_nsec = 0; + itspec.it_value = dt.Timespec(); + + if (::timerfd_settime(fFd, 0, &itspec, nullptr) < 0) + throw Rexception("RtimerFd::SetRelative()", + "timerfd_settime() failed: ", errno); + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +void RtimerFd::Cancel() +{ + if (!IsOpen()) + throw Rexception("RtimerFd::Cancel()", "bad state: not open"); + + struct itimerspec itspec; + itspec.it_interval.tv_sec = 0; + itspec.it_interval.tv_nsec = 0; + itspec.it_value.tv_sec = 0; + itspec.it_value.tv_nsec = 0; + + // cancel running timers + if (::timerfd_settime(fFd, 0, &itspec, nullptr) < 0) + throw Rexception("RtimerFd::Cancel()", + "timerfd_settime() failed: ", errno); + + // clear aready experied timers + uint64_t cnt; + int irc = ::read(fFd, &cnt, sizeof(cnt)); + if (irc < 0 && errno != EAGAIN) + throw Rexception("RtimerFd::Cancel()", "read() failed: ", errno); + + return; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +uint64_t RtimerFd::Read() +{ + if (!IsOpen()) + throw Rexception("RtimerFd::Read()", "bad state: not open"); + + uint64_t cnt; + int irc = ::read(fFd, &cnt, sizeof(cnt)); + if (irc < 0) { + if (errno == EAGAIN) return 0; + throw Rexception("RtimerFd::Read()", "read() failed: ", errno); + } + return cnt; +} + } // end namespace Retro diff --git a/tools/src/librlink/RtimerFd.hpp b/tools/src/librlink/RtimerFd.hpp index 508911fe..a6a1d9d2 100644 --- a/tools/src/librlink/RtimerFd.hpp +++ b/tools/src/librlink/RtimerFd.hpp @@ -1,6 +1,6 @@ -// $Id: RtimerFd.hpp 486 2013-02-10 22:34:43Z mueller $ +// $Id: RtimerFd.hpp 852 2017-02-18 12:43:31Z mueller $ // -// Copyright 2013- by Walter F.J. Mueller +// Copyright 2013-2017 by Walter F.J. Mueller // // This program is free software; you may redistribute and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -13,21 +13,26 @@ // // Revision History: // Date Rev Version Comment -// 2013-01-11 473 1.0 Initial version +// 2017-02-18 852 1.0 Initial version +// 2013-01-11 473 0.1 First draft // --------------------------------------------------------------------------- /*! \file - \version $Id: RtimerFd.hpp 486 2013-02-10 22:34:43Z mueller $ + \version $Id: RtimerFd.hpp 852 2017-02-18 12:43:31Z mueller $ \brief Declaration of class \c RtimerFd. */ #ifndef included_Retro_RtimerFd #define included_Retro_RtimerFd 1 +#include + #include "boost/utility.hpp" -#include "boost/date_time/posix_time/posix_time_types.hpp" + +#include "librtools/Rtime.hpp" + namespace Retro { @@ -36,11 +41,16 @@ namespace Retro { RtimerFd(); virtual ~RtimerFd(); - int Fd() const; - void SetRelTimer(boost::posix_time::time_duration interval, - boost::posix_time::time_duration initial); + void Open(clockid_t clkid=CLOCK_MONOTONIC); + bool IsOpen() const; + void Close(); + void SetRelative(const Rtime& dt); + void SetRelative(double dt); + void Cancel(); + uint64_t Read(); - operator int() const; + int Fd() const; + explicit operator bool() const; protected: diff --git a/tools/src/librlink/RtimerFd.ipp b/tools/src/librlink/RtimerFd.ipp index c15fd31a..f321b8aa 100644 --- a/tools/src/librlink/RtimerFd.ipp +++ b/tools/src/librlink/RtimerFd.ipp @@ -1,6 +1,6 @@ -// $Id: RtimerFd.ipp 488 2013-02-16 18:49:47Z mueller $ +// $Id: RtimerFd.ipp 851 2017-02-18 09:20:40Z mueller $ // -// Copyright 2013- by Walter F.J. Mueller +// Copyright 2013-2017 by Walter F.J. Mueller // // This program is free software; you may redistribute and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -13,12 +13,13 @@ // // Revision History: // Date Rev Version Comment -// 2013-01-11 473 1.0 Initial version +// 2017-02-18 851 1.0 Initial version +// 2013-01-11 473 0.1 First draft // --------------------------------------------------------------------------- /*! \file - \version $Id: RtimerFd.ipp 488 2013-02-16 18:49:47Z mueller $ + \version $Id: RtimerFd.ipp 851 2017-02-18 09:20:40Z mueller $ \brief Implemenation (inline) of class RtimerFd. */ @@ -28,6 +29,22 @@ namespace Retro { //------------------------------------------+----------------------------------- //! FIXME_docs +inline bool RtimerFd::IsOpen() const +{ + return fFd >= 0; +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + +inline void RtimerFd::SetRelative(double dt) +{ + return SetRelative(Rtime(dt)); +} + +//------------------------------------------+----------------------------------- +//! FIXME_docs + inline int RtimerFd::Fd() const { return fFd; @@ -36,9 +53,9 @@ inline int RtimerFd::Fd() const //------------------------------------------+----------------------------------- //! FIXME_docs -inline RtimerFd::operator int() const +inline RtimerFd::operator bool() const { - return fFd; + return IsOpen(); } } // end namespace Retro