Fixed synchronization issue when adding/removing scheduled tasks

This commit is contained in:
themode 2020-10-29 19:20:25 +01:00
parent c8d1a30486
commit 384df073a8
4 changed files with 51 additions and 20 deletions

View File

@ -267,6 +267,7 @@ public class CommandDispatcher {
syntaxValues.setArg(argument.getId(), parsedValue); syntaxValues.setArg(argument.getId(), parsedValue);
} else { } else {
fullyCorrect = false; fullyCorrect = false;
break;
} }
} }

View File

@ -1,6 +1,7 @@
package net.minestom.server.command.builder.arguments; package net.minestom.server.command.builder.arguments;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays; import java.util.Arrays;
@ -22,7 +23,14 @@ public class ArgumentWord extends Argument<String> {
super(id, false); super(id, false);
} }
public ArgumentWord from(String... restrictions) { /**
* Used to force the use of a few precise words instead of complete freedom.
*
* @param restrictions the accepted words
* @return 'this'
*/
@NotNull
public ArgumentWord from(@Nullable String... restrictions) {
this.restrictions = restrictions; this.restrictions = restrictions;
return this; return this;
} }
@ -44,7 +52,7 @@ public class ArgumentWord extends Argument<String> {
@Override @Override
public int getConditionResult(@NotNull String value) { public int getConditionResult(@NotNull String value) {
// Check restrictions // Check restrictions
if (restrictions != null && restrictions.length > 0) { if (hasRestrictions()) {
for (String r : restrictions) { for (String r : restrictions) {
if (value.equalsIgnoreCase(r)) if (value.equalsIgnoreCase(r))
return SUCCESS; return SUCCESS;
@ -55,10 +63,21 @@ public class ArgumentWord extends Argument<String> {
return SUCCESS; return SUCCESS;
} }
/**
* Gets if this argument allow complete freedom in the word choice or if a list has been defined.
*
* @return true if the word selection is restricted
*/
public boolean hasRestrictions() { public boolean hasRestrictions() {
return restrictions != null && restrictions.length > 0; return restrictions != null && restrictions.length > 0;
} }
/**
* Gets all the word restrictions
*
* @return the word restrictions, can be null
*/
@Nullable
public String[] getRestrictions() { public String[] getRestrictions() {
return restrictions; return restrictions;
} }

View File

@ -68,7 +68,7 @@ public class SchedulerManager {
} }
/** /**
* Initializes a new {@link TaskBuilder} for creating a shutdown {@link Task} * Initializes a new {@link TaskBuilder} for creating a shutdown {@link Task}.
* *
* @param runnable The shutdown {@link Task} to run when scheduled * @param runnable The shutdown {@link Task} to run when scheduled
* @return the {@link TaskBuilder} * @return the {@link TaskBuilder}
@ -78,16 +78,18 @@ public class SchedulerManager {
} }
/** /**
* Removes/Forces the end of a {@link Task} * Removes/Forces the end of a {@link Task}.
* *
* @param task The {@link Task} to remove * @param task The {@link Task} to remove
*/ */
public void removeTask(Task task) { public void removeTask(Task task) {
this.tasks.remove(task.getId()); synchronized (tasks) {
this.tasks.remove(task.getId());
}
} }
/** /**
* Removes/Forces the end of a {@link Task} * Removes/Forces the end of a {@link Task}.
* *
* @param task The {@link Task} to remove * @param task The {@link Task} to remove
*/ */
@ -96,7 +98,7 @@ public class SchedulerManager {
} }
/** /**
* Shutdowns all normal tasks and call the registered shutdown tasks * Shutdowns all normal tasks and call the registered shutdown tasks.
*/ */
public void shutdown() { public void shutdown() {
MinecraftServer.getLOGGER().info("Executing all shutdown tasks.."); MinecraftServer.getLOGGER().info("Executing all shutdown tasks..");
@ -122,7 +124,7 @@ public class SchedulerManager {
} }
/** /**
* Increments the current shutdown counter value * Increments the current shutdown counter value.
* *
* @return the updated shutdown counter value * @return the updated shutdown counter value
*/ */
@ -131,7 +133,9 @@ public class SchedulerManager {
} }
/** /**
* Gets a {@link Collection} with all the registered {@link Task} * Gets a {@link Collection} with all the registered {@link Task}.
* <p>
* Be aware that the collection is not thread-safe.
* *
* @return a {@link Collection} with all the registered {@link Task} * @return a {@link Collection} with all the registered {@link Task}
*/ */
@ -140,7 +144,7 @@ public class SchedulerManager {
} }
/** /**
* Gets a {@link Collection} with all the registered shutdown {@link Task} * Gets a {@link Collection} with all the registered shutdown {@link Task}.
* *
* @return a {@link Collection} with all the registered shutdown {@link Task} * @return a {@link Collection} with all the registered shutdown {@link Task}
*/ */
@ -149,7 +153,7 @@ public class SchedulerManager {
} }
/** /**
* Gets the execution service for all the registered {@link Task} * Gets the execution service for all the registered {@link Task}.
* *
* @return the execution service for all the registered {@link Task} * @return the execution service for all the registered {@link Task}
*/ */
@ -158,7 +162,7 @@ public class SchedulerManager {
} }
/** /**
* Gets the scheduled execution service for all the registered {@link Task} * Gets the scheduled execution service for all the registered {@link Task}.
* *
* @return the scheduled execution service for all the registered {@link Task} * @return the scheduled execution service for all the registered {@link Task}
*/ */

View File

@ -1,5 +1,6 @@
package net.minestom.server.timer; package net.minestom.server.timer;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minestom.server.utils.time.TimeUnit; import net.minestom.server.utils.time.TimeUnit;
/** /**
@ -22,9 +23,9 @@ public class TaskBuilder {
private long repeat; private long repeat;
/** /**
* Creates a task builder * Creates a task builder.
* <br> * <br>
* <b>Note:</b> The task builder creates a normal task * <b>Note:</b> The task builder creates a normal task.
* *
* @param schedulerManager The manager for the tasks * @param schedulerManager The manager for the tasks
* @param runnable The task to run when scheduled * @param runnable The task to run when scheduled
@ -34,7 +35,7 @@ public class TaskBuilder {
} }
/** /**
* Creates task builder * Creates a task builder.
* *
* @param schedulerManager The manager for the tasks * @param schedulerManager The manager for the tasks
* @param runnable The task to run when scheduled * @param runnable The task to run when scheduled
@ -71,7 +72,7 @@ public class TaskBuilder {
} }
/** /**
* Clears the delay interval of the {@link Task} * Clears the delay interval of the {@link Task}.
* *
* @return this builder, for chaining * @return this builder, for chaining
*/ */
@ -81,7 +82,7 @@ public class TaskBuilder {
} }
/** /**
* Clears the repeat interval of the {@link Task} * Clears the repeat interval of the {@link Task}.
* *
* @return this builder, for chaining * @return this builder, for chaining
*/ */
@ -91,7 +92,7 @@ public class TaskBuilder {
} }
/** /**
* Schedule this {@link Task} for execution * Schedule this {@link Task} for execution.
* *
* @return the built {@link Task} * @return the built {@link Task}
*/ */
@ -103,9 +104,15 @@ public class TaskBuilder {
this.delay, this.delay,
this.repeat); this.repeat);
if (this.shutdown) { if (this.shutdown) {
this.schedulerManager.shutdownTasks.put(task.getId(), task); Int2ObjectMap<Task> shutdownTasks = this.schedulerManager.shutdownTasks;
synchronized (shutdownTasks) {
shutdownTasks.put(task.getId(), task);
}
} else { } else {
this.schedulerManager.tasks.put(task.getId(), task); Int2ObjectMap<Task> tasks = this.schedulerManager.tasks;
synchronized (tasks) {
tasks.put(task.getId(), task);
}
task.schedule(); task.schedule();
} }
return task; return task;