1
0
mirror of https://github.com/wfjm/w11.git synced 2026-02-06 16:55:09 +00:00

first practical version of RtimerFd

This commit is contained in:
Walter F.J. Mueller
2017-04-02 18:54:36 +02:00
parent 62bd03d422
commit e73c041309
3 changed files with 137 additions and 37 deletions

View File

@@ -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 <W.F.J.Mueller@gsi.de>
// Copyright 2013-2017 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// 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::<ctor>", "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