Files
Renderive/Core/architecture/Timeline_Stream.cpp
T
2026-08-02 12:15:48 +08:00

85 lines
3.8 KiB
C++

#include "Timeline_Stream.h"
#include <algorithm>
#include <limits>
#include <memory_resource>
namespace renderive {
int Timeline_Stream_Snapshot::coordinate_end() const {
return coordinate_begin + visible_time_point_count - 1;
}
bool Timeline_Stream_Snapshot::coord_by_stream_tick(int stream_tick, int& coord) const {
if (times.empty())
return false;
if (stream_tick < first_stream_tick || stream_tick > last_stream_tick)
return false;
int count = static_cast<int>(times.size());
if (newest_at_axis_start)
coord = coordinate_begin + (last_stream_tick - stream_tick);
else
coord = coordinate_begin + (visible_time_point_count - count) + (stream_tick - first_stream_tick);
return coord >= coordinate_begin && coord <= coordinate_end();
}
Time_Of_Day Timeline_Stream_Snapshot::time_by_tick(int tick) const {
int offset = tick - coordinate_begin;
int count = static_cast<int>(times.size());
int index = newest_at_axis_start ? count - 1 - offset : offset - (visible_time_point_count - count);
if (index < 0 || index >= count)
return {};
return times[static_cast<std::size_t>(index)];
}
Timeline_Stream::Timeline_Stream() = default;
int Timeline_Stream::append_time(Time_Of_Day time) {
int tick = next_tick_value.fetch_add(1, std::memory_order_acq_rel);
if (tick == std::numeric_limits<int>::max()) {
int expected = std::numeric_limits<int>::min();
next_tick_value.compare_exchange_strong(expected, 1, std::memory_order_acq_rel, std::memory_order_acquire);
tick = 0;
}
{
std::lock_guard<std::mutex> lock(samples_mutex);
if (samples.size() >= Max_Buffered_Time_Count)
samples.pop_front();
samples.push_back(Sample{tick, time});
version_value.fetch_add(1, std::memory_order_release);
}
return tick;
}
Timeline_Stream_Snapshot Timeline_Stream::capture(int time_point_size, int label_tick_interval, bool start_coord_to_end_coord) const {
time_point_size = std::max(1, time_point_size);
label_tick_interval = std::max(1, label_tick_interval);
Timeline_Stream_Snapshot snapshot;
std::pmr::vector<Sample> captured;
{
std::lock_guard<std::mutex> lock(samples_mutex);
std::uint64_t version = version_value.load(std::memory_order_acquire);
snapshot.version = version + 1;
std::size_t count = std::min<std::size_t>(static_cast<std::size_t>(time_point_size), samples.size());
captured.reserve(count);
auto first = samples.end() - static_cast<std::ptrdiff_t>(count);
for (auto it = first; it != samples.end(); ++it)
captured.push_back(*it);
}
snapshot.newest_at_axis_start = start_coord_to_end_coord;
snapshot.visible_time_point_count = time_point_size;
if (captured.empty()) {
snapshot.coordinate_begin = 0;
return snapshot;
}
snapshot.first_stream_tick = captured.front().stream_tick;
snapshot.last_stream_tick = captured.back().stream_tick;
snapshot.coordinate_begin = snapshot.last_stream_tick - time_point_size + 1;
snapshot.times.reserve(captured.size());
for (const auto& sample : captured)
snapshot.times.push_back(sample.time);
snapshot.ticks.reserve(captured.size() / static_cast<std::size_t>(label_tick_interval) + 1);
for (const auto& sample : captured) {
int coord{};
if ((label_tick_interval == 1 || sample.stream_tick % label_tick_interval == 0) && snapshot.coord_by_stream_tick(sample.stream_tick, coord))
snapshot.ticks.push_back({sample.time, coord});
}
std::sort(snapshot.ticks.begin(), snapshot.ticks.end(), [](const Timeline_Label_Tick& left, const Timeline_Label_Tick& right) {
return left.coordinate < right.coordinate;
});
return snapshot;
}
}