/** Run tasks periodically. * * @file * @author Steffen Vogel <svogel2@eonerc.rwth-aachen.de> * @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC * @license Apache License 2.0 *********************************************************************************/ #pragma once #include <cstdio> #include <cstdint> #include <ctime> /** We can choose between two periodic task implementations */ //#define PERIODIC_TASK_IMPL NANOSLEEP #define TIMERFD 1 #define CLOCK_NANOSLEEP 2 #define NANOSLEEP 3 #define RDTSC 4 #if defined(__MACH__) #define PERIODIC_TASK_IMPL NANOSLEEP #elif defined(__linux__) #define PERIODIC_TASK_IMPL TIMERFD #else #error "Platform not supported" #endif #if PERIODIC_TASK_IMPL == RDTSC #include <villas/tsc.hpp> #endif struct Task { int clock; /**< CLOCK_{MONOTONIC,REALTIME} */ #if PERIODIC_TASK_IMPL == RDTSC /* We use cycle counts in RDTSC mode */ uint64_t period; uint64_t next; #else struct timespec period; /**< The period of periodic invations of this task */ struct timespec next; /**< The timer value for the next invocation */ #endif #if PERIODIC_TASK_IMPL == TIMERFD int fd; /**< The timerfd_create(2) file descriptior. */ #elif PERIODIC_TASK_IMPL == RDTSC struct Tsc tsc; /**< Initialized by tsc_init(). */ #endif /** Create a new task with the given rate. */ Task(int clock = CLOCK_REALTIME); ~Task(); /** Wait until task elapsed * * @retval 0 An error occured. Maybe the task was stopped. * @retval >0 The nummer of runs this task already fired. */ uint64_t wait(); void setNext(const struct timespec *next); void setTimeout(double to); void setRate(double rate); void stop(); /** Returns a poll'able file descriptor which becomes readable when the timer expires. * * Note: currently not supported on all platforms. */ int getFD() const; };