Chessclock manager

P

potmo

Hi!

Im creating a multiplayer Alfapet (Scrabble in English) and i need
something to handle all the users clocks.
I want one thread to manage all clocks since i guess 500 gametables
with one thread each will be hard on performance. The clock can be
terminated eather when the clock expire or when a player lays bricks
on the table and the turn is passed to the other player. Its like a
chess-clock if you know how they work.

I have made a Clock-Singelton-class where one can add events and when
they expire a callback to a listener is fired.
The clock class runs in one thread and checks every 500ms if an event
has expired. The problem is that im getting a
ConcurrentModificationError all the time.
It seems as addEvent() and run() are modifying the EventList-HashMap
at the same time. I cant get this to work.
I Have been synchronizing about everything and nothing helps.

Here is a code 'snippet' of my code. Thanks in advance.


package se.raketspel.revolution.application.alfapetGame;

import java.util.HashMap;
import java.util.Collections;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Set;
import java.util.Iterator;

/
*******************************************************************************
* A Generic clock than can enque events and call back when the events
expire.
* Events are called at a rate of 500 milliseconds.
*
* @author Nisse Bergman
*
*/
public class Clock extends TimerTask {

private static HashMap<Integer, TimerEvent> EventList = new
HashMap<Integer, TimerEvent>();

private Timer timer;

/
***************************************************************************
* Create a new clock
*
* Here you can modify the rate of whitch the run function is called.
*/
private Clock() {
timer = new Timer("AlfapetClock");
timer.scheduleAtFixedRate(this, 0, 500);
}

/
***************************************************************************
* Gets the instance of the clock if it exsists and creates and gets
it if
* it doesnt.
*
* @return
*/
public static Clock getInstance() {
return OthelloClockSingletonHolder.INSTANCE;
}

/
***************************************************************************
* Private constructor. Since this is an singleton its created by
calling
* the classes getInstance().
*
* @author Nisse Bergman
*
*/
private static class OthelloClockSingletonHolder {

private final static Clock INSTANCE = new Clock();

}

// the top event id. Increments and loops around the max int back to
min
// int.
private int EventID = Integer.MIN_VALUE;

/
***************************************************************************
* Enque a new event.
*
* @param millseconds
* @param CallBackHandler
* @param Event
* @param params
* @return
*/
public synchronized int CreateEvent(long millseconds,
TimerCallbackInterface CallBackHandler, int Event, Object params) {
long t0 = System.currentTimeMillis();
long t1 = t0 + millseconds;
EventID++;
if (EventID > Integer.MAX_VALUE)
EventID = Integer.MIN_VALUE;
TimerEvent o = new TimerEvent((TimerCallbackInterface)
CallBackHandler, Event, params, t1, EventID);

synchronized (this) {
EventList.put(EventID, o);
}

return EventID;
}

/
***************************************************************************
* Flag an event as used and that it should be removed later
*
* @param evID
* @return
*/
public synchronized boolean KillEvent(int evID) {

// flag the events as used and that they should be removed

System.out.println("AlfapetClock - About to kill event " + evID);

if (!EventList.containsKey(evID)) {
System.out.println("------------------------------------------
AlfapetClock Trying to kill a timer event that doesnt exist");
return false;
} else {
EventList.get(evID).isDone = true;
}

return true;
}

/
***************************************************************************
* The main run function. Is called every half second (specified in
private
* Clock() constructor)
*
*/
public synchronized void run() {

// invoke all events and remove them when they are invoked
Map<Integer, TimerEvent> m = Collections.synchronizedMap(EventList);

Iterator<TimerEvent> iterator = m.values().iterator();
synchronized (this) {
while (iterator.hasNext()) {
TimerEvent t = iterator.next();

if ((System.currentTimeMillis() > t.timetoiinvoke) && !(t.isDone))
{
TimerCallbackInterface CallBackHandler = t.CallBackHandler;
CallBackHandler.TimerCallBack(t.Event, t.params);
t.isDone = true;
}

//this is where it fails. Cant understand why.
if (t.isDone) {
iterator.remove();
}
}
}

}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,119
Latest member
IrmaNorcro
Top