Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_compile_definitions(CF_DEBUG)
endif()

add_library(Caffeine INTERFACE)
target_include_directories(Caffeine INTERFACE
add_library(Caffeine
src/core/Timer.cpp
)

target_include_directories(Caffeine PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:include>
)

target_compile_features(Caffeine PUBLIC cxx_std_20)

add_library(Caffeine::Core ALIAS Caffeine)

add_subdirectory(tests)
76 changes: 76 additions & 0 deletions src/core/Timer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include "Timer.hpp"
#include <chrono>

namespace Caffeine::Core {

static TimePoint getCurrentTimePoint() {
auto now = std::chrono::high_resolution_clock::now();
auto elapsed = now.time_since_epoch();
u64 nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed).count();
return TimePoint(nanos);
}

Timer::Timer()
: m_is_running(false), m_accumulated_ticks(0) {
}

Timer::~Timer() {
}

void Timer::start() {
if (!m_is_running) {
m_start_time = getCurrentTimePoint();
m_is_running = true;
}
}

void Timer::stop() {
if (m_is_running) {
m_stop_time = getCurrentTimePoint();
u64 ticks = m_stop_time.ticks - m_start_time.ticks;
m_accumulated_ticks += ticks;
m_is_running = false;
}
}

void Timer::reset() {
m_accumulated_ticks = 0;
m_start_time.ticks = 0;
m_stop_time.ticks = 0;
m_is_running = false;
}

Duration Timer::elapsed() const {
if (m_is_running) {
TimePoint current = getCurrentTimePoint();
u64 ticks = current.ticks - m_start_time.ticks + m_accumulated_ticks;
return Duration::fromNanos(static_cast<double>(ticks));
} else {
return Duration::fromNanos(static_cast<double>(m_accumulated_ticks));
}
}

Duration Timer::tick() {
if (m_is_running) {
TimePoint current = getCurrentTimePoint();
u64 ticks = current.ticks - m_start_time.ticks;
m_start_time = current;
return Duration::fromNanos(static_cast<double>(ticks));
}
return Duration::fromSeconds(0.0);
}

bool Timer::isRunning() const {
return m_is_running;
}

ScopeTimer::ScopeTimer(const char* name)
: m_name(name) {
m_timer.start();
}

ScopeTimer::~ScopeTimer() {
m_timer.stop();
}

}
154 changes: 154 additions & 0 deletions src/core/Timer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#pragma once

#include "../core/Types.hpp"

namespace Caffeine::Core {

struct TimePoint {
u64 ticks = 0;

TimePoint() = default;
explicit TimePoint(u64 t) : ticks(t) {}

bool operator<(const TimePoint& other) const {
return ticks < other.ticks;
}

bool operator<=(const TimePoint& other) const {
return ticks <= other.ticks;
}

bool operator>(const TimePoint& other) const {
return ticks > other.ticks;
}

bool operator>=(const TimePoint& other) const {
return ticks >= other.ticks;
}

bool operator==(const TimePoint& other) const {
return ticks == other.ticks;
}

bool operator!=(const TimePoint& other) const {
return ticks != other.ticks;
}
};

struct Duration {
f64 seconds = 0.0;

Duration() = default;
explicit Duration(f64 s) : seconds(s) {}

static Duration fromSeconds(f64 s) {
return Duration(s);
}

static Duration fromMillis(f64 ms) {
return Duration(ms / 1000.0);
}

static Duration fromMicros(f64 us) {
return Duration(us / 1000000.0);
}

static Duration fromNanos(f64 ns) {
return Duration(ns / 1000000000.0);
}

f64 millis() const {
return seconds * 1000.0;
}

f64 micros() const {
return seconds * 1000000.0;
}

f64 nanos() const {
return seconds * 1000000000.0;
}

Duration operator+(const Duration& other) const {
return Duration(seconds + other.seconds);
}

Duration operator-(const Duration& other) const {
return Duration(seconds - other.seconds);
}

Duration operator*(f64 scalar) const {
return Duration(seconds * scalar);
}

friend Duration operator*(f64 scalar, const Duration& d) {
return Duration(scalar * d.seconds);
}

Duration operator/(f64 scalar) const {
return Duration(seconds / scalar);
}

bool operator<(const Duration& other) const {
return seconds < other.seconds;
}

bool operator<=(const Duration& other) const {
return seconds <= other.seconds;
}

bool operator>(const Duration& other) const {
return seconds > other.seconds;
}

bool operator>=(const Duration& other) const {
return seconds >= other.seconds;
}

bool operator==(const Duration& other) const {
const f64 epsilon = 1e-15;
return (seconds - other.seconds) < epsilon && (seconds - other.seconds) > -epsilon;
}

bool operator!=(const Duration& other) const {
return !(*this == other);
}
};

inline Duration operator-(const TimePoint& a, const TimePoint& b) {
u64 tick_diff = (a.ticks > b.ticks) ? (a.ticks - b.ticks) : (b.ticks - a.ticks);
return Duration::fromSeconds(static_cast<f64>(tick_diff) / 1000000.0);
}

class Timer {
public:
Timer();
~Timer();

void start();
void stop();
void reset();

Duration elapsed() const;
Duration tick();

bool isRunning() const;

private:
TimePoint m_start_time;
TimePoint m_stop_time;
u64 m_accumulated_ticks;
bool m_is_running;
};

class ScopeTimer {
public:
explicit ScopeTimer(const char* name);
~ScopeTimer();

private:
const char* m_name;
Timer m_timer;
};

}
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ add_executable(CaffeineTest
test_containers.cpp
test_math.cpp
test_core.cpp
test_timer.cpp
)

target_link_libraries(CaffeineTest PRIVATE Caffeine)
Expand Down
Loading
Loading