mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-09 17:31:18 +00:00
Reformat ClockReceiver.
This commit is contained in:
parent
abfc73299e
commit
86fa8da8c5
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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_;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1400"
|
||||
LastUpgradeVersion = "1610"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -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">
|
||||
|
@ -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">
|
||||
|
Loading…
x
Reference in New Issue
Block a user