powerd++  0.4.4
Public Member Functions | Private Types | Private Attributes | List of all members
timing::Cycle Class Reference

Implements an interruptible cyclic sleeping functor. More...

#include <Cycle.hpp>

Public Member Functions

bool operator() () const
 Completes an interrupted sleep cycle. More...
 
template<class... DurTraits>
bool operator() (std::chrono::duration< DurTraits... > const &cycleTime)
 Sleep for the time required to complete the given cycle time. More...
 

Private Types

using clock = std::chrono::steady_clock
 Use steady_clock, avoid time jumps.
 
using us = std::chrono::microseconds
 Shorthand for microseconds.
 

Private Attributes

std::chrono::time_point< clockclk = clock::now()
 The current time clock. More...
 

Detailed Description

Implements an interruptible cyclic sleeping functor.

Cyclic sleeping means that instead of having a fixed sleeping time, each sleep is timed to meet a fixed wakeup time. I.e. the waking rhythm does not drift with changing system loads.

The canonical way to do this in C++ is like this:

#include <chrono>
#include <thread>
int main() {
std::chrono::milliseconds const ival{500};
auto time = std::chrono::steady_clock::now();
while (…something…) {
std::this_thread::sleep_until(time += ival);
…do stuff…
}
return 0;
}

The issue is that you might want to install a signal handler to guarantee stack unwinding and sleep_until() will resume its wait after the signal handler completes.

The Cycle class offers you an interruptible sleep:

#include "Cycle.hpp"
#include <csignal>
…signal handlers…
int main() {
std::chrono::milliseconds const ival{500};
…setup some signal handlers…
while (…something… && sleep(ival)) {
…do stuff…
}
return 0;
}

In the example the while loop is terminated if the sleep() is interrupted by a signal. Optionally the sleep cycle can be resumed:

while (…something…) {
if (!sleep(ival)) {
…interrupted…
while (!sleep());
}
…do stuff…
}

Note there was a design decision between providing a cycle time to the constructor or providing it every cycle. The latter was chosen so the cycle time can be adjusted.

Member Function Documentation

◆ operator()() [1/2]

bool timing::Cycle::operator() ( ) const
inline

Completes an interrupted sleep cycle.

I.e. if the last sleep cycle was 500 ms and the sleep was interrupted 300 ms into the cycle, this would sleep for the remaining 200 ms unless interrupted.

Return values
trueSleep completed uninterrupted
falseSleep was interrupted

◆ operator()() [2/2]

template<class... DurTraits>
bool timing::Cycle::operator() ( std::chrono::duration< DurTraits... > const &  cycleTime)
inline

Sleep for the time required to complete the given cycle time.

I.e. if the time since the last sleep cycle was 12 ms and the given cycleTime was 500 ms, the actual sleeping time would be 488 ms.

Template Parameters
DurTraitsThe traits of the duration type
Parameters
cycleTimeThe duration of the cycle to complete
Return values
trueCommand completed uninterrupted
falseCommand was interrupted

Member Data Documentation

◆ clk

std::chrono::time_point<clock> timing::Cycle::clk = clock::now()
private

The current time clock.


The documentation for this class was generated from the following file:
anonymous_namespace{libloadplay.cpp}::main
class anonymous_namespace{libloadplay.cpp}::Main main
Sole instance of Main.
Cycle.hpp
Implements timing::Cycle, a cyclic sleep functor.
timing::Cycle
Implements an interruptible cyclic sleeping functor.
Definition: Cycle.hpp:82
clas::ival
types::ms ival(char const *const str)
Convert string to time interval in milliseconds.
Definition: clas.cpp:217