diff --git a/concurrentutil/src/main/java/ca/spottedleaf/concurrentutil/scheduler/EDFSchedulerThreadPool.java b/concurrentutil/src/main/java/ca/spottedleaf/concurrentutil/scheduler/EDFSchedulerThreadPool.java index b66b1c7..f787b32 100644 --- a/concurrentutil/src/main/java/ca/spottedleaf/concurrentutil/scheduler/EDFSchedulerThreadPool.java +++ b/concurrentutil/src/main/java/ca/spottedleaf/concurrentutil/scheduler/EDFSchedulerThreadPool.java @@ -226,6 +226,10 @@ private ScheduledState returnTask(final TickThreadRunner runner, final Scheduled @Override public void schedule(final SchedulableTick task) { synchronized (this.scheduleLock) { + if (task.getScheduledStart() == TimeUtil.DEADLINE_NOT_SET) { + throw new IllegalStateException("Start must be set when scheduling"); + } + final ScheduledState state = new ScheduledState(task); if (!task.setState(state)) { throw new IllegalStateException("Task " + task + " is already scheduled or cancelled"); @@ -284,17 +288,17 @@ public boolean updateTickStartToMax(final ScheduledState task, final long newSta @Override public boolean cancel(final SchedulableTick task) { - if (!(task.state instanceof ScheduledState state)) { - return false; - } - - if (state.schedulerOwnedBy != this) { + if (!(task.getState() instanceof ScheduledState state)) { return false; } synchronized (this.scheduleLock) { + if (state.schedulerOwnedBy != this) { + return false; + } if (this.queued.remove(state)) { // cancelled, and no runner owns it - so return + state.tryMarkCancelled(); return true; } if (state.awaitingLink != null) { @@ -312,10 +316,16 @@ public boolean cancel(final SchedulableTick task) { runner.replaceTask(replace); } + state.tryMarkCancelled(); return true; } - // could not find it in queue + if (state.ownedBy != null) { + // the runner is currently executing the tick, it will not reschedule the task if cancelled + return state.tryMarkCancelled(); + } + + // not queued, not awaiting, and not owned by a runner - the task has completed or is already cancelled return false; } } diff --git a/concurrentutil/src/main/java/ca/spottedleaf/concurrentutil/scheduler/SchedulableTick.java b/concurrentutil/src/main/java/ca/spottedleaf/concurrentutil/scheduler/SchedulableTick.java index fa594cb..dd477ac 100644 --- a/concurrentutil/src/main/java/ca/spottedleaf/concurrentutil/scheduler/SchedulableTick.java +++ b/concurrentutil/src/main/java/ca/spottedleaf/concurrentutil/scheduler/SchedulableTick.java @@ -32,7 +32,11 @@ public abstract class SchedulableTick { long scheduledStart = TimeUtil.DEADLINE_NOT_SET; - Object state; + private volatile Object state; + + final Object getState() { + return this.state; + } boolean setState(final Object state) { synchronized (this) { @@ -79,7 +83,7 @@ protected final void setScheduledStart(final long value) { public String toString() { return "SchedulableTick:{" + "class=" + this.getClass().getName() + "," + - "state=" + this.state + "," + "state=" + this.getState() + "," + "}"; } } diff --git a/concurrentutil/src/main/java/ca/spottedleaf/concurrentutil/scheduler/StealingScheduledThreadPool.java b/concurrentutil/src/main/java/ca/spottedleaf/concurrentutil/scheduler/StealingScheduledThreadPool.java index a4ce487..0729685 100644 --- a/concurrentutil/src/main/java/ca/spottedleaf/concurrentutil/scheduler/StealingScheduledThreadPool.java +++ b/concurrentutil/src/main/java/ca/spottedleaf/concurrentutil/scheduler/StealingScheduledThreadPool.java @@ -68,7 +68,7 @@ public OSNuma getNuma() { } private static ScheduledState getState(final SchedulableTick tick) { - return (ScheduledState)tick.state; + return (ScheduledState)tick.getState(); } private static Thread[] getThreads(final COWArrayList runners) { @@ -350,14 +350,14 @@ public void schedule(final SchedulableTick tick) { @Override public void notifyTasks(final SchedulableTick tick) { - if (tick.state instanceof ScheduledState state) { + if (tick.getState() instanceof ScheduledState state) { state.scheduleTasks(); } } @Override public boolean cancel(final SchedulableTick tick) { - if (tick.state instanceof ScheduledState state) { + if (tick.getState() instanceof ScheduledState state) { return state.tryCancel(); } else { return false;