package com.jenjinstudios.server.net;
import java.io.IOException;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* A server which executes runnable tasks.
* @author Caleb Brinkman
*/
public class TaskedServer extends Server
{
/** Tasks to be repeated in the main loop. */
private final List<Runnable> repeatedTasks;
/** Synced tasks scheduled by client handlers. */
private final LinkedList<Runnable> syncedTasks;
/** The timer that controls the server loop. */
private ScheduledExecutorService loopTimer;
/** The server loop. */
private ServerUpdateTask serverUpdateTask;
/**
* Construct a new Server without a SQLHandler.
* @throws java.io.IOException If there is an IO Error initializing the server.
* @throws NoSuchMethodException If there is no appropriate constructor for the specified ClientHandler
* constructor.
*/
protected TaskedServer(ServerInit initInfo) throws IOException, NoSuchMethodException {
super(initInfo);
repeatedTasks = new LinkedList<>();
syncedTasks = new LinkedList<>();
}
/**
* Get the start time, in nanoseconds, of the current update cycle.
* @return The cycle start time.
*/
public long getCycleStartTime() {
return serverUpdateTask != null ? serverUpdateTask.getCycleStartTime() : -1;
}
/**
* Add a task to be repeated every update.
* @param r The {@code Runnable} containing the task to be repeated.
*/
protected void addRepeatedTask(Runnable r) {
synchronized (repeatedTasks)
{
repeatedTasks.add(r);
}
}
@Override
public void run() {
super.run();
serverUpdateTask = new ServerUpdateTask(this);
loopTimer = Executors.newSingleThreadScheduledExecutor(new ServerUpdateThreadFactory());
loopTimer.scheduleAtFixedRate(serverUpdateTask, 0, PERIOD, TimeUnit.MILLISECONDS);
}
@Override
public void shutdown() throws IOException {
super.shutdown();
if (loopTimer != null)
loopTimer.shutdown();
}
public double getAverageUPS() { return serverUpdateTask.getAverageUPS(); }
public int getUps() { return UPS; }
public void runRepeatedTasks() {
synchronized (repeatedTasks)
{
for (Runnable r : repeatedTasks) r.run();
}
}
public void runSyncedTasks() {
synchronized (syncedTasks)
{
while (!syncedTasks.isEmpty()) { syncedTasks.remove().run(); }
}
}
/**
* Tasks to be repeated in the main loop.
* @return The list of repeated tasks to be executed by this server.
*/
Iterable<Runnable> getRepeatedTasks() { return repeatedTasks; }
/**
* Synced tasks scheduled by client handlers.
* @return The list of synchronized tasks scheduled by ClientHandlers.
*/
Deque<Runnable> getSyncedTasks() { return syncedTasks; }
}