/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2019 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
//------------------------------------------------------------------------------
// author: Georgios Bitzes
// desc: A stopwatch which measures duration of cyclic events
//------------------------------------------------------------------------------
#pragma once
#include "common/Namespace.hh"
#include
EOSCOMMONNAMESPACE_BEGIN
class SteadyClock;
//------------------------------------------------------------------------------
//! We often have the following pattern for background threads:
//! - Start of event
//! - ....
//! - End of event
//! - Sleep
//!
//! We want "event" to happen every 1 hour, for example. If the duration of
//! "event" was 10 minutes, we would want to sleep for 50 minutes before
//! starting the cycle once again. This class simplifies the above pattern,
//! essentially telling you for how long to sleep.
//------------------------------------------------------------------------------
class IntervalStopwatch {
public:
//----------------------------------------------------------------------------
//! Constructor. It's possible to pass a fake clock for testing - if none is
//! passed, a default one will be used.
//!
//! The first cycle starts as soon as the constructor is called, with the
//! given duration. (zero by default)
//----------------------------------------------------------------------------
IntervalStopwatch(std::chrono::milliseconds initialCycleDuration = std::chrono::milliseconds(0),
SteadyClock *clock = nullptr);
//----------------------------------------------------------------------------
//! Start a cycle from this point onwards, with the given duration.
//! The previously running cycle is discarded.
//----------------------------------------------------------------------------
void startCycle(std::chrono::milliseconds duration);
//----------------------------------------------------------------------------
//! Get timepoint of cycle start
//----------------------------------------------------------------------------
std::chrono::steady_clock::time_point getCycleStart() const;
//----------------------------------------------------------------------------
//! Return how much time has elapsed within this cycle, ie milliseconds since
//! startCycle was called.
//----------------------------------------------------------------------------
std::chrono::milliseconds timeIntoCycle() const;
//----------------------------------------------------------------------------
//! Return how much time is remaining in this cycle. If more time has elapsed
//! than the cycle duration, this function returns 0.
//----------------------------------------------------------------------------
std::chrono::milliseconds timeRemainingInCycle() const;
//----------------------------------------------------------------------------
//! Convenience function - if the cycle has expired:
//! - Restart from this point on, with the same exact duration.
//! - Return true.
//! Else, return false and do nothing else.
//----------------------------------------------------------------------------
bool restartIfExpired();
private:
SteadyClock *mClock; //< The internal clock object of this class, can be null.
std::chrono::steady_clock::time_point mCycleStart; //< The point at which the
//< current cycle started
std::chrono::milliseconds mCycleDuration; //< The current duration
};
EOSCOMMONNAMESPACE_END