geforkt von Mirrors/Paper
Fixed some async tasks running synchronously. Fixes BUKKIT-2934
Additionally refactored cancel method to be more object-oriented.
Dieser Commit ist enthalten in:
Ursprung
c2bae0bebb
Commit
092800af26
@ -95,4 +95,12 @@ class CraftAsyncTask extends CraftTask {
|
|||||||
LinkedList<BukkitWorker> getWorkers() {
|
LinkedList<BukkitWorker> getWorkers() {
|
||||||
return workers;
|
return workers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean cancel0() {
|
||||||
|
synchronized (workers) {
|
||||||
|
// Synchronizing here prevents race condition for a completing task
|
||||||
|
setPeriod(-2l);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,4 +96,13 @@ class CraftFuture<T> extends CraftTask implements Future<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
synchronized boolean cancel0() {
|
||||||
|
if (getPeriod() != -1l) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
setPeriod(-2l);
|
||||||
|
notifyAll();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ public class CraftScheduler implements BukkitScheduler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BukkitTask runTaskLaterAsynchronously(Plugin plugin, Runnable runnable, long delay) {
|
public BukkitTask runTaskLaterAsynchronously(Plugin plugin, Runnable runnable, long delay) {
|
||||||
return runTaskTimer(plugin, runnable, delay, -1l);
|
return runTaskTimerAsynchronously(plugin, runnable, delay, -1l);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int scheduleSyncRepeatingTask(final Plugin plugin, final Runnable runnable, long delay, long period) {
|
public int scheduleSyncRepeatingTask(final Plugin plugin, final Runnable runnable, long delay, long period) {
|
||||||
@ -158,7 +158,7 @@ public class CraftScheduler implements BukkitScheduler {
|
|||||||
}
|
}
|
||||||
CraftTask task = runners.get(taskId);
|
CraftTask task = runners.get(taskId);
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
cancelTask(task);
|
task.cancel0();
|
||||||
}
|
}
|
||||||
task = new CraftTask(
|
task = new CraftTask(
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
@ -172,7 +172,7 @@ public class CraftScheduler implements BukkitScheduler {
|
|||||||
while (tasks.hasNext()) {
|
while (tasks.hasNext()) {
|
||||||
final CraftTask task = tasks.next();
|
final CraftTask task = tasks.next();
|
||||||
if (task.getTaskId() == taskId) {
|
if (task.getTaskId() == taskId) {
|
||||||
cancelTask(task);
|
task.cancel0();
|
||||||
tasks.remove();
|
tasks.remove();
|
||||||
if (task.isSync()) {
|
if (task.isSync()) {
|
||||||
runners.remove(taskId);
|
runners.remove(taskId);
|
||||||
@ -188,7 +188,7 @@ public class CraftScheduler implements BukkitScheduler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (taskPending.getTaskId() == taskId) {
|
if (taskPending.getTaskId() == taskId) {
|
||||||
cancelTask(taskPending);
|
taskPending.cancel0();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -206,7 +206,7 @@ public class CraftScheduler implements BukkitScheduler {
|
|||||||
while (tasks.hasNext()) {
|
while (tasks.hasNext()) {
|
||||||
final CraftTask task = tasks.next();
|
final CraftTask task = tasks.next();
|
||||||
if (task.getOwner().equals(plugin)) {
|
if (task.getOwner().equals(plugin)) {
|
||||||
cancelTask(task);
|
task.cancel0();
|
||||||
tasks.remove();
|
tasks.remove();
|
||||||
if (task.isSync()) {
|
if (task.isSync()) {
|
||||||
runners.remove(task.getTaskId());
|
runners.remove(task.getTaskId());
|
||||||
@ -222,12 +222,12 @@ public class CraftScheduler implements BukkitScheduler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (taskPending.getTaskId() != -1 && taskPending.getOwner().equals(plugin)) {
|
if (taskPending.getTaskId() != -1 && taskPending.getOwner().equals(plugin)) {
|
||||||
cancelTask(taskPending);
|
taskPending.cancel0();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (CraftTask runner : runners.values()) {
|
for (CraftTask runner : runners.values()) {
|
||||||
if (runner.getOwner().equals(plugin)) {
|
if (runner.getOwner().equals(plugin)) {
|
||||||
cancelTask(runner);
|
runner.cancel0();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,7 +239,7 @@ public class CraftScheduler implements BukkitScheduler {
|
|||||||
Iterator<CraftTask> it = CraftScheduler.this.runners.values().iterator();
|
Iterator<CraftTask> it = CraftScheduler.this.runners.values().iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
CraftTask task = it.next();
|
CraftTask task = it.next();
|
||||||
cancelTask(task);
|
task.cancel0();
|
||||||
if (task.isSync()) {
|
if (task.isSync()) {
|
||||||
it.remove();
|
it.remove();
|
||||||
}
|
}
|
||||||
@ -253,10 +253,10 @@ public class CraftScheduler implements BukkitScheduler {
|
|||||||
if (taskPending == task) {
|
if (taskPending == task) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cancelTask(taskPending);
|
taskPending.cancel0();
|
||||||
}
|
}
|
||||||
for (CraftTask runner : runners.values()) {
|
for (CraftTask runner : runners.values()) {
|
||||||
cancelTask(runner);
|
runner.cancel0();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,35 +421,6 @@ public class CraftScheduler implements BukkitScheduler {
|
|||||||
return !pending.isEmpty() && pending.peek().getNextRun() <= currentTick;
|
return !pending.isEmpty() && pending.peek().getNextRun() <= currentTick;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is important to make sure the code is consistent everywhere.
|
|
||||||
* Synchronizing is needed for future and async to prevent race conditions,
|
|
||||||
* main thread or otherwise.
|
|
||||||
* @return True if cancelled
|
|
||||||
*/
|
|
||||||
private boolean cancelTask(final CraftTask task) {
|
|
||||||
if (task.isSync()) {
|
|
||||||
if (task instanceof CraftFuture) {
|
|
||||||
synchronized (task) {
|
|
||||||
if (task.getPeriod() != -1l) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// This needs to be set INSIDE of the synchronized block
|
|
||||||
task.setPeriod(-2l);
|
|
||||||
task.notifyAll();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
task.setPeriod(-2l);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synchronized (((CraftAsyncTask) task).getWorkers()) {
|
|
||||||
// Synchronizing here prevents race condition for a completing task
|
|
||||||
task.setPeriod(-2l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
int debugTick = currentTick;
|
int debugTick = currentTick;
|
||||||
|
@ -84,4 +84,14 @@ class CraftTask implements BukkitTask, Runnable {
|
|||||||
public void cancel() {
|
public void cancel() {
|
||||||
Bukkit.getScheduler().cancelTask(id);
|
Bukkit.getScheduler().cancelTask(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method properly sets the status to cancelled, synchronizing when required.
|
||||||
|
*
|
||||||
|
* @return false if it is a craft future task that has already begun execution, true otherwise
|
||||||
|
*/
|
||||||
|
boolean cancel0() {
|
||||||
|
setPeriod(-2l);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren