diff --git a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java index 4057796..c8935fc 100644 --- a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java +++ b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java @@ -18,7 +18,6 @@ package ru.windcorp.progressia; -import ru.windcorp.progressia.common.modules.TaskManager; import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.crash.analyzers.OutOfMemoryAnalyzer; import ru.windcorp.progressia.common.util.crash.providers.*; diff --git a/src/main/java/ru/windcorp/progressia/client/audio/AudioSystem.java b/src/main/java/ru/windcorp/progressia/client/audio/AudioSystem.java index 1747134..db64833 100644 --- a/src/main/java/ru/windcorp/progressia/client/audio/AudioSystem.java +++ b/src/main/java/ru/windcorp/progressia/client/audio/AudioSystem.java @@ -31,13 +31,14 @@ public class AudioSystem { Thread shutdownHook = new Thread(AudioManager::closeAL, "AL Shutdown Hook"); Runtime.getRuntime().addShutdownHook(shutdownHook); - Task t = new Task("AudioSystem:Initialize", audioModule) { + Task t = new Task("AudioSystem:Initialize") { @Override protected void perform() { loadAudioData(); LogManager.getLogger().info("Audio data is loaded"); } }; + audioModule.addTask(t); TaskManager.getInstance().registerModule(audioModule); } diff --git a/src/main/java/ru/windcorp/progressia/common/modules/Module.java b/src/main/java/ru/windcorp/progressia/common/modules/Module.java index 235da24..4d185ed 100644 --- a/src/main/java/ru/windcorp/progressia/common/modules/Module.java +++ b/src/main/java/ru/windcorp/progressia/common/modules/Module.java @@ -25,8 +25,6 @@ public class Module extends Namespaced { private final Set tasks = new HashSet<>(); private final Map meta = new HashMap<>(); - private final Map unmodifiableMeta = Collections.unmodifiableMap(meta); - private final Set unmodifiableTasks = Collections.unmodifiableSet(tasks); /** * @param id the identifier of a task object. @@ -42,11 +40,11 @@ public class Module extends Namespaced { * @return meta information of the module as {@link Map}. */ public Map getMeta() { - return unmodifiableMeta; + return Collections.unmodifiableMap(meta); } public Set getTasks() { - return unmodifiableTasks; + return Collections.unmodifiableSet(tasks); } /** diff --git a/src/main/java/ru/windcorp/progressia/common/modules/Task.java b/src/main/java/ru/windcorp/progressia/common/modules/Task.java index 2100da7..54b4523 100644 --- a/src/main/java/ru/windcorp/progressia/common/modules/Task.java +++ b/src/main/java/ru/windcorp/progressia/common/modules/Task.java @@ -21,9 +21,7 @@ import ru.windcorp.jputil.chars.StringUtil; import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.namespaces.Namespaced; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; +import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; public abstract class Task @@ -40,28 +38,18 @@ public abstract class Task * Its format is restricted by {@link Namespaced}. * @see Namespaced#Namespaced */ - public Task(String id) { + protected Task(String id) { super(id); } - /** - * @param id the identifier of a task object. - * Its format is restricted by {@link Namespaced}. - * @param module to which the task will be attached. - * @see Namespaced#Namespaced - */ - public Task(String id, Module module) { - this(id); - module.addTask(this); - } - @Override public void run() { if (!canRun()) { - ArrayList undoneTasks = new ArrayList<>(); - for (Task j : requiredTasks) { - if (!j.isDone()) { - undoneTasks.add(j); + List undoneTasks = new ArrayList<>(); + for (Iterator iterator = requiredTasks.iterator(); iterator.hasNext(); ) { + Task t = iterator.next(); + if (!t.isDone()) { + undoneTasks.add(t); } } @@ -103,14 +91,15 @@ public abstract class Task */ public boolean canRun() { if (this.isActive.get() || isDone.get()) return false; - for (Task reqT : requiredTasks) { - if (!reqT.isDone()) return false; + for (Iterator iterator = requiredTasks.iterator(); iterator.hasNext(); ) { + Task reqTask = iterator.next(); + if (!reqTask.isDone()) return false; } return true; } public Set getRequiredTasks() { - return requiredTasks; + return Collections.unmodifiableSet(requiredTasks); } public void addRequiredTask(Task task) { @@ -130,10 +119,10 @@ public abstract class Task */ public void setOwner(Module module) { if (owner != null) { - CrashReports.crash( - new Throwable() + throw CrashReports.crash( + null , "Could not set %s as owner of %s, because %s is already owner of it.", - module.getId(), this.getId(), this.getOwner().getId()); + module.getId(), this.getId(), this.owner.getId()); } else { owner = module; } diff --git a/src/main/java/ru/windcorp/progressia/common/modules/TaskManager.java b/src/main/java/ru/windcorp/progressia/common/modules/TaskManager.java index e2d8bcb..275c136 100644 --- a/src/main/java/ru/windcorp/progressia/common/modules/TaskManager.java +++ b/src/main/java/ru/windcorp/progressia/common/modules/TaskManager.java @@ -19,6 +19,7 @@ package ru.windcorp.progressia.common.modules; import org.apache.logging.log4j.LogManager; import ru.windcorp.progressia.common.util.crash.CrashReports; +import ru.windcorp.progressia.common.util.namespaces.Namespaced; import java.util.*; import java.util.concurrent.ExecutorService; @@ -27,18 +28,17 @@ import java.util.concurrent.atomic.AtomicInteger; import static java.util.concurrent.Executors.newFixedThreadPool; -public class TaskManager { - private static final TaskManager instance = new TaskManager(); +public final class TaskManager { + private static final TaskManager INSTANCE = new TaskManager(); private final Set tasks = new HashSet<>(); private final Set modules = new HashSet<>(); private final ExecutorService executorService; - private final AtomicBoolean loadingDone; - private final AtomicInteger activeThreadsCount; + final AtomicBoolean loadingDone; + final AtomicInteger activeThreadsCount; - private final Map loadersMonitorMap; - Map unmodifiableLoadersMonitorMap; + private final Map loadersMonitorMap; private TaskManager() { loadingDone = new AtomicBoolean(false); @@ -46,11 +46,10 @@ public class TaskManager { executorService = newFixedThreadPool( Runtime.getRuntime().availableProcessors(), Thread::new); loadersMonitorMap = new HashMap<>(Runtime.getRuntime().availableProcessors()); - unmodifiableLoadersMonitorMap = Collections.unmodifiableMap(loadersMonitorMap); } public static TaskManager getInstance() { - return instance; + return TaskManager.INSTANCE; } /** @@ -83,40 +82,14 @@ public class TaskManager { */ public void startLoading() { LogManager.getLogger().info("Loading is started"); - for (int i = 0; i < Runtime.getRuntime().availableProcessors(); i++) { - executorService.submit(() -> { - while (!loadingDone.get()) { - Task t = getRunnableTask(); - if (t != null) { - activeThreadsCount.incrementAndGet(); - loadersMonitorMap.put(Thread.currentThread(), t); - t.run(); - loadersMonitorMap.put(Thread.currentThread(), null); - activeThreadsCount.decrementAndGet(); - synchronized (this) { - notifyAll(); - } - } else if (activeThreadsCount.get() > 0) { - try { - synchronized (this) { - this.wait(); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } else { - loadingDone.set(true); - synchronized (this) { - notifyAll(); - } - } - } - }); + int procAmount = Runtime.getRuntime().availableProcessors(); + for (int i = 0; i < procAmount; i++) { + executorService.submit(loaderTask); } waitForLoadingEnd(); if (!tasks.isEmpty()) { - throw CrashReports.crash(new Exception("Loading is failed"), ""); + throw CrashReports.crash(null, "Loading is failed"); } LogManager.getLogger().info("Loading is finished"); executorService.shutdownNow(); @@ -125,12 +98,12 @@ public class TaskManager { /** * @return Task - founded registered task with {@link Task#canRun()} = true; * null - there is no available task found. - * @see Task#canRun() + * @see Task#canRun() */ - private synchronized Task getRunnableTask() { + synchronized Task getRunnableTask() { if (!tasks.isEmpty()) { - for (Task t : - tasks) { + for (Iterator iterator = tasks.iterator(); iterator.hasNext(); ) { + Task t = iterator.next(); if (t.canRun()) { tasks.remove(t); return t; @@ -145,24 +118,56 @@ public class TaskManager { * to wait until the loading is not done. */ private void waitForLoadingEnd() { - synchronized (this) { + synchronized (tasks) { while (!loadingDone.get()) { try { - this.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } + tasks.wait(); + } catch (InterruptedException ignored) {} } } } + private void stopLoading() { + loadingDone.set(true); + synchronized (tasks) { + tasks.notifyAll(); + } + } + /** * @return a map where key is a thread making loading - * and where value is a task that is being performed by it + * and where value is a {@link Namespaced} of {@link Task} that is being performed by it * at the moment. + * @see Namespaced */ - public Map getLoadersMonitorMap() { - return unmodifiableLoadersMonitorMap; + public Map getLoadersMonitorMap() { + return Collections.unmodifiableMap(loadersMonitorMap); } + private final Runnable loaderTask = new Runnable() { + @Override + public void run() { + while (!loadingDone.get()) { + Task t = getRunnableTask(); + if (t != null) { + activeThreadsCount.incrementAndGet(); + loadersMonitorMap.put(Thread.currentThread(), t); + t.run(); + loadersMonitorMap.put(Thread.currentThread(), null); + activeThreadsCount.decrementAndGet(); + synchronized (tasks) { + tasks.notifyAll(); + } + } else if (activeThreadsCount.get() > 0) { + try { + synchronized (tasks) { + tasks.wait(); + } + } catch (InterruptedException ignored) {} + } else { + stopLoading(); + } + } + } + }; }