Skip to content

Commit

Permalink
Changed it to blocking file descriptors.
Browse files Browse the repository at this point in the history
  • Loading branch information
berndporr committed Jan 27, 2024
1 parent d08b2b2 commit 60d49aa
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 51 deletions.
67 changes: 34 additions & 33 deletions CppTimer.cpp
Original file line number Diff line number Diff line change
@@ -1,36 +1,41 @@
#include "CppTimer.h"
#include <sys/timerfd.h>

/**
* GNU GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* (C) 2020-2021, Bernd Porr <[email protected]>
* (C) 2020-2024, Bernd Porr <[email protected]>
*
* This is inspired by the timer_create man page.
* This is inspired by the timerfd_create man page.
**/

CppTimer::CppTimer(const int signo)
{
// We create a static handler catches the signal SIG
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
if (sigaction(signo, &sa, NULL) == -1)
throw("Could not create signal handler");

// Create the timer
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = signo;
// Cruical is that the signal carries the pointer to this class instance here
// because the handler just handles anything that comes in!
sev.sigev_value.sival_ptr = this;
// create the timer
if (timer_create(CLOCKID, &sev, &timerid) == -1)
throw("Could not create timer");
void CppTimer::worker() {
running = true;
while (running) {
uint64_t exp;
const long int s = read(fd, &exp, sizeof(uint64_t));
if (s != sizeof(uint64_t) ) {
running = false;
return;
}
timerEvent();
}
// disarm
struct itimerspec itsnew;
itsnew.it_value.tv_sec = 0;
itsnew.it_value.tv_nsec = 0;
itsnew.it_interval.tv_sec = 0;
itsnew.it_interval.tv_nsec = 0;
timerfd_settime(fd, 0, &itsnew, &its);
close(fd);
fd = -1;
}

void CppTimer::startns(long nanosecs, cppTimerType_t type)
{
if (running) return;
fd = timerfd_create(CLOCKID, 0);
switch (type)
{
case (PERIODIC):
Expand All @@ -48,12 +53,15 @@ void CppTimer::startns(long nanosecs, cppTimerType_t type)
its.it_interval.tv_nsec = 0;
break;
}
if (timer_settime(timerid, 0, &its, NULL) == -1)
if (timerfd_settime(fd, 0, &its, NULL) == -1)
throw("Could not start timer");
uthread = std::thread(&CppTimer::worker,this);
}

void CppTimer::startms(long millisecs, cppTimerType_t type)
{
if (running) return;
fd = timerfd_create(CLOCKID, 0);
switch (type)
{
case (PERIODIC):
Expand All @@ -71,26 +79,19 @@ void CppTimer::startms(long millisecs, cppTimerType_t type)
its.it_interval.tv_nsec = 0;
break;
}
if (timer_settime(timerid, 0, &its, NULL) == -1)
if (timerfd_settime(fd, 0, &its, NULL) == -1)
throw("Could not start timer");
uthread = std::thread(&CppTimer::worker,this);
}

void CppTimer::stop()
{
// disarm
struct itimerspec itsnew;
itsnew.it_value.tv_sec = 0;
itsnew.it_value.tv_nsec = 0;
itsnew.it_interval.tv_sec = 0;
itsnew.it_interval.tv_nsec = 0;
timer_settime(timerid, 0, &itsnew, &its);
if (!running) return;
running = false;
uthread.join();
}

CppTimer::~CppTimer()
{
stop();
// delete the timer
timer_delete(timerid);
// default action for signal handling
signal(sev.sigev_signo, SIG_IGN);
}
24 changes: 6 additions & 18 deletions CppTimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* GNU GENERAL PUBLIC LICENSE
* Version 3, 29 June 2007
*
* (C) 2020-2021, Bernd Porr <[email protected]>
* (C) 2020-2024, Bernd Porr <[email protected]>
*
* This is inspired by the timer_create man page.
**/
Expand All @@ -15,6 +15,7 @@
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <thread>

#define CLOCKID CLOCK_MONOTONIC

Expand All @@ -35,15 +36,6 @@ class CppTimer
{

public:
/**
* Creates an instance of the timer and connects the
* signal handler to the timer. The default signal which
* is being used is SIGRTMIN but can be changed to other
* signals if other processes / threads use them.
* @param signo The signal used by the timer.
**/
CppTimer(const int signo = SIGRTMIN);

/**
* Starts the timer. The timer fires first after
* the specified time in nanoseconds and then at
Expand Down Expand Up @@ -86,15 +78,11 @@ class CppTimer
virtual void timerEvent() = 0;

private:
timer_t timerid = 0;
struct sigevent sev;
struct sigaction sa;
int fd = 0;
struct itimerspec its;

inline static void handler(int, siginfo_t *si, void *)
{
(reinterpret_cast<CppTimer *>(si->si_value.sival_ptr))->timerEvent();
}
bool running = false;
std::thread uthread;
void worker();
};

#endif

0 comments on commit 60d49aa

Please sign in to comment.