Files
Renderive/Core/architecture/Timeline_Stream.cpp
T
2026-08-01 20:09:45 +08:00

86 lines
3.8 KiB
C++

#include "Timeline_Stream.h"
#include <algorithm>
#include <limits>
#include <memory_resource>
namespace renderive {
int Timeline_Stream_Snapshot::upper() const {
return lower + time_point_size - 1;
}
bool Timeline_Stream_Snapshot::coord_by_stream_tick(int stream_tick, int& coord) const {
if (times.empty())
return false;
if (stream_tick < lower_stream_tick || stream_tick > upper_stream_tick)
return false;
int count = static_cast<int>(times.size());
if (start_coord_to_end_coord)
coord = lower + (upper_stream_tick - stream_tick);
else
coord = lower + (time_point_size - count) + (stream_tick - lower_stream_tick);
return coord >= lower && coord <= upper();
}
Time_Of_Day Timeline_Stream_Snapshot::time_by_tick(int tick) const {
int offset = tick - lower;
int count = static_cast<int>(times.size());
int index = start_coord_to_end_coord ? count - 1 - offset : offset - (time_point_size - count);
if (index < 0 || index >= count)
return {};
return times[static_cast<std::size_t>(index)];
}
Timeline_Stream::Timeline_Stream() = default;
int Timeline_Stream::push_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::uint64_t sequence = write_sequence.fetch_add(1, std::memory_order_acq_rel);
auto sample = std::make_shared<Sample>(Sample{sequence, tick, time});
time_slots[sequence % Max_Buffered_Time_Count].store(std::move(sample), std::memory_order_release);
return tick;
}
Timeline_Stream_Snapshot Timeline_Stream::capture(int time_point_size, int tick_space, bool start_coord_to_end_coord) const {
time_point_size = std::max(1, time_point_size);
tick_space = std::max(1, tick_space);
Timeline_Stream_Snapshot snapshot;
std::uint64_t write = write_sequence.load(std::memory_order_acquire);
snapshot.version = write + 1;
snapshot.start_coord_to_end_coord = start_coord_to_end_coord;
snapshot.time_point_size = time_point_size;
if (write == 0) {
snapshot.lower = 0;
return snapshot;
}
std::uint64_t available = std::min<std::uint64_t>(write, Max_Buffered_Time_Count);
std::uint64_t count = std::min<std::uint64_t>(static_cast<std::uint64_t>(time_point_size), available);
std::uint64_t first_sequence = write - count;
std::pmr::vector<Sample> samples;
samples.reserve(static_cast<std::size_t>(count));
for (std::uint64_t sequence = first_sequence; sequence < write; ++sequence) {
auto sample = time_slots[sequence % Max_Buffered_Time_Count].load(std::memory_order_acquire);
if (sample && sample->sequence == sequence)
samples.push_back(*sample);
}
if (samples.empty()) {
snapshot.lower = 0;
return snapshot;
}
snapshot.lower_stream_tick = samples.front().tick;
snapshot.upper_stream_tick = samples.back().tick;
snapshot.lower = snapshot.upper_stream_tick - time_point_size + 1;
snapshot.times.reserve(samples.size());
for (const auto& sample : samples)
snapshot.times.push_back(sample.time);
snapshot.ticks.reserve(samples.size() / static_cast<std::size_t>(tick_space) + 1);
for (const auto& sample : samples) {
int coord{};
if ((tick_space == 1 || sample.tick % tick_space == 0) && snapshot.coord_by_stream_tick(sample.tick, coord))
snapshot.ticks.push_back({sample.time, coord});
}
std::sort(snapshot.ticks.begin(), snapshot.ticks.end(), [](const Timeline_Tick& left, const Timeline_Tick& right) {
return left.tick < right.tick;
});
return snapshot;
}
}