#include "Timeline_Stream.h" #include #include #include 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(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(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(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::max()) { int expected = std::numeric_limits::min(); next_tick_value.compare_exchange_strong(expected, 1, std::memory_order_acq_rel, std::memory_order_acquire); tick = 0; } { std::lock_guard 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 captured; { std::lock_guard lock(samples_mutex); std::uint64_t version = version_value.load(std::memory_order_acquire); snapshot.version = version + 1; std::size_t count = std::min(static_cast(time_point_size), samples.size()); captured.reserve(count); auto first = samples.end() - static_cast(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(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; } }