Diaboli
April 7th, 2011, 00:37
After adding grahams new event manager for two people that needed help, I decided a few mins back to just quickly update his old one. (Now there is no reason for me to sit here and divide numbers by 600 in my head :P).
Anyway here you all go.
Ready to be copied into PI / emulous.
FIXED A SLIGHT ERROR. RE-ADD THIS IF YOU ADDED EARLIER.
package server.event;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 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;
/**
* A list of events that are being executed.
*/
private List<EventContainer> events;
/**
* A queue of events that still need to be added.
*/
private Queue<EventContainer> newEvents;
/**
* The {@link ScheduledExecutorService} which schedules calls to the
* {@link #run()} method.
*/
private final ScheduledExecutorService logicService;
/**
* Initialize the event manager.
*/
private EventManager() {
logicService = Executors.newSingleThreadScheduledExecutor();
events = new ArrayList<EventContainer>();
newEvents = new ArrayDeque<EventContainer>();
logicService.scheduleAtFixedRate(this, 0, 600, TimeUnit.MILLISECONDS);
}
/**
* 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();
}
return singleton;
}
/**
* Initializes the event manager (if it needs to be).
*/
public static void initialise() {
getSingleton();
}
@Override
/**
* Processes events. Works kinda like newer versions of cron.
*/
public void run() {
synchronized (newEvents) {
EventContainer event;
while ((event = newEvents.poll()) != null)
events.add(event);
}
// process all events
for (Iterator<EventContainer> it = events.iterator(); it.hasNext();) {
EventContainer container = it.next();
if (container.isRunning()) {
if ((System.currentTimeMillis() - container.getLastRun()) >= container.getTick()) {
container.execute();
}
} else {
// remove events that have completed
it.remove();
}
}
}
/**
* Adds an event.
* @param event The event to add.
* @param tick The tick time.
*/
public void addEvent(Event event, int tick) {
synchronized (newEvents) {
newEvents.add(new EventContainer(event, tick));
}
}
/**
* Shuts the event manager down.
*/
public void shutdown() {
logicService.shutdown();
}
}
Ready to be copied into shards. Slightly older, was the first one I did, was for a friends project on shards.
package com.rs.worldserver.events;
//Shard Revolutions Generic MMORPG Server
//Copyright (C) 2008 Graham Edgecombe
//This program 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 3 of the License, or
//(at your option) any later version.
//This program 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 this program. If not, see <Only the registered members can see the link.>.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import com.rs.worldserver.Server;
/**
* 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 {@link ScheduledExecutorService} which schedules calls to the
* {@link #run()} method.
*/
private final ScheduledExecutorService logicService = Executors.newSingleThreadScheduledExecutor();
/**
* A list of events that are being executed.
*/
private List<EventContainer> events;
/**
* A list of events to add.
*/
private List<EventContainer> eventsToAdd;
/**
* A list of events to remove.
*/
private List<EventContainer> remove;
/**
* Initialise the event manager.
*/
private EventManager() {
events = new ArrayList<EventContainer>();
eventsToAdd = new ArrayList<EventContainer>();
remove = new ArrayList<EventContainer>();
logicService.scheduleAtFixedRate(this, 0, 600, TimeUnit.MILLISECONDS);
}
/**
* 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();
}
return singleton;
}
/**
* Initialises the event manager (if it needs to be).
*/
public static void initialise() {
getSingleton();
}
/**
* Have we shutdown?
*/
private boolean isShutdown = false;
/**
* Toggle shutdown.
*/
private boolean toggleShutdown = false;
/**
* Processes events. Works kinda like newer versions of cron.
*/
@Override
public void run() {
if (toggleShutdown) {
isShutdown = true;
return;
}
if (!isShutdown) {
synchronized (eventsToAdd) {
for (EventContainer c : eventsToAdd) {
events.add(c);
}
eventsToAdd.clear();
}
// Log.debug(Log.MAIN, "Executing events");
// process all events
for (EventContainer container : events) {
if (container.isRunning()) {
if ((System.nanoTime() / 1000000L - container.getLastRun()) >= container.getTick()) {
try {
synchronized (Server.gameLogicLock) {
container.execute();
}
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
// add to remove list
remove.add(container);
}
}
// remove events that have completed
for (EventContainer container : remove) {
events.remove(container);
}
remove.clear();
} else {
System.out.println("Event manager shut down.");
if (Server.getIoThread().isShutdown()) {
System.exit(0);
}
}
}
/**
* Adds an event.
* @param object The owner.
* @param event The event to add.
* @param tick The tick time.
*/
public void addEvent(Object owner, Event event, int tick) {
synchronized (eventsToAdd) {
eventsToAdd.add(new EventContainer(owner, event, tick));
}
}
/**
* Stops events
* @param object The owner.
*/
public void stopEvents(Object owner) {
synchronized (events) {
for (EventContainer container : events) {
if (container.getOwner() == owner) {
container.stop();
}
}
}
}
/**
* Shuts the event manager down.
*/
public void shutdown() {
logicService.shutdown();
toggleShutdown = true;
}
/**
* Have we shutdown?
* @return
*/
public boolean isShutdown() {
return isShutdown;
}
public int getEventCount() {
synchronized (events) {
return events.size();
}
}
}
I ask no rep for this. I also take no credit for this.
* If you wish to avoid synchronization problems, you can run your main server tick with an event.
Anyway here you all go.
Ready to be copied into PI / emulous.
FIXED A SLIGHT ERROR. RE-ADD THIS IF YOU ADDED EARLIER.
package server.event;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 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;
/**
* A list of events that are being executed.
*/
private List<EventContainer> events;
/**
* A queue of events that still need to be added.
*/
private Queue<EventContainer> newEvents;
/**
* The {@link ScheduledExecutorService} which schedules calls to the
* {@link #run()} method.
*/
private final ScheduledExecutorService logicService;
/**
* Initialize the event manager.
*/
private EventManager() {
logicService = Executors.newSingleThreadScheduledExecutor();
events = new ArrayList<EventContainer>();
newEvents = new ArrayDeque<EventContainer>();
logicService.scheduleAtFixedRate(this, 0, 600, TimeUnit.MILLISECONDS);
}
/**
* 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();
}
return singleton;
}
/**
* Initializes the event manager (if it needs to be).
*/
public static void initialise() {
getSingleton();
}
@Override
/**
* Processes events. Works kinda like newer versions of cron.
*/
public void run() {
synchronized (newEvents) {
EventContainer event;
while ((event = newEvents.poll()) != null)
events.add(event);
}
// process all events
for (Iterator<EventContainer> it = events.iterator(); it.hasNext();) {
EventContainer container = it.next();
if (container.isRunning()) {
if ((System.currentTimeMillis() - container.getLastRun()) >= container.getTick()) {
container.execute();
}
} else {
// remove events that have completed
it.remove();
}
}
}
/**
* Adds an event.
* @param event The event to add.
* @param tick The tick time.
*/
public void addEvent(Event event, int tick) {
synchronized (newEvents) {
newEvents.add(new EventContainer(event, tick));
}
}
/**
* Shuts the event manager down.
*/
public void shutdown() {
logicService.shutdown();
}
}
Ready to be copied into shards. Slightly older, was the first one I did, was for a friends project on shards.
package com.rs.worldserver.events;
//Shard Revolutions Generic MMORPG Server
//Copyright (C) 2008 Graham Edgecombe
//This program 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 3 of the License, or
//(at your option) any later version.
//This program 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 this program. If not, see <Only the registered members can see the link.>.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import com.rs.worldserver.Server;
/**
* 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 {@link ScheduledExecutorService} which schedules calls to the
* {@link #run()} method.
*/
private final ScheduledExecutorService logicService = Executors.newSingleThreadScheduledExecutor();
/**
* A list of events that are being executed.
*/
private List<EventContainer> events;
/**
* A list of events to add.
*/
private List<EventContainer> eventsToAdd;
/**
* A list of events to remove.
*/
private List<EventContainer> remove;
/**
* Initialise the event manager.
*/
private EventManager() {
events = new ArrayList<EventContainer>();
eventsToAdd = new ArrayList<EventContainer>();
remove = new ArrayList<EventContainer>();
logicService.scheduleAtFixedRate(this, 0, 600, TimeUnit.MILLISECONDS);
}
/**
* 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();
}
return singleton;
}
/**
* Initialises the event manager (if it needs to be).
*/
public static void initialise() {
getSingleton();
}
/**
* Have we shutdown?
*/
private boolean isShutdown = false;
/**
* Toggle shutdown.
*/
private boolean toggleShutdown = false;
/**
* Processes events. Works kinda like newer versions of cron.
*/
@Override
public void run() {
if (toggleShutdown) {
isShutdown = true;
return;
}
if (!isShutdown) {
synchronized (eventsToAdd) {
for (EventContainer c : eventsToAdd) {
events.add(c);
}
eventsToAdd.clear();
}
// Log.debug(Log.MAIN, "Executing events");
// process all events
for (EventContainer container : events) {
if (container.isRunning()) {
if ((System.nanoTime() / 1000000L - container.getLastRun()) >= container.getTick()) {
try {
synchronized (Server.gameLogicLock) {
container.execute();
}
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
// add to remove list
remove.add(container);
}
}
// remove events that have completed
for (EventContainer container : remove) {
events.remove(container);
}
remove.clear();
} else {
System.out.println("Event manager shut down.");
if (Server.getIoThread().isShutdown()) {
System.exit(0);
}
}
}
/**
* Adds an event.
* @param object The owner.
* @param event The event to add.
* @param tick The tick time.
*/
public void addEvent(Object owner, Event event, int tick) {
synchronized (eventsToAdd) {
eventsToAdd.add(new EventContainer(owner, event, tick));
}
}
/**
* Stops events
* @param object The owner.
*/
public void stopEvents(Object owner) {
synchronized (events) {
for (EventContainer container : events) {
if (container.getOwner() == owner) {
container.stop();
}
}
}
}
/**
* Shuts the event manager down.
*/
public void shutdown() {
logicService.shutdown();
toggleShutdown = true;
}
/**
* Have we shutdown?
* @return
*/
public boolean isShutdown() {
return isShutdown;
}
public int getEventCount() {
synchronized (events) {
return events.size();
}
}
}
I ask no rep for this. I also take no credit for this.
* If you wish to avoid synchronization problems, you can run your main server tick with an event.