Skip to content

Instantly share code, notes, and snippets.

@novln
Created November 19, 2012 21:13
Show Gist options
  • Save novln/4113953 to your computer and use it in GitHub Desktop.
Save novln/4113953 to your computer and use it in GitHub Desktop.
package fr.umlv.poo.automate0.command;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.PriorityBlockingQueue;
public final class Invoker {
private final static int INITIAL_CAPACITY = 11;
private final Command abort;
private final Comparator<Command> comparator;
private final Map<Command, Integer> priority;
private final PriorityBlockingQueue<Command> executeQueue;
private final BlockingDeque<Command> revokeQueue;
private final Runnable runnable;
private final Thread thread;
public Invoker() {
abort = new Command() {
@Override
public void execute() {
executeQueue.clear();
}
@Override
public void undo() {
throw new UnsupportedOperationException("Cannot be undone");
}
};
comparator = new Comparator<Command>() {
@Override
public int compare(Command command1, Command command2) {
int p1 = Objects.requireNonNull(priority.get(command1));
int p2 = Objects.requireNonNull(priority.get(command2));
return p1 - p2;
}
};
priority = new HashMap<>();
priority.put(abort, 0);
executeQueue = new PriorityBlockingQueue<>(INITIAL_CAPACITY, comparator);
revokeQueue = new LinkedBlockingDeque<>();
runnable = new Runnable() {
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()) {
try {
Command command = executeQueue.take();
revokeQueue.addFirst(command);
command.execute();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread = new Thread(runnable);
thread.start();
}
public void apply(Command command) {
priority.put(command, priority.size());
executeQueue.add(command);
}
public void revokeAll() {
apply(new Command() {
@Override
public void execute() {
while(!revokeQueue.isEmpty()) {
try {
final Command command = revokeQueue.take();
apply(new Command() {
@Override
public void execute() {
command.undo();
}
@Override
public void undo() {
command.execute();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void undo() {}
});
}
public void abort() {
apply(abort);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment