88 lines
2.3 KiB
C++
88 lines
2.3 KiB
C++
#include "global.ipp"
|
|
|
|
#include "time_thread/Timer_Service.hpp"
|
|
|
|
#include <exception>
|
|
#include <utility>
|
|
|
|
namespace aethera {
|
|
Throttled_Latest_only::Private::Private(
|
|
proxy<FP_Scene> scene,
|
|
proxy<FP_Sink> sink) :
|
|
state(std::make_shared<detail::Throttled_Latest_Only_State>(
|
|
std::move(scene),
|
|
std::move(sink))) {}
|
|
|
|
Throttled_Latest_only::Throttled_Latest_only(
|
|
proxy<FP_Scene> scene,
|
|
proxy<FP_Sink> sink) :
|
|
d(std::make_unique<Private>(std::move(scene), std::move(sink))) {}
|
|
|
|
Throttled_Latest_only::~Throttled_Latest_only() noexcept {
|
|
if (!d->state->destructible()) {
|
|
std::terminate();
|
|
}
|
|
}
|
|
|
|
Start_Throttled_Latest_Only_Result
|
|
Throttled_Latest_only::start(double frames_per_second) {
|
|
const auto interval =
|
|
detail::timer_interval_from_frames_per_second(frames_per_second);
|
|
if (!interval) {
|
|
return interval.error() ==
|
|
Schedule_Every_Fps_Result::invalid_frames_per_second
|
|
? Start_Throttled_Latest_Only_Result::invalid_frames_per_second
|
|
: Start_Throttled_Latest_Only_Result::interval_out_of_range;
|
|
}
|
|
|
|
const auto prepared = d->state->prepare_start();
|
|
if (prepared != Start_Throttled_Latest_Only_Result::started) {
|
|
return prepared;
|
|
}
|
|
|
|
const auto state = d->state;
|
|
Timer_Id timer_id{};
|
|
try {
|
|
timer_id =
|
|
Timer_Service::instance().schedule_every(
|
|
*interval,
|
|
[state] {
|
|
state->frame_due();
|
|
});
|
|
}
|
|
catch (...) {
|
|
state->start_failed();
|
|
throw;
|
|
}
|
|
state->timer_started(timer_id);
|
|
return Start_Throttled_Latest_Only_Result::started;
|
|
}
|
|
|
|
Stop_Throttled_Latest_Only_Result
|
|
Throttled_Latest_only::stop(
|
|
Throttled_Latest_Only_Stop_Completion completion) {
|
|
auto request = d->state->request_stop(std::move(completion));
|
|
if (request.result !=
|
|
Stop_Throttled_Latest_Only_Result::stopping) {
|
|
return request.result;
|
|
}
|
|
if (!request.timer_id) {
|
|
std::terminate();
|
|
}
|
|
|
|
try {
|
|
const auto state = d->state;
|
|
Timer_Service::instance().cancel(
|
|
*request.timer_id,
|
|
[state] {
|
|
state->timer_cancelled();
|
|
});
|
|
}
|
|
catch (...) {
|
|
d->state->cancel_failed();
|
|
throw;
|
|
}
|
|
return Stop_Throttled_Latest_Only_Result::stopping;
|
|
}
|
|
}
|