From 5abff02d56303bf8b1ae1d2f32cce490aebecdf4 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 15 Feb 2026 13:10:24 -0500 Subject: [PATCH] Factor out the stuff of being a circular counter. --- Numeric/CircularCounter.hpp | 48 +++++++++++++++++++ .../Clock Signal.xcodeproj/project.pbxproj | 2 + Outputs/ScanTargets/BufferingScanTarget.cpp | 4 +- Outputs/ScanTargets/BufferingScanTarget.hpp | 8 ++-- 4 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 Numeric/CircularCounter.hpp diff --git a/Numeric/CircularCounter.hpp b/Numeric/CircularCounter.hpp new file mode 100644 index 000000000..a52fee89f --- /dev/null +++ b/Numeric/CircularCounter.hpp @@ -0,0 +1,48 @@ +// +// CircularCounter.hpp +// Clock Signal +// +// Created by Thomas Harte on 15/02/2026. +// Copyright © 2026 Thomas Harte. All rights reserved. +// + +#include + +namespace Numeric { + +template +class CircularCounter { +public: + constexpr CircularCounter() noexcept = default; + constexpr CircularCounter(const IntT value) noexcept : value_(value) { + assert(value < limit); + } + + CircularCounter &operator ++() { + ++value_; + if(value_ == limit) { + value_ = 0; + } + return *this; + } + + CircularCounter operator ++(int) { + const auto result = *this; + ++*this; + return result; + } + + operator IntT() const { + return value_; + } + + CircularCounter &operator = (const IntT rhs) { + value_ = rhs; + return *this; + } + +private: + IntT value_{}; +}; + +} diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index bee040c6b..f36d91304 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -1505,6 +1505,7 @@ 4B228CD724DA12C50077EF25 /* CSScanTargetView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSScanTargetView.h; sourceTree = ""; }; 4B228CD824DA12C60077EF25 /* CSScanTargetView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSScanTargetView.m; sourceTree = ""; }; 4B24095A1C45DF85004DA684 /* Stepper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Stepper.hpp; sourceTree = ""; }; + 4B249EDE2F4241DA00FD485B /* CircularCounter.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CircularCounter.hpp; sourceTree = ""; }; 4B2530F3244E6773007980BF /* fm.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = fm.json; sourceTree = ""; }; 4B25BC1E2DDD64AA002044CA /* TaskStateSegment.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TaskStateSegment.hpp; sourceTree = ""; }; 4B262BFF29691F55002EC0F7 /* PersonalityTraits.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = PersonalityTraits.hpp; sourceTree = ""; }; @@ -3844,6 +3845,7 @@ 4BD155312716362A00410C6E /* BitSpread.hpp */, 4B0B239F2D658C9400153879 /* BitStream.hpp */, 4281572E2AA0334300E16AA1 /* Carry.hpp */, + 4B249EDE2F4241DA00FD485B /* CircularCounter.hpp */, 4B7BA03E23D55E7900B98D9E /* CRC.hpp */, 4BC3A9A52F15EF2D00ACC885 /* CubicCurve.hpp */, 4B7BA03F23D55E7900B98D9E /* LFSR.hpp */, diff --git a/Outputs/ScanTargets/BufferingScanTarget.cpp b/Outputs/ScanTargets/BufferingScanTarget.cpp index 33409027b..4962a18c3 100644 --- a/Outputs/ScanTargets/BufferingScanTarget.cpp +++ b/Outputs/ScanTargets/BufferingScanTarget.cpp @@ -225,12 +225,12 @@ void BufferingScanTarget::announce( const auto submit_pointers = submit_pointers_.load(std::memory_order_relaxed); frames_[write].first_line = submit_pointers.line; frames_[write].first_scan = submit_pointers.scan; - write = (write + 1) % frames_.size(); + ++write; frame_write_.store(write, std::memory_order_release); auto read = frame_read_.load(std::memory_order_relaxed); if(read == write) { - read = (read + 1) % frames_.size(); + ++read; frame_read_.store(read, std::memory_order_relaxed); } } diff --git a/Outputs/ScanTargets/BufferingScanTarget.hpp b/Outputs/ScanTargets/BufferingScanTarget.hpp index 2bd19ea11..a1ced05ed 100644 --- a/Outputs/ScanTargets/BufferingScanTarget.hpp +++ b/Outputs/ScanTargets/BufferingScanTarget.hpp @@ -11,6 +11,7 @@ #include "Outputs/ScanTarget.hpp" #include "Outputs/DisplayMetrics.hpp" #include "Concurrency/SpinLock.hpp" +#include "Numeric/CircularCounter.hpp" #include #include @@ -320,9 +321,10 @@ private: size_t first_line; bool previous_frame_was_complete; }; - std::array frames_; - std::atomic frame_read_ = 0; - std::atomic frame_write_ = 0; + static constexpr uint16_t NumFrames = 60; + std::array frames_; + std::atomic> frame_read_; + std::atomic> frame_write_; // By convention everything in the PointerSet points to the next instance