1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-09 17:31:18 +00:00

Reformat ClockReceiver.

This commit is contained in:
Thomas Harte 2024-11-29 22:12:57 -05:00
parent abfc73299e
commit 86fa8da8c5
12 changed files with 715 additions and 710 deletions

View File

@ -56,7 +56,7 @@
Boolean operators, but forcing callers and receivers to be explicit as to usage.
*/
template <class T> class WrappedInt {
public:
public:
using IntType = int64_t;
forceinline constexpr WrappedInt(IntType l) noexcept : length_(l) {}
@ -136,7 +136,8 @@ template <class T> class WrappedInt {
forceinline constexpr bool operator !=(const T &rhs) const { return length_ != rhs.length_; }
forceinline constexpr bool operator !() const { return !length_; }
// bool operator () is not supported because it offers an implicit cast to int, which is prone silently to permit misuse
// bool operator () is not supported because it offers an implicit cast to int,
// which is prone silently to permit misuse.
/// @returns The underlying int, converted to an integral type of your choosing, clamped to that int's range.
template<typename Type = IntType> forceinline constexpr Type as() const {
@ -146,14 +147,19 @@ template <class T> class WrappedInt {
} else if constexpr (std::is_signed_v<Type>) {
// Both integers are the same size, but a signed result is being asked for
// from an unsigned original.
return length_ > Type(std::numeric_limits<Type>::max()) ? Type(std::numeric_limits<Type>::max()) : Type(length_);
return length_ > Type(std::numeric_limits<Type>::max()) ?
Type(std::numeric_limits<Type>::max()) : Type(length_);
} else {
// An unsigned result is being asked for from a signed original.
return length_ < 0 ? 0 : Type(length_);
}
}
const auto clamped = std::clamp(length_, IntType(std::numeric_limits<Type>::min()), IntType(std::numeric_limits<Type>::max()));
const auto clamped = std::clamp(
length_,
IntType(std::numeric_limits<Type>::min()),
IntType(std::numeric_limits<Type>::max())
);
return Type(clamped);
}
@ -185,20 +191,20 @@ template <class T> class WrappedInt {
// operator int() is deliberately not provided, to avoid accidental subtitution of
// classes that use this template.
protected:
protected:
IntType length_;
};
/// Describes an integer number of whole cycles: pairs of clock signal transitions.
class Cycles: public WrappedInt<Cycles> {
public:
public:
forceinline constexpr Cycles(IntType l) noexcept : WrappedInt<Cycles>(l) {}
forceinline constexpr Cycles() noexcept : WrappedInt<Cycles>() {}
forceinline static constexpr Cycles max() {
return Cycles(std::numeric_limits<IntType>::max());
}
private:
private:
friend WrappedInt;
void fill(Cycles &result) {
result.length_ = length_;
@ -213,14 +219,15 @@ class Cycles: public WrappedInt<Cycles> {
/// Describes an integer number of half cycles: single clock signal transitions.
class HalfCycles: public WrappedInt<HalfCycles> {
public:
public:
forceinline constexpr HalfCycles(IntType l) noexcept : WrappedInt<HalfCycles>(l) {}
forceinline constexpr HalfCycles() noexcept : WrappedInt<HalfCycles>() {}
forceinline static constexpr HalfCycles max() {
return HalfCycles(std::numeric_limits<IntType>::max());
}
forceinline constexpr HalfCycles(const Cycles &cycles) noexcept : WrappedInt<HalfCycles>(cycles.as_integral() * 2) {}
forceinline constexpr HalfCycles(const Cycles &cycles) noexcept :
WrappedInt<HalfCycles>(cycles.as_integral() * 2) {}
/// @returns The number of whole cycles completely covered by this span of half cycles.
forceinline constexpr Cycles cycles() const {
@ -247,7 +254,7 @@ class HalfCycles: public WrappedInt<HalfCycles> {
return result;
}
private:
private:
friend WrappedInt;
void fill(Cycles &result) {
result = Cycles(length_ >> 1);

View File

@ -58,7 +58,7 @@ struct Observer {
The hint provided is just that: a hint. Owners may perform ::run_for at a greater frequency.
*/
class Source {
public:
public:
/// Registers @c observer as the new clocking observer.
void set_clocking_hint_observer(Observer *observer) {
observer_ = observer;
@ -68,10 +68,10 @@ class Source {
/// @returns the current preferred clocking strategy.
virtual Preference preferred_clocking() const = 0;
private:
private:
Observer *observer_ = nullptr;
protected:
protected:
/*!
Provided for subclasses; call this whenever the clocking preference might have changed.
This will notify the observer if there is one.

View File

@ -15,7 +15,7 @@
Provides the logic to insert into and traverse a list of future scheduled items.
*/
template <typename TimeUnit> class DeferredQueue {
public:
public:
/*!
Schedules @c action to occur in @c delay units of time.
*/
@ -78,13 +78,14 @@ template <typename TimeUnit> class DeferredQueue {
return pending_actions_.empty();
}
private:
private:
// The list of deferred actions.
struct DeferredAction {
TimeUnit delay;
std::function<void(void)> action;
DeferredAction(TimeUnit delay, const std::function<void(void)> &action) : delay(delay), action(std::move(action)) {}
DeferredAction(TimeUnit delay, const std::function<void(void)> &action) :
delay(delay), action(std::move(action)) {}
};
std::vector<DeferredAction> pending_actions_;
};
@ -117,8 +118,6 @@ template <typename TimeUnit> class DeferredQueuePerformer: public DeferredQueue<
DeferredQueue<TimeUnit>::advance(length);
target_(length);
// TODO: optimise this to avoid the multiple std::vector deletes. Find a neat way to expose that solution, maybe?
}
private:

View File

@ -13,7 +13,7 @@
of future values.
*/
template <int DeferredDepth, typename ValueT> class DeferredValue {
private:
private:
static_assert(sizeof(ValueT) <= 4);
constexpr int elements_per_uint32 = sizeof(uint32_t) / sizeof(ValueT);
@ -23,7 +23,7 @@ template <int DeferredDepth, typename ValueT> class DeferredValue {
std::array<uint32_t, (DeferredDepth + elements_per_uint32 - 1) / elements_per_uint32> backlog;
public:
public:
/// @returns the current value.
ValueT value() const {
return uint8_t(backlog[0]);
@ -38,7 +38,7 @@ template <int DeferredDepth, typename ValueT> class DeferredValue {
}
/// Inserts a new value, replacing whatever is currently at the end of the queue.
void insert(ValueT value) {
void insert(const ValueT value) {
backlog[DeferredDepth / elements_per_uint32] =
(backlog[DeferredDepth / elements_per_uint32] & insert_mask) | (value << insert_shift);
}

View File

@ -35,8 +35,9 @@
TODO: incorporate and codify AsyncJustInTimeActor.
*/
template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int divider = 1> class JustInTimeActor:
public ClockingHint::Observer {
private:
public ClockingHint::Observer
{
private:
/*!
A std::unique_ptr deleter which causes an update_sequence_point to occur on the actor supplied
to it at construction if it implements @c next_sequence_point(). Otherwise destruction is a no-op.
@ -49,7 +50,8 @@ template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int di
*/
class SequencePointAwareDeleter {
public:
explicit SequencePointAwareDeleter(JustInTimeActor<T, LocalTimeScale, multiplier, divider> *actor) noexcept
explicit SequencePointAwareDeleter(
JustInTimeActor<T, LocalTimeScale, multiplier, divider> *const actor) noexcept
: actor_(actor) {}
forceinline void operator ()(const T *const) const {
@ -72,7 +74,7 @@ template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int di
HalfCycles,
Cycles>;
public:
public:
/// Constructs a new JustInTimeActor using the same construction arguments as the included object.
template<typename... Args> JustInTimeActor(Args&&... args) : object_(std::forward<Args>(args)...) {
if constexpr (std::is_base_of<ClockingHint::Source, T>::value) {
@ -264,14 +266,15 @@ template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int di
return clocking_preference_;
}
private:
private:
T object_;
LocalTimeScale time_since_update_, time_until_event_, time_overrun_;
bool is_flushed_ = true;
bool did_flush_ = false;
template <typename S, typename = void> struct has_sequence_points : std::false_type {};
template <typename S> struct has_sequence_points<S, decltype(void(std::declval<S &>().next_sequence_point()))> : std::true_type {};
template <typename S>
struct has_sequence_points<S, decltype(void(std::declval<S &>().next_sequence_point()))> : std::true_type {};
ClockingHint::Preference clocking_preference_ = ClockingHint::Preference::JustInTime;
void set_component_prefers_clocking(ClockingHint::Source *, ClockingHint::Preference clocking) {
@ -288,8 +291,9 @@ template <class T, class LocalTimeScale = HalfCycles, int multiplier = 1, int di
Any time the amount of accumulated time crosses a threshold provided at construction time,
the object will be updated on the AsyncTaskQueue.
*/
template <class T, class LocalTimeScale = HalfCycles, class TargetTimeScale = LocalTimeScale> class AsyncJustInTimeActor {
public:
template <class T, class LocalTimeScale = HalfCycles, class TargetTimeScale = LocalTimeScale>
class AsyncJustInTimeActor {
public:
/// Constructs a new AsyncJustInTimeActor using the same construction arguments as the included object.
template<typename... Args> AsyncJustInTimeActor(TargetTimeScale threshold, Args&&... args) :
object_(std::forward<Args>(args)...),
@ -327,7 +331,7 @@ template <class T, class LocalTimeScale = HalfCycles, class TargetTimeScale = Lo
}
}
private:
private:
T object_;
LocalTimeScale time_since_update_;
TargetTimeScale threshold_;

View File

@ -21,12 +21,12 @@ namespace Time {
of time, to bring it into phase.
*/
class ScanSynchroniser {
public:
public:
/*!
@returns @c true if the emulated machine can be synchronised with the host frame output based on its
current @c [scan]status and the host machine's @c frame_duration; @c false otherwise.
*/
bool can_synchronise(const Outputs::Display::ScanStatus &scan_status, double frame_duration) {
bool can_synchronise(const Outputs::Display::ScanStatus &scan_status, const double frame_duration) {
ratio_ = 1.0;
if(scan_status.field_duration_gradient < 0.00001) {
// Check out the machine's current frame time.
@ -62,15 +62,15 @@ class ScanSynchroniser {
return speed_multiplier_ * base_multiplier_;
}
void set_base_speed_multiplier(double multiplier) {
void set_base_speed_multiplier(const double multiplier) {
base_multiplier_ = multiplier;
}
double get_base_speed_multiplier() {
double get_base_speed_multiplier() const {
return base_multiplier_;
}
private:
private:
static constexpr double maximum_rate_adjustment = 1.03;
static constexpr double phase_adjustment_ratio = 1.005;

View File

@ -16,7 +16,9 @@ typedef double Seconds;
typedef int64_t Nanos;
inline Nanos nanos_now() {
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
return std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch()
).count();
}
inline Seconds seconds(Nanos nanos) {

View File

@ -21,7 +21,7 @@ namespace Time {
(iii) optionally, timer jitter; in order to suggest when you should next start drawing.
*/
class VSyncPredictor {
public:
public:
/*!
Announces to the predictor that the work of producing an output frame has begun.
*/
@ -102,7 +102,7 @@ class VSyncPredictor {
return last_vsync_ + frame_duration_ - period;
}
private:
private:
class VarianceCollector {
public:
VarianceCollector(Time::Nanos default_value) {

View File

@ -5455,7 +5455,7 @@
attributes = {
BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 1430;
LastUpgradeCheck = 1610;
ORGANIZATIONNAME = "Thomas Harte";
TargetAttributes = {
4B055A691FAE763F0060FFFF = {
@ -6908,6 +6908,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_ENABLE_MODULES = YES;
@ -6968,6 +6969,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
CLANG_ENABLE_MODULES = YES;

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1400"
LastUpgradeVersion = "1610"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1400"
version = "1.3">
LastUpgradeVersion = "1610"
version = "1.8">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1400"
LastUpgradeVersion = "1610"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -51,15 +51,6 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4BB73E9D1B587A5100552FC2"
BuildableName = "Clock Signal.app"
BlueprintName = "Clock Signal"
ReferencedContainer = "container:Clock Signal.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">