C
cppaddict
Assume events are being generated by players in a game. They must be
processed in order: player 1, player 2, etc. Our application, on the
other hand, is receiving them at somewhat arbitrary times. If it
receives player 2's event before player 1's, it must hold off on
processing player 2's event. In addition, if it has not received
player 1's event after a specified amount of time (after having
already received player 2's event), it should throw an error.
Below is a sample program which generates test events and processes
them. It works, but I'd like advice on how to improve its design. I
thought that maybe Doug Lea's concurrent package had some classes that
might be appropriate here.
It seems like a lot of code, but it's pretty simple. Also, then Event
and EventGenerator classes are just for creating test events, so there
not really part of the critique I'm looking for.
Thanks in advance,
cpp
PS: If you save the code below in a single file called
"EventProcessor.java", it will compile and run.
-----CODE FOLLOWS-----
import java.util.LinkedList;
import java.util.ListIterator;
class ThreadPauser {
int mPlayer;
public ThreadPauser (int i) {
mPlayer = i;
}
public synchronized void stop() {
System.out.println(mPlayer + " waiting...");
try { wait(10); }
catch (InterruptedException ignore) {}
System.out.println(mPlayer + " waking...");
}
public synchronized void start() {
notifyAll();
}
}
public class EventProcessor {
private LinkedList mPlayersToProcess;
private LinkedList mReceivedEvents;
private ThreadPauser[] mThreadPausers;
private long mTimeBenchmark;
public EventProcessor() {
mTimeBenchmark = System.currentTimeMillis();
mPlayersToProcess = new LinkedList();
mReceivedEvents = new LinkedList();
mThreadPausers = new ThreadPauser[10];
for (int i=0; i<10; i++) {
mPlayersToProcess.add(new Integer(i));
mThreadPausers = new ThreadPauser(i);
}
}
public void processEvent(Event e) {
mReceivedEvents.add(e);
int firstInLine = ( (Integer)
mPlayersToProcess.getFirst() ).intValue();
if (e.mPlayer == firstInLine) {
System.out.println("Event for position " +
e.mPlayer + " at time " + e.mTime + " -- time now = " +
(System.currentTimeMillis() - mTimeBenchmark));
mPlayersToProcess.removeFirst();
int nextInLine = (firstInLine + 1) % 10;
mThreadPausers[nextInLine].start();
}
else {
mThreadPausers[e.mPlayer].stop();
processEvent(e,true);
}
}
private void processEvent(Event e, boolean recursive) {
int firstInLine = ( (Integer)
mPlayersToProcess.getFirst() ).intValue();
if (e.mPlayer == firstInLine)
processEvent(e);
else if (haveReceivedPrecedingEvents(e.mPlayer)) {
mThreadPausers[e.mPlayer].stop();
processEvent(e,true);
}
else {
System.out.println("error!");
}
}
private boolean haveReceivedPrecedingEvents(int
playerPosition) {
ListIterator neededPlayersIter =
mPlayersToProcess.listIterator(0);
while (neededPlayersIter.hasNext()) {
int testPlayer = ( (Integer)
neededPlayersIter.next() ).intValue();
ListIterator receivedEventsIter =
mReceivedEvents.listIterator(0);
boolean gotNeededPosition = false;
while (receivedEventsIter.hasNext()) {
int thisPlayer = ((Event)
receivedEventsIter.next()).mPlayer;
if (thisPlayer == testPlayer) {
gotNeededPosition = true;
break;
}
}
if (!gotNeededPosition)
return false;
}
return true;
}
public static void main(String[] args) {
EventProcessor myProcessor = new EventProcessor();
Thread threads[] = new Thread[10];
//create the threads
for (int i=0; i<10; i++)
threads = new Thread(new
EventGenerator(myProcessor,i));
//start the threads
for (int i=0; i<10; i++)
threads.start();
}
}
/***********************************
* Event and Event Generator
* ***********************************/
class Event {
//these are public just for convenience, since this is a test
public int mPlayer;
public int mTime;
public Event(int player, int time) {
mPlayer = player;
mTime = time;
}
}
class EventGenerator implements Runnable {
private int mPosition;
private EventProcessor mEventProcessor;
public EventGenerator(EventProcessor ep, int pos) {
mEventProcessor = ep;
mPosition = pos;
}
public void run() {
int sleepTime = (int) (10*Math.random()) ;
try { Thread.currentThread().sleep( sleepTime ); }
catch (InterruptedException ignore) {}
mEventProcessor.processEvent(new
Event(mPosition,sleepTime));
}
}
processed in order: player 1, player 2, etc. Our application, on the
other hand, is receiving them at somewhat arbitrary times. If it
receives player 2's event before player 1's, it must hold off on
processing player 2's event. In addition, if it has not received
player 1's event after a specified amount of time (after having
already received player 2's event), it should throw an error.
Below is a sample program which generates test events and processes
them. It works, but I'd like advice on how to improve its design. I
thought that maybe Doug Lea's concurrent package had some classes that
might be appropriate here.
It seems like a lot of code, but it's pretty simple. Also, then Event
and EventGenerator classes are just for creating test events, so there
not really part of the critique I'm looking for.
Thanks in advance,
cpp
PS: If you save the code below in a single file called
"EventProcessor.java", it will compile and run.
-----CODE FOLLOWS-----
import java.util.LinkedList;
import java.util.ListIterator;
class ThreadPauser {
int mPlayer;
public ThreadPauser (int i) {
mPlayer = i;
}
public synchronized void stop() {
System.out.println(mPlayer + " waiting...");
try { wait(10); }
catch (InterruptedException ignore) {}
System.out.println(mPlayer + " waking...");
}
public synchronized void start() {
notifyAll();
}
}
public class EventProcessor {
private LinkedList mPlayersToProcess;
private LinkedList mReceivedEvents;
private ThreadPauser[] mThreadPausers;
private long mTimeBenchmark;
public EventProcessor() {
mTimeBenchmark = System.currentTimeMillis();
mPlayersToProcess = new LinkedList();
mReceivedEvents = new LinkedList();
mThreadPausers = new ThreadPauser[10];
for (int i=0; i<10; i++) {
mPlayersToProcess.add(new Integer(i));
mThreadPausers = new ThreadPauser(i);
}
}
public void processEvent(Event e) {
mReceivedEvents.add(e);
int firstInLine = ( (Integer)
mPlayersToProcess.getFirst() ).intValue();
if (e.mPlayer == firstInLine) {
System.out.println("Event for position " +
e.mPlayer + " at time " + e.mTime + " -- time now = " +
(System.currentTimeMillis() - mTimeBenchmark));
mPlayersToProcess.removeFirst();
int nextInLine = (firstInLine + 1) % 10;
mThreadPausers[nextInLine].start();
}
else {
mThreadPausers[e.mPlayer].stop();
processEvent(e,true);
}
}
private void processEvent(Event e, boolean recursive) {
int firstInLine = ( (Integer)
mPlayersToProcess.getFirst() ).intValue();
if (e.mPlayer == firstInLine)
processEvent(e);
else if (haveReceivedPrecedingEvents(e.mPlayer)) {
mThreadPausers[e.mPlayer].stop();
processEvent(e,true);
}
else {
System.out.println("error!");
}
}
private boolean haveReceivedPrecedingEvents(int
playerPosition) {
ListIterator neededPlayersIter =
mPlayersToProcess.listIterator(0);
while (neededPlayersIter.hasNext()) {
int testPlayer = ( (Integer)
neededPlayersIter.next() ).intValue();
ListIterator receivedEventsIter =
mReceivedEvents.listIterator(0);
boolean gotNeededPosition = false;
while (receivedEventsIter.hasNext()) {
int thisPlayer = ((Event)
receivedEventsIter.next()).mPlayer;
if (thisPlayer == testPlayer) {
gotNeededPosition = true;
break;
}
}
if (!gotNeededPosition)
return false;
}
return true;
}
public static void main(String[] args) {
EventProcessor myProcessor = new EventProcessor();
Thread threads[] = new Thread[10];
//create the threads
for (int i=0; i<10; i++)
threads = new Thread(new
EventGenerator(myProcessor,i));
//start the threads
for (int i=0; i<10; i++)
threads.start();
}
}
/***********************************
* Event and Event Generator
* ***********************************/
class Event {
//these are public just for convenience, since this is a test
public int mPlayer;
public int mTime;
public Event(int player, int time) {
mPlayer = player;
mTime = time;
}
}
class EventGenerator implements Runnable {
private int mPosition;
private EventProcessor mEventProcessor;
public EventGenerator(EventProcessor ep, int pos) {
mEventProcessor = ep;
mPosition = pos;
}
public void run() {
int sleepTime = (int) (10*Math.random()) ;
try { Thread.currentThread().sleep( sleepTime ); }
catch (InterruptedException ignore) {}
mEventProcessor.processEvent(new
Event(mPosition,sleepTime));
}
}