package kukaWii.movement;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import kukaWii.wiiHandle.service.SecurityService;
/**
* Hilfsklasse, in der Bewegungsbefehle ({@link MoveAction}) gesammelt werden
* können.
*
* @author Kai Hufenbach
*
*/
public class MovementService {
// Maximale Größe der Queue, wird diese überschrieben, passiert ein
// eingestelltes Verhalten.
private int bufferSize = 1000;
private int overflowAction = 2;
private int takeAction = 0;
public static final int DROP = 0;
public static final int SOFT_INTERRUPT = 1;
public static final int HARD_INTERRUPT = 2;
public static final int BLOCK = 0;
public static final int NULL = 1;
private static MovementService instance;
private BlockingQueue<MoveAction> moveQueue;
private MovementService() {
moveQueue = new ArrayBlockingQueue<MoveAction>(bufferSize);
}
/**
* Fügt eine MoveAction hinzu. Ist die Queue voll, wird je nach Einstellung,
* ein Packet weggeworfen, ein harter- oder weicher Abbruch eingeleitet.
*
* @param action
*/
public synchronized void addMoveAction(MoveAction action) {
if (!moveQueue.offer(action)) {
if (overflowAction == DROP) {
try {
moveQueue.take();
moveQueue.add(action);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else if (overflowAction == SOFT_INTERRUPT) {
// TODO muss noch entschieden
} else if (overflowAction == HARD_INTERRUPT) {
SecurityService
.panicInterrupt("Bewegungs-Queue übergelaufen, Größe: "
+ bufferSize);
}
}
}
/**
* Gibt die nächste Bewegungsanweisung zurück. Das Verhalten, was bei leerer
* Queue passiert, kann eingesetellt werden.
*
* @return
*/
public synchronized MoveAction getNextMoveAction() {
if (takeAction == BLOCK) {
try {
return moveQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else if (takeAction == NULL) {
return moveQueue.poll();
}
// Sollte nicht passieren.
return null;
}
/**
* Gibt die Aktuelle anzahl der Elemente an, die im Buffer vorhanden sind.
* @return
*/
public synchronized int getActualBuffer(){
return moveQueue.size() - moveQueue.remainingCapacity();
}
/**
* Setzt die Größe des Bewegungs-Buffers auf die angegebene Größe. (Standard
* ist 10) Der Bewegungsbuffer wird bei dieser Aktion geleert!
*
* @param size
*/
public void setBufferSize(int size) {
bufferSize = size;
moveQueue = new ArrayBlockingQueue<MoveAction>(bufferSize);
}
/**
* Setzt das Verhalten, was passieren soll, wenn beim Herausnehmen eines
* Elements eine leere Queue vorliegt.
*
* @param action
* 0: Der Aufruf blockt solange, bis ein Element vorhanden ist
* (Standard), 1: es wird null zurückgegeben
*/
public void setTakeAction(int action) {
if (action >= 0 && action < 2) {
this.takeAction = action;
} else {
throw new IllegalArgumentException(
"Es sind nur 0, 1 als Aktion erlaubt. Siehe dazu die Konstanten der Klasse.");
}
}
/**
* Bestimmt, was passieren soll, wenn der Bewegungs-Buffer überläuft.
*
* @param action
* zur Auswahl stehen: 0: ältestes verwerfen, 1: weicher Abbruch,
* 2: harter Abbruch (Standard)
*/
public void setOverflowAction(int action) {
if (action >= 0 && action < 4) {
this.overflowAction = action;
} else {
throw new IllegalArgumentException(
"Es sind nur 0, 1 o.2 als Aktion erlaubt. Siehe dazu die Konstanten der Klasse.");
}
}
public static synchronized MovementService getService() {
if (instance == null) {
instance = new MovementService();
}
return instance;
}
}