diff --git a/Server/src/main/java/uulm/teamname/marvelous/server/lobbymanager/LobbyRunner.java b/Server/src/main/java/uulm/teamname/marvelous/server/lobbymanager/LobbyRunner.java index a73bf1d..de402c8 100644 --- a/Server/src/main/java/uulm/teamname/marvelous/server/lobbymanager/LobbyRunner.java +++ b/Server/src/main/java/uulm/teamname/marvelous/server/lobbymanager/LobbyRunner.java @@ -1,13 +1,17 @@ package uulm.teamname.marvelous.server.lobbymanager; import org.tinylog.Logger; +import uulm.teamname.marvelous.server.Server; +import uulm.teamname.marvelous.server.lobby.Lobby; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; /** * Class meant for running lobbies. It manages said lobbys, creates threads for it, and moves it into an executor @@ -24,56 +28,59 @@ public class LobbyRunner { } - private final HashMap activeLobbies; + private final ExecutorService lobbyExecutor; + private final HashSet activeLobbies; private LobbyRunner() { - this.activeLobbies = new HashMap<>(); + this.lobbyExecutor = Executors.newFixedThreadPool(Server.getMaxLobbies()); + this.activeLobbies = new HashSet<>(); + } + + boolean canAddLobby() { + return activeLobbies.size() <= Server.getMaxLobbies(); } /** Starts a new thread for the current LobbyConnection, and adds it to the currently active lobbies */ void startLobby(LobbyConnection connection) { Logger.trace("Starting lobby connection thread '{}'", connection.gameID); - synchronized (activeLobbies) { - if (activeLobbies.containsKey(connection)) { - Logger.warn("Already active lobby was started again. This is probably a bug."); - } else { - Logger.trace("Creating lobby thread 'Lobby-{}'...", connection.gameID); - var lobbyThread = new Thread(connection, "Lobby-" + connection.gameID); - Logger.trace("Creating mapping from LobbyConnection to newly created thread"); - activeLobbies.put(connection, lobbyThread); - Logger.debug("Starting new lobby thread '{}'", lobbyThread.getName()); - lobbyThread.start(); - } - } - } - - /** Calls {@link Thread#notify()} on the given lobbyConnection's thread */ - void notifyLobby(LobbyConnection toNotify) { - var lobbyThread = activeLobbies.get(toNotify); - if (lobbyThread == null) { - Logger.warn("Tried to notify non-existent lobby thread. This is probably a bug."); + if (activeLobbies.contains(connection)) { + Logger.warn("Already active lobby was started again. This is probably a bug."); + } else if (!canAddLobby()) { + Logger.warn("Scheduling lobby to be started while no thread is free. This might be a bug."); + activeLobbies.add(connection); + lobbyExecutor.execute(connection); } else { - lobbyThread.notify(); + Logger.trace("Executing LobbyThread 'Lobby-{}'...", connection.gameID); + activeLobbies.add(connection); + lobbyExecutor.execute(connection); } } void removeLobby(LobbyConnection lobby) { synchronized (activeLobbies) { - var lobbyThread = activeLobbies.get(lobby); - if (lobbyThread == null) { + if (!activeLobbies.contains(lobby)) { Logger.warn("Tried to remove non-existent lobby thread. This is probably a bug."); } else { Logger.debug("Stopping and removing lobby '{}'", lobby.gameID); lobby.terminateConnection(); - lobbyThread.notify(); activeLobbies.remove(lobby); } } } + boolean isStarted(LobbyConnection connection) { + return activeLobbies.contains(connection); + } + /** Shutdown all threads, destroy the lobbies, and close everything up */ void shutdownAll() { Logger.info("Stopping and removing all LobbyThreads"); - activeLobbies.keySet().forEach(this::removeLobby); + activeLobbies.forEach(LobbyConnection::terminateConnection); + try { + lobbyExecutor.awaitTermination(5, TimeUnit.SECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } + lobbyExecutor.shutdownNow(); } }