Skip to content

Commit

Permalink
Merge pull request #236 from satur9nine/dsfixnegativedelay
Browse files Browse the repository at this point in the history
Support negative delays in ScheduledFutures executed by the Determini…
  • Loading branch information
olibye committed Mar 16, 2024
2 parents e7a5fd1 + f6c3815 commit 87d54c1
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
*/
public class DeterministicScheduler implements ScheduledExecutorService {
private final DeltaQueue<ScheduledTask<?>> deltaQueue = new DeltaQueue<ScheduledTask<?>>();

private long passedTicks = 0;

/**
* Runs time forwards by a given duration, executing any commands scheduled for
* execution during that time period, and any background tasks spawned by the
Expand All @@ -39,12 +40,15 @@ public class DeterministicScheduler implements ScheduledExecutorService {
*/
public void tick(long duration, TimeUnit timeUnit) {
long remaining = toTicks(duration, timeUnit);
long total = remaining;

do {
remaining = deltaQueue.tick(remaining);
passedTicks += (total - remaining);
runUntilIdle();

} while (deltaQueue.isNotEmpty() && remaining > 0);

passedTicks += remaining;
}

/**
Expand Down Expand Up @@ -185,6 +189,7 @@ private final class ScheduledTask<T> implements ScheduledFuture<T>, Runnable {
private boolean isDone = false;
private T futureResult;
private Exception failure = null;
private long ranAtTicks;

public ScheduledTask(Callable<T> command) {
this.repeatDelay = -1;
Expand All @@ -210,7 +215,11 @@ public boolean repeats() {
}

public long getDelay(TimeUnit unit) {
return unit.convert(deltaQueue.delay(this), TimeUnit.MILLISECONDS);
Long delay = deltaQueue.delay(this);
if (delay == null) {
delay = ranAtTicks - passedTicks;
}
return unit.convert(delay, TimeUnit.MILLISECONDS);
}

public int compareTo(Delayed o) {
Expand Down Expand Up @@ -248,6 +257,7 @@ public boolean isDone() {
}

public void run() {
ranAtTicks = passedTicks;
try {
futureResult = command.call();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ public T next() {
public long delay() {
return head.delay;
}
public long delay(T element) {

public Long delay(T element) {
long ret = 0;
Node<T> next = head;
while (next != null) {
Expand All @@ -42,7 +42,7 @@ public long delay(T element) {
next = next.next;
}
if (next == null) {
return -1;
return null;
}
return ret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,21 @@ public void testCannotBlockWaitingForFutureResultOfScheduledCallable() throws Ex
}
catch (UnsupportedSynchronousOperationException expected) {}
}


public void testCanGetDelayAfterExecution() {
ScheduledFuture<?> task1 = scheduler.schedule(commandA, 1, TimeUnit.SECONDS);

checking(new Expectations() {{
oneOf (commandA).run();
}});

scheduler.tick(10, TimeUnit.SECONDS);

// Per getDelay documentation it returns: the remaining delay; zero or
// negative values indicate that the delay has already elapsed
assertEquals(-9, task1.getDelay(TimeUnit.SECONDS));
}

private Action schedule(final Runnable command) {
return ScheduleOnExecutorAction.schedule(scheduler, command);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,10 @@ public void testReturnsFalseIfElementAlreadyRemoved() {
assertFalse(deltaQueue.remove(elementC));
}

public void testDelayIsMinusOneWhenElementIsAlreadyRemoved() {
public void testDelayIsNullWhenElementIsAlreadyRemoved() {
deltaQueue.add(1L, elementA);
deltaQueue.remove(elementA);

assertEquals("delay", -1, deltaQueue.delay(elementA));
assertNull("delay", deltaQueue.delay(elementA));
}
}

0 comments on commit 87d54c1

Please sign in to comment.