ParityCountdownFrequencyDivider.java

1
package com.rox.apu;
2
3
import com.rox.clock.ClockWatcher;
4
5
/**
6
 * Every other call to {@link #tick()}, counts down from {@link #getCounterPeriod()} to 0 then
7
 * executes the given action - the "do real work on every other CPU cycle" gating that pulse and
8
 * noise channel timers both need (one APU cycle = two CPU cycles).
9
 *
10
 * Whether the very first call already counts as an "active" one (and so can run the action
11
 * immediately, if the countdown is already at 0) is set via the constructor's
12
 * {@code initialParityGate} argument, which seeds {@link #parityGate}.
13
 */
14
public class ParityCountdownFrequencyDivider implements ClockWatcher {
15
    private final Runnable action;
16
17
    private boolean parityGate;
18
    private int countdown;
19
    private int counterPeriod;
20
21
    public ParityCountdownFrequencyDivider(final Runnable action,
22
                                           final boolean initialParityGate,
23
                                           final int counterPeriod) {
24 2 1. <init> : negated conditional → KILLED
2. <init> : changed conditional boundary → KILLED
        if (counterPeriod < 0){
25
            throw new IllegalArgumentException("Period must be non-negative since it's a decreasing count that ends at 0.");
26
        }
27
28
        this.action = action;
29
        this.parityGate = initialParityGate;
30
        this.counterPeriod = counterPeriod;
31
    }
32
33
    public int getCounterPeriod() {
34 1 1. getCounterPeriod : replaced int return with 0 for com/rox/apu/ParityCountdownFrequencyDivider::getCounterPeriod → KILLED
        return counterPeriod;
35
    }
36
37
    public void setCounterPeriod(final int newCounterPeriod) {
38 2 1. setCounterPeriod : changed conditional boundary → KILLED
2. setCounterPeriod : negated conditional → KILLED
        if (newCounterPeriod < 0){
39
            throw new IllegalArgumentException("Period must be non-negative since it's a decreasing count that ends at 0.");
40
        }
41
42
        this.counterPeriod = newCounterPeriod;
43
    }
44
45
    /** Toggle the parity boolean and return the result */
46
    private boolean toggleParityAndGet(){
47 1 1. toggleParityAndGet : negated conditional → KILLED
        parityGate = !parityGate;
48 2 1. toggleParityAndGet : replaced boolean return with false for com/rox/apu/ParityCountdownFrequencyDivider::toggleParityAndGet → KILLED
2. toggleParityAndGet : replaced boolean return with true for com/rox/apu/ParityCountdownFrequencyDivider::toggleParityAndGet → KILLED
        return parityGate;
49
    }
50
51
    @Override
52
    public void tick() {
53
        //Only actions half the time, effectively dividing by 2
54 1 1. tick : negated conditional → KILLED
        if (toggleParityAndGet()){
55
            //Counts down from `counterPeriod` using `countdown`, firing `action` when we reach zero
56 1 1. tick : negated conditional → KILLED
            if (countdown == 0){
57
                countdown = counterPeriod;
58 1 1. tick : removed call to java/lang/Runnable::run → KILLED
                action.run();
59
            } else {
60 1 1. tick : Replaced integer subtraction with addition → KILLED
                countdown--;
61
            }
62
        }
63
    }
64
65
    /** Everything a {@link ParityCountdownFrequencyDivider} needs to carry on exactly where it was (its action is wiring, not state). */
66
    public record Snapshot(boolean parityGate, int countdown, int counterPeriod) {
67
    }
68
69
    public Snapshot snapshot(){
70 1 1. snapshot : replaced return value with null for com/rox/apu/ParityCountdownFrequencyDivider::snapshot → KILLED
        return new Snapshot(parityGate, countdown, counterPeriod);
71
    }
72
73
    public void restore(final Snapshot snapshot){
74
        parityGate = snapshot.parityGate();
75
        countdown = snapshot.countdown();
76
        counterPeriod = snapshot.counterPeriod();
77
    }
78
}

Mutations

24

1.1
Location : <init>
Killed by : com.rox.apu.ParityCountdownFrequencyDividerTest.[engine:junit-jupiter]/[class:com.rox.apu.ParityCountdownFrequencyDividerTest]/[method:withInitialParityGateTrueTheFirstCallSkipsTheAction()]
negated conditional → KILLED

2.2
Location : <init>
Killed by : com.rox.apu.ParityCountdownFrequencyDividerTest.[engine:junit-jupiter]/[class:com.rox.apu.ParityCountdownFrequencyDividerTest]/[method:withInitialParityGateTrueTheFirstCallSkipsTheAction()]
changed conditional boundary → KILLED

34

1.1
Location : getCounterPeriod
Killed by : com.rox.apu.ParityCountdownFrequencyDividerTest.[engine:junit-jupiter]/[class:com.rox.apu.ParityCountdownFrequencyDividerTest]/[method:counterPeriodCanBeReadAndUpdated()]
replaced int return with 0 for com/rox/apu/ParityCountdownFrequencyDivider::getCounterPeriod → KILLED

38

1.1
Location : setCounterPeriod
Killed by : com.rox.apu.ParityCountdownFrequencyDividerTest.[engine:junit-jupiter]/[class:com.rox.apu.ParityCountdownFrequencyDividerTest]/[method:changingCounterPeriodMidCountdownOnlyTakesEffectOnTheNextReload()]
changed conditional boundary → KILLED

2.2
Location : setCounterPeriod
Killed by : com.rox.apu.ParityCountdownFrequencyDividerTest.[engine:junit-jupiter]/[class:com.rox.apu.ParityCountdownFrequencyDividerTest]/[method:counterPeriodCanBeReadAndUpdated()]
negated conditional → KILLED

47

1.1
Location : toggleParityAndGet
Killed by : com.rox.apu.ParityCountdownFrequencyDividerTest.[engine:junit-jupiter]/[class:com.rox.apu.ParityCountdownFrequencyDividerTest]/[method:withInitialParityGateTrueTheFirstCallSkipsTheAction()]
negated conditional → KILLED

48

1.1
Location : toggleParityAndGet
Killed by : com.rox.apu.ParityCountdownFrequencyDividerTest.[engine:junit-jupiter]/[class:com.rox.apu.ParityCountdownFrequencyDividerTest]/[method:actionRunsOnEveryOtherCallThereafter()]
replaced boolean return with false for com/rox/apu/ParityCountdownFrequencyDivider::toggleParityAndGet → KILLED

2.2
Location : toggleParityAndGet
Killed by : com.rox.apu.ParityCountdownFrequencyDividerTest.[engine:junit-jupiter]/[class:com.rox.apu.ParityCountdownFrequencyDividerTest]/[method:withInitialParityGateTrueTheFirstCallSkipsTheAction()]
replaced boolean return with true for com/rox/apu/ParityCountdownFrequencyDivider::toggleParityAndGet → KILLED

54

1.1
Location : tick
Killed by : com.rox.apu.ParityCountdownFrequencyDividerTest.[engine:junit-jupiter]/[class:com.rox.apu.ParityCountdownFrequencyDividerTest]/[method:withInitialParityGateTrueTheFirstCallSkipsTheAction()]
negated conditional → KILLED

56

1.1
Location : tick
Killed by : com.rox.apu.ParityCountdownFrequencyDividerTest.[engine:junit-jupiter]/[class:com.rox.apu.ParityCountdownFrequencyDividerTest]/[method:actionRunsOnEveryOtherCallThereafter()]
negated conditional → KILLED

58

1.1
Location : tick
Killed by : com.rox.apu.ParityCountdownFrequencyDividerTest.[engine:junit-jupiter]/[class:com.rox.apu.ParityCountdownFrequencyDividerTest]/[method:actionRunsOnEveryOtherCallThereafter()]
removed call to java/lang/Runnable::run → KILLED

60

1.1
Location : tick
Killed by : com.rox.apu.ParityCountdownFrequencyDividerTest.[engine:junit-jupiter]/[class:com.rox.apu.ParityCountdownFrequencyDividerTest]/[method:actionRunsOncePerFullCounterPeriodOfActiveCalls()]
Replaced integer subtraction with addition → KILLED

70

1.1
Location : snapshot
Killed by : com.rox.apu.ApuSnapshotTest.[engine:jqwik]/[class:com.rox.apu.ApuSnapshotTest]/[property:frequencyDividerRoundTrips(boolean, int, int)]
replaced return value with null for com/rox/apu/ParityCountdownFrequencyDivider::snapshot → KILLED

Active mutators

Tests examined


Report generated by PIT 1.22.1