/*
** This file is part of Filius, a network construction and simulation software.
**
** Originally created at the University of Siegen, Institute "Didactics of
** Informatics and E-Learning" by a students' project group:
** members (2006-2007):
** André Asschoff, Johannes Bade, Carsten Dittich, Thomas Gerding,
** Nadja Haßler, Ernst Johannes Klebert, Michell Weyer
** supervisors:
** Stefan Freischlad (maintainer until 2009), Peer Stechert
** Project is maintained since 2010 by Christian Eibl <filius@c.fameibl.de>
** and Stefan Freischlad
** Filius is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 2 of the License, or
** (at your option) version 3.
**
** Filius is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied
** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
** PURPOSE. See the GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Filius. If not, see <http://www.gnu.org/licenses/>.
*/
package filius.software;
import java.util.LinkedList;
import filius.Main;
/** Diese Klasse ist die Oberklasse von Protokoll-Threads.
* Die Aufgabe ist, den Puffer zu ueberwachen, und die
* Verarbeitung der eingehenden Dateneinheiten zu starten.
*
* @author stefan
*
*/
public abstract class ProtokollThread extends Thread {
/** ob der Thread gerade am laufen ist */
protected boolean running = false;
/** der von dem Thread zu ueberwachende Puffer */
private LinkedList<?> puffer;
/** Leerer Konstruktur, der nur dann genutzt werden darf,
* wenn von diesem Thread kein Puffer ueberwacht werden
* soll. In diesem Fall <b>muss</b> auch die run()-Methode
* ueberschrieben werden!
*/
public ProtokollThread() { }
/** Konstruktur, der ausschliesslich die Initialisierung
* des zu ueberwachenden Puffers uebernimmt, der als
* Parameter uebergeben wird.
* @param puffer der zu ueberwachende Puffer
*/
public ProtokollThread(LinkedList<?> puffer) {
this.puffer = puffer;
}
/** Diese Methode implementiert die Ueberwachung des Puffers
* in einem eigenen Thread. Solange sich keine Dateneinheit in
* dem Puffer befindet, geht der Thread in den wartenden Zustand.
* Wenn eine Dateneinheit eintrifft, wird diese mit dem Aufruf
* der Methode verarbeiteDatenEinheit() zur weiteren Verarbeitung
* weitergegeben.
*/
public void run() {
Main.debug.println("INVOKED ("+this.hashCode()+", T"+this.getId()+") "+getClass()+" (ProtkollThread), run()");
while (running) {
synchronized(puffer){
if(puffer.size() < 1){
try {
puffer.wait();
}
catch (InterruptedException e) { }
}
if(puffer.size() > 0){
verarbeiteDatenEinheit(puffer.removeFirst());
}
}
}
}
/** Diese Methode wird aufgerufen, wenn eine Dateneinheit in dem
* ueberwachten Puffer eintrifft.
* @param datenEinheit die im ueberwachten Puffer eingetroffene
* Dateneinheit
*/
protected abstract void verarbeiteDatenEinheit(Object datenEinheit);
/** Methode fuer den Zugriff auf den zu ueberwachenden Puffer */
protected LinkedList<?> holeEingangsPuffer() {
return puffer;
}
/** Methode zum Starten des Threads beim Wechsel vom Entwurfs-
* in den Aktionsmodus. Wenn sich der Thread noch in einem wartenden
* oder blockierten Zustand wird kein neuer Thread gestartet, sondern
* lediglich gewaehrleistet, dass der Thread nicht beendet wird.
*/
public void starten() {
Main.debug.println("INVOKED ("+this.hashCode()+", T"+this.getId()+") "+getClass()+" (ProtokollThread), starten()");
if (!running) {
running = true;
if (getState().equals(State.WAITING) || getState().equals(State.BLOCKED)) {
//Main.debug.println(getClass()+"\n\tProtokollThread: Thread laeuft bereits.");
}
else {
start();
}
}
}
/** Methode zum Beenden des Threads. Wenn der Thread noch in einem
* wartenden oder blockierten Zustand ist, wird interrupt() aufgerufen,
* um die Verarbeitung fortzusetzen, damit der Thread dann beendet
* werden kann.
*/
public void beenden() {
Main.debug.println("INVOKED ("+this.hashCode()+", T"+this.getId()+") "+getClass()+" (ProtokollThread), beenden()");
running = false;
if (getState().equals(State.WAITING) || getState().equals(State.BLOCKED)) {
interrupt();
}
if (this.puffer != null) this.puffer.clear();
}
}