jalse.actions.DefaultActionScheduler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of JALSE Show documentation
Show all versions of JALSE Show documentation
Java Artificial Life Simulation Engine
package jalse.actions;
import static jalse.actions.Actions.emptyActionContext;
import static jalse.actions.Actions.unmodifiableActionContext;
import static jalse.actions.Actions.unmodifiableActorActionContext;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* A {@link ActionScheduler} implementation that schedules all actions against the supplied actor.
* Weak references are kept against all scheduled tasks so they can be bulk cancelled (these are
* also cleared on {@link ActionEngine} change).
*
* By default if no {@link ActionEngine} is supplied {@link ForkJoinActionEngine#commonPoolEngine()}
* will be used.
*
* @author Elliot Ford
*
* @param
* Actor type.
*/
public class DefaultActionScheduler implements ActionScheduler {
private final T actor;
private ActionEngine engine;
private final Set> contexts;
/**
* Creates a DefaultScheduler for the supplied actor.
*
* @param actor
* Actor to schedule actions against.
*/
public DefaultActionScheduler(final T actor) {
this.actor = Objects.requireNonNull(actor);
engine = ForkJoinActionEngine.commonPoolEngine(); // Defaults use common engine
contexts = new HashSet<>();
}
/**
* Cancel all tasks scheduled to the current engine for the actor by this scheduler.
*/
@Override
public void cancelAllScheduledForActor() {
synchronized (contexts) {
final Iterator> it = contexts.iterator();
while (it.hasNext()) {
final ActionContext cxt = it.next();
if (!cxt.isDone()) {
cxt.cancel();
}
it.remove();
}
}
}
/**
* Gets the action Actor.
*
* @return Actor to schedule events against.
*/
public T getActor() {
return actor;
}
/**
* Gets the associated engine.
*
* @return Associated engine or null if it has not been set.
*/
public ActionEngine getEngine() {
return engine;
}
@Override
public MutableActionContext newContextForActor(final Action action) {
// Check engine running
if (engine.isStopped()) {
return emptyActionContext();
} else {
// New context for actor
return unmodifiableActorActionContext(newContextForActor0(action));
}
}
private MutableActionContext newContextForActor0(final Action action) {
// Create new context
final MutableActionContext context = engine.newContext(action);
context.setActor(actor);
// Add then purge
synchronized (contexts) {
contexts.add(context);
contexts.removeIf(ActionContext::isDone);
}
return context;
}
@Override
public ActionContext scheduleForActor(final Action action, final long initialDelay, final long period,
final TimeUnit unit) {
// Check engine running
if (engine.isStopped()) {
return emptyActionContext();
}
// Create new actor context
final MutableActionContext context = newContextForActor0(action);
context.setInitialDelay(initialDelay, unit);
context.setPeriod(period, unit);
context.schedule();
// Don't allow for mutation (it's running)
return unmodifiableActionContext(context);
}
/**
* Associates a engine to this scheduler (if the engine changes all task references are lost).
*
* @param engine
* Engine to schedule actions against.
*/
public void setEngine(final ActionEngine engine) {
if (!Objects.equals(this.engine, engine)) { // Only if changed
synchronized (contexts) {
contexts.clear();
}
}
this.engine = engine;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy