Skip to content

Commit

Permalink
Introduce system/phase timers
Browse files Browse the repository at this point in the history
Close: #181
  • Loading branch information
AndreasLrx committed Nov 22, 2024
1 parent e1fcd84 commit 5ab85cc
Show file tree
Hide file tree
Showing 8 changed files with 490 additions and 8 deletions.
5 changes: 4 additions & 1 deletion src/ecstasy/registry/Registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ namespace ecstasy

void Registry::runSystem(const std::type_index &systemId)
{
_systems.get(systemId).run(*this);
ISystem &system = _systems.get(systemId);

if (system.getTimer().trigger())
system.run(*this);
}

void Registry::runSystems()
Expand Down
2 changes: 2 additions & 0 deletions src/ecstasy/system/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ set(SRC
${INCROOT}/Pipeline.hpp
${SRCROOT}/Pipeline.cpp
${INCROOT}/ISystem.hpp
${INCROOT}/Timer.hpp
${SRCROOT}/Timer.cpp
PARENT_SCOPE
)
38 changes: 38 additions & 0 deletions src/ecstasy/system/ISystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#ifndef ECSTASY_SYSTEM_ISYSTEM_HPP_
#define ECSTASY_SYSTEM_ISYSTEM_HPP_

#include "ecstasy/system/Timer.hpp"

namespace ecstasy
{
/// @brief Forward declaration of Registry class.
Expand All @@ -37,6 +39,42 @@ namespace ecstasy
/// @since 1.0.0 (2022-10-17)
///
virtual void run(Registry &registry) = 0;

///
/// @brief Get the system timer.
///
/// @note The timer is used to control the execution of the system. You can also use
/// @ref ecstasy::Pipeline::Phase "Phase" scale timers.
///
/// @return Timer& Reference to the system timer.
///
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-11-22)
///
[[nodiscard]] constexpr Timer &getTimer() noexcept
{
return _timer;
}

///
/// @brief Get the system timer.
///
/// @note The timer is used to control the execution of the system. You can also use
/// @ref ecstasy::Pipeline::Phase "Phase" scale timers.
///
/// @return const Timer& Reference to the system timer.
///
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-11-22)
///
[[nodiscard]] constexpr const Timer &getTimer() const noexcept
{
return _timer;
}

private:
/// @brief Timer to control the execution of the system.
Timer _timer;
};
} // namespace ecstasy

Expand Down
8 changes: 5 additions & 3 deletions src/ecstasy/system/Pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ namespace ecstasy
return _pipeline._systemsIds.begin() + static_cast<long>(end_idx());
}

void Pipeline::Phase::run() const
void Pipeline::Phase::run()
{
if (!_timer.trigger())
return;
for (auto it = begin(); it < end(); ++it) {
_pipeline._registry.runSystem(*it);
}
Expand Down Expand Up @@ -54,14 +56,14 @@ namespace ecstasy
}
}

void Pipeline::run() const
void Pipeline::run()
{
for (auto &phase : _phases) {
phase.second.run();
}
}

void Pipeline::run(Pipeline::PhaseId phase) const
void Pipeline::run(Pipeline::PhaseId phase)
{
auto phaseIt = _phases.find(phase);

Expand Down
49 changes: 45 additions & 4 deletions src/ecstasy/system/Pipeline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <typeindex>
#include <vector>
#include "ecstasy/system/ISystem.hpp"
#include "ecstasy/system/Timer.hpp"

namespace ecstasy
{
Expand Down Expand Up @@ -72,7 +73,7 @@ namespace ecstasy
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-11-21)
///
constexpr Phase(Pipeline &pipeline, PhaseId id) : _pipeline(pipeline), _begin(), _size(0), _id(id)
Phase(Pipeline &pipeline, PhaseId id) : _pipeline(pipeline), _begin(), _size(0), _id(id)
{
}

Expand All @@ -83,7 +84,7 @@ namespace ecstasy
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-11-21)
///
void run() const;
void run();

