blob: 485030dbfe4083db6cf8e104b38ce162c243730f [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COBALT_UTIL_CLOCK_H_
#define COBALT_UTIL_CLOCK_H_
#include <chrono>
#include <iomanip>
#include <sstream>
#include <string>
namespace cobalt {
namespace util {
// Allows us to mock out a clock for tests.
class ClockInterface {
public:
virtual ~ClockInterface() = default;
virtual std::chrono::system_clock::time_point now() = 0;
};
// A clock that returns the real system time.
class SystemClock : public ClockInterface {
public:
std::chrono::system_clock::time_point now() override {
return std::chrono::system_clock::now();
}
};
// A clock that returns an incrementing sequence of tics each time it is called.
// Optionally a callback may be set that will be invoked each time the
// clock ticks.
class IncrementingClock : public ClockInterface {
public:
IncrementingClock() {}
// Constructs an IncrementingClock which increments by |increment| seconds
// each time it is called.
explicit IncrementingClock(std::chrono::system_clock::duration increment)
: increment_(increment) {}
std::chrono::system_clock::time_point now() override {
time_ += increment_;
if (callback_) {
callback_(time_);
}
return time_;
}
// Return the current value of time_ without advancing time.
std::chrono::system_clock::time_point peek_now() { return time_; }
// Set the value by which the clock is incremented each time it is called.
void set_increment(std::chrono::system_clock::duration increment) {
increment_ = increment;
}
// Increment the clock's current time once.
void increment_by(std::chrono::system_clock::duration increment) {
time_ += increment;
if (callback_) {
callback_(time_);
}
}
void set_time(std::chrono::system_clock::time_point t) { time_ = t; }
void set_callback(
std::function<void(std::chrono::system_clock::time_point)> c) {
callback_ = c;
}
std::string DebugString() {
std::ostringstream stream;
std::time_t now = std::chrono::system_clock::to_time_t(time_);
stream << "time: " << std::put_time(std::localtime(&now), "%F %T") << "\n";
return stream.str();
}
private:
std::chrono::system_clock::time_point time_ =
std::chrono::system_clock::time_point(
std::chrono::system_clock::duration(0));
std::chrono::system_clock::duration increment_ =
std::chrono::system_clock::duration(1);
std::function<void(std::chrono::system_clock::time_point)> callback_;
};
} // namespace util
} // namespace cobalt
#endif // COBALT_UTIL_CLOCK_H_