85 lines
3.8 KiB
C++
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;
|
|
}
|
|
}
|