Skip to content

Commit

Permalink
[#78] tep: remove&removeAll for scheduled once
Browse files Browse the repository at this point in the history
  • Loading branch information
vbmacher committed May 13, 2023
1 parent 1e30f2d commit 54ba22a
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public void scheduleOnceMultiple(Map<Integer, Runnable> events) {
* for cycles which were scheduled first (always the lower ones). In effect the behavior should be as expected
* though.
* <p>
* Also, this function does not work when the event was scheduled using
* This function does not work when the event was scheduled using
* {@link #scheduleOnce(int, Runnable) scheduleOnce} function.
*
* @param cycles the number of cycles
Expand Down Expand Up @@ -190,6 +190,8 @@ public void remove(int cycles, Runnable event) {
* Remove all scheduled events from this processor.
* <p>
* This function is thread-safe.
* This function does not work when the event was scheduled using
* {@link #scheduleOnce(int, Runnable) scheduleOnce} function.
*
* @param cycles the number of cycles
*/
Expand All @@ -211,6 +213,57 @@ public void removeAll(int cycles) {
});
}

/**
* Remove events scheduled once.
* <p>
* This function is thread-safe.
* <p>
* Given event function must be the same instance as used on scheduling.
* <p>
* This function does not work when the event was scheduled using
* {@link #schedule(int, Runnable) schedule} function.
*
* @param cycles the number of cycles
* @param event the scheduled event
*/
public void removeScheduledOnce(int cycles, Runnable event) {
lockNoRepeat.lockWrite(() -> {
if (noRepeatEventQueue.containsKey(cycles)) {
Queue<Runnable> queue = noRepeatEventQueue.get(cycles);
queue.remove(event);
if (queue.isEmpty()) {
noRepeatEventQueue.remove(cycles);
}
if (noRepeatEventQueue.isEmpty()) {
cycleNoRepeatMaximum.set(0);
} else {
cycleNoRepeatMaximum.set(noRepeatEventQueue.lastKey());
}
}
});
}

/**
* Removes all events scheduled once
* <p>
* This function is thread-safe.
* <p>
* This function does not work when the event was scheduled using
* {@link #schedule(int, Runnable) schedule} function.
*
* @param cycles the number of cycles
*/
public void removeAllScheduledOnce(int cycles) {
lockNoRepeat.lockWrite(() -> {
noRepeatEventQueue.remove(cycles);
if (noRepeatEventQueue.isEmpty()) {
cycleNoRepeatMaximum.set(0);
} else {
cycleNoRepeatMaximum.set(noRepeatEventQueue.lastKey());
}
});
}

/**
* Advances system clock (number of passed CPU cycles) and triggers all events
* which passed their deadline.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
package net.emustudio.emulib.plugins.cpu;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

import java.util.Map;
Expand Down Expand Up @@ -53,6 +52,18 @@ public void testScheduleAndAdvanceWorks() {
assertEquals(11, count.get());
}

@Test
public void testScheduleOneCycleMoreEvents() {
AtomicInteger count = new AtomicInteger();

tep.schedule(1, count::incrementAndGet);
tep.schedule(1, count::incrementAndGet);
tep.schedule(1, count::incrementAndGet);

tep.advanceClock(2);
assertEquals(6, count.get());
}

@Test
public void testScheduleAndAdvanceOverflowWorks() {
AtomicInteger count = new AtomicInteger();
Expand Down Expand Up @@ -215,4 +226,42 @@ public void testScheduleOnceMultiple() {
tep.advanceClock(6);
assertEquals(3, count.get());
}

@Test
public void testScheduleOnceOneCycleMoreEvents() {
AtomicInteger count = new AtomicInteger();

tep.scheduleOnce(1, count::incrementAndGet);
tep.scheduleOnce(1, count::incrementAndGet);
tep.scheduleOnce(1, count::incrementAndGet);

tep.advanceClock(1);
assertEquals(3, count.get());
}

@Test
public void testRemoveScheduledOnce() {
AtomicInteger count = new AtomicInteger();
Runnable r1 = count::incrementAndGet;

tep.scheduleOnce(1, r1);
tep.scheduleOnce(5, r1);
tep.removeScheduledOnce(1, r1);

tep.advanceClock(5);
assertEquals(1, count.get());
}

@Test
public void testRemoveAllScheduledOnce() {
AtomicInteger count = new AtomicInteger();

tep.scheduleOnce(1, count::incrementAndGet);
tep.scheduleOnce(1, count::incrementAndGet);
tep.scheduleOnce(1, count::incrementAndGet);
tep.removeAllScheduledOnce(1);

tep.advanceClock(10);
assertEquals(0, count.get());
}
}

0 comments on commit 54ba22a

Please sign in to comment.