///
/// @brief Get the number of systems in this phase.
Expand Down Expand Up @@ -132,6 +133,44 @@ namespace ecstasy
///
[[nodiscard]] SystemIterator end() const noexcept;

///
/// @brief Get the phase timer.
///
/// @note The timer is used to control the execution of the phase. You can also use
/// @ref ecstasy::ISystem "ISystem" scale timers.
///
/// @warning Rate limiting both the phase and the systems will result in multiplied timers (not added).
/// However interval timers will be cumulative.
///
/// @return Timer& Reference to the system timer.
///
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-11-22)
///
[[nodiscard]] constexpr Timer &getTimer() noexcept
{
return _timer;
}

///
/// @brief Get the phase timer.
///
/// @note The timer is used to control the execution of the phase. You can also use
/// @ref ecstasy::ISystem "ISystem" scale timers.
///
/// @warning Rate limiting both the phase and the systems will result in multiplied timers (not added).
/// However interval timers will be cumulative.
///
/// @return const Timer& Reference to the system timer.
///
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-11-22)
///
[[nodiscard]] constexpr const Timer &getTimer() const noexcept
{
return _timer;
}

private:
/// @brief Owning pipeline.
Pipeline &_pipeline;
Expand All @@ -141,6 +180,8 @@ namespace ecstasy
std::size_t _size;
/// @brief Identifier of the phase.
PhaseId _id;
/// @brief Timer to control the execution of the phase.
Timer _timer;

///
/// @brief Get the index of the first system in this phase.
Expand Down Expand Up @@ -266,7 +307,7 @@ namespace ecstasy
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-11-21)
///
void run() const;
void run();

///
/// @brief Run a specific phase of the pipeline.
Expand All @@ -276,7 +317,7 @@ namespace ecstasy
/// @author Andréas Leroux ([email protected])
/// @since 1.0.0 (2024-11-21)
///
void run(PhaseId phase) const;
void run(PhaseId phase);

private:
/// @brief Ordered list of systems.
Expand Down
88 changes: 88 additions & 0 deletions src/ecstasy/system/Timer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
///
/// @file Timer.cpp
/// @author Andréas Leroux ([email protected])
/// @brief
/// @version 1.0.0
/// @date 2024-11-21
///
/// @copyright Copyright (c) ECSTASY 2022 - 2024
///
///

#include "Timer.hpp"
#include <stdexcept>

namespace ecstasy
{
Timer::Timer()
{
_lastTrigger = TimePoint::min();
setRate(0);
}

Timer::Timer(Timer::Interval interval) : Timer()
{
setInterval(interval);
}

Timer::Timer(std::uint32_t rate) : Timer()
{
setRate(rate);
}

void Timer::setRate(std::uint32_t rate) noexcept
{
_type = Type::Rate;
if (rate == 0) {
rate = 1;
}
_rate.rate = rate;
// Reset the countdown to trigger to run the first time
_rate.triggerCountdown = 0;
}

std::uint32_t Timer::getRate() const
{
if (_type != Type::Rate)
throw std::runtime_error("Timer is not of type Rate");
return _rate.rate;
}

void Timer::setInterval(Timer::Interval interval) noexcept
{
_type = Type::TimeInterval;
_timer.interval = interval;
}

Timer::Interval Timer::getInterval() const
{
if (_type != Type::TimeInterval)
throw std::runtime_error("Timer is not of type Rate");
return _timer.interval;
}

bool Timer::trigger() noexcept
{
switch (_type) {
case Type::TimeInterval: {
auto tp = std::chrono::system_clock::now();

if (tp - _timer.interval >= _lastTrigger) {
_lastTrigger = tp;
return true;
}
return false;
}
case Type::Rate: {
if (_rate.triggerCountdown == 0) {
_rate.triggerCountdown = _rate.rate - 1;
_lastTrigger = std::chrono::system_clock::now();
return true;
}
--_rate.triggerCountdown;
return false;
}
}
return false;
}
} // namespace ecstasy
Loading

0 comments on commit 5ab85cc

Please sign in to comment.