package org.gametrack.util; import java.util.LinkedList; /** *

Title: BFTracker

*

Description: Tracks online Battlefield 1942 games, outputs game records

*

Copyright: Copyright (c) 2003

*

Company: bf1942.gametrack.org

* @author Brian Cairns * @version 1.0 */ // Runs through a task queue, sleeping when not needed public abstract class QueueProcessor extends Thread { protected LinkedList queue = new LinkedList(); // the queue protected String userName; // user supplied name from Thread.setName() private Object obSleepLock = new Object(); // thread sleeps on this when there's nothing to do private volatile boolean bAlive; // thread control Object item; // debugging private int state; private int ST_REM = 1, ST_SLEEP = 2, ST_PROC = 3, ST_ERR = 4; private String[] STATE_NAMES = new String[]{ "UNSET", "REMOVE", "SLEEP", "PROCESS", "ERROR" }; public QueueProcessor( String name ) { userName = name; this.setName( name ); } public String toString() { return userName + "(" + queue.size() + ") " + ( state < 1 || state > 4 ? "Unknown state! " : "" ) + STATE_NAMES[state] + ( state == ST_PROC ? ( " [" + item + "]" ) : " -" ); } /** * Process this queue item. If you have controlled access to the queue * as described under addToQueue(), you can assume queueItem will be * your object type. * @param queueItem */ protected abstract void process( Object queueItem ); /** * This is protected because subclass should really provide a public version * with a custom object type, this will force users to use only one type * and ensure type consistency. * @param obj */ protected void addToQueue( Object item ) { synchronized( queue ) { queue.add( item ); } wake(); } public int getSize() { return queue.size(); } /** * Add to front of queue. * @param obj */ protected void addImmediate( Object item ) { synchronized( queue ) { queue.addFirst( item ); } } /** * Call to kill this thread from running */ public void kill() { bAlive = false; wake(); } /** * Main execution loop */ public void run() { bAlive = true; while( bAlive ) { // pull a score list off the queue, if there is one synchronized ( queue ) { if( queue.size() > 0 ) { state = ST_REM; item = queue.removeFirst(); } else item = null; } if( item == null ) { state = ST_SLEEP; sleep(); } else { try { state = ST_PROC; process( item ); } catch( Exception ex ) { state = ST_ERR; Log.err( "QueueProcessor: " + ex ); Log.debug( "QueueProcessor: " + ex ); ex.printStackTrace(); } } } } // private methods /////////////////////////////////////////////////////////// /** * Wait until notified */ private void sleep() { synchronized( obSleepLock ) { try { obSleepLock.wait(); } catch ( Exception ex ) { } } } /** * Notify sleeping thread */ private void wake() { synchronized( obSleepLock ) { obSleepLock.notifyAll(); } } }