package server.event;


import java.util.ArrayList;
import java.util.List;

/**
 * Manages events which will be run in the future. Has its own thread since some
 * events may need to be ran faster than the cycle time in the main thread.
 * 
 * @author Graham
 * 
 */
public class EventManager implements Runnable {

 /**
  * A reference to the singleton;
  */
 private static EventManager singleton = null;

 /**
  * The waitFor variable is multiplied by this before the call to wait() is
  * made. We do this because other events may be executed after waitFor is
  * set (and take time). We may need to modify this depending on event count?
  * Some proper tests need to be done.
  */
 private static final double WAIT_FOR_FACTOR = 0.5;

 /**
  * Gets the event manager singleton. If there is no singleton, the singleton
  * is created.
  * 
  * @return The event manager singleton.
  */
 public static EventManager getSingleton() {
  if (singleton == null) {
   singleton = new EventManager();
   singleton.thread = new Thread(singleton);
   singleton.thread.start();
  }
  return singleton;
 }

 /**
  * Initialises the event manager (if it needs to be).
  */
 public static void initialize() {
  getSingleton();
 }

 /**
  * A list of events that are being executed.
  */
 private List<EventContainer> events;

 /**
  * The event manager thread. So we can interrupt it and end it nicely on
  * shutdown.
  */
 private Thread thread;

 /**
  * Initialise the event manager.
  */
 private EventManager() {
  events = new ArrayList<EventContainer>();
 }

 /**
  * Adds an event.
  * 
  * @param event
  *            The event to add.
  * @param tick
  *            The tick time.
  */
 public synchronized void addEvent(Event event, int tick) {
  events.add(new EventContainer(event, tick));
  notify();
 }

 @Override
 /*
  * Processes events. Works kinda like newer versions of cron.
  */
 public synchronized void run() {
  long waitFor = -1;
  List<EventContainer> remove = new ArrayList<EventContainer>();

  while (true) {

   // reset wait time
   waitFor = -1;

   // process all events
   for (EventContainer container : events) {
    if (container.isRunning()) {
     if ((System.currentTimeMillis() - container.getLastRun()) >= container
       .getTick()) {
      try {
       container.execute();
      } catch (Exception e){e.printStackTrace();} 
     }
     if (container.getTick() < waitFor || waitFor == -1) {
      waitFor = container.getTick();
     }
    } else {
     // add to remove list
     remove.add(container);
    }
   }

   // remove events that have completed
   for (EventContainer container : remove) {
    events.remove(container);
   }
   remove.clear();

   // no events running
   try {
    if (waitFor == -1) {
     wait(); // wait with no timeout
    } else {
     // an event is running, wait for that time or until a new
     // event is added
     int decimalWaitFor = (int) (Math.ceil(waitFor
       * WAIT_FOR_FACTOR));
     wait(decimalWaitFor);
    }
   } catch (InterruptedException e) {
    break; // stop running
   }
  }
 }

 /**
  * Shuts the event manager down.
  */
 public void shutdown() {
  this.thread.interrupt();
 }

}

Add a code snippet to your website: www.paste.org