TaskManager bug fixes and code cleanup

This commit is contained in:
Евгений Смирнов 2021-07-07 17:02:38 +03:00
parent 5a06788652
commit f520d4b2c6
4 changed files with 120 additions and 106 deletions

View File

@ -15,9 +15,10 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package ru.windcorp.progressia.client.audio; package ru.windcorp.progressia.client.audio;
import org.apache.logging.log4j.LogManager;
import ru.windcorp.progressia.common.modules.Module; import ru.windcorp.progressia.common.modules.Module;
import ru.windcorp.progressia.common.modules.Task; import ru.windcorp.progressia.common.modules.Task;
import ru.windcorp.progressia.common.modules.TaskManager; import ru.windcorp.progressia.common.modules.TaskManager;
@ -29,10 +30,12 @@ public class AudioSystem {
AudioManager.initAL(); AudioManager.initAL();
Thread shutdownHook = new Thread(AudioManager::closeAL, "AL Shutdown Hook"); Thread shutdownHook = new Thread(AudioManager::closeAL, "AL Shutdown Hook");
Runtime.getRuntime().addShutdownHook(shutdownHook); Runtime.getRuntime().addShutdownHook(shutdownHook);
Task t = new Task("Task:InitializeAudio") {
Task t = new Task("AudioSystem:Initialize") {
@Override @Override
protected void perform() { protected void perform() {
loadAudioData(); loadAudioData();
LogManager.getLogger().info("Audio data is loaded");
} }
}; };
audioModule.addTask(t); audioModule.addTask(t);
@ -41,9 +44,9 @@ public class AudioSystem {
static void loadAudioData() { static void loadAudioData() {
AudioManager.loadSound( AudioManager.loadSound(
ResourceManager.getResource("assets/sounds/block_destroy_clap.ogg"), ResourceManager.getResource("assets/sounds/block_destroy_clap.ogg"),
"Progressia:BlockDestroy", "Progressia:BlockDestroy",
AudioFormat.MONO AudioFormat.MONO
); );
} }
} }

View File

@ -1,34 +1,35 @@
package ru.windcorp.progressia.common.modules; package ru.windcorp.progressia.common.modules;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
public class Module extends Namespaced { public class Module extends Namespaced {
private final List<Task> tasks = new ArrayList<>(); private final List<Task> tasks = new ArrayList<>();
private final Map<String, String> meta = new HashMap<>(); private final Map<String, String> meta = new HashMap<>();
private final boolean done = false; private final boolean done = false;
public Module(String id) { public Module(String id) {
super(id); super(id);
} }
public Map<String, String> getMeta() { public Map<String, String> getMeta() {
return meta; return meta;
} }
public List<Task> getTasks() { public List<Task> getTasks() {
return tasks; return tasks;
} }
public void addTask(Task task) { public void addTask(Task task) {
tasks.add(task); tasks.add(task);
} }
/** /**
* @return false - not all tasks are done * @return false - not all tasks are done
*/ */
@ -38,7 +39,7 @@ public class Module extends Namespaced {
return false; return false;
} }
} }
return true; return true;
} }
} }

View File

@ -5,15 +5,13 @@ import ru.windcorp.progressia.common.util.namespaces.Namespaced;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public abstract class Task public abstract class Task
extends Namespaced extends Namespaced
implements Runnable implements Runnable {
{
List<Task> requiredTasks = new ArrayList<>();
private boolean isDone = false; private boolean isDone = false;
private boolean isActive = false; private boolean isActive = false;
List<Task> requiredTasks = new ArrayList<>();
protected Task(String id) { protected Task(String id) {
super(id); super(id);
@ -28,13 +26,15 @@ public abstract class Task
// This method will be invoked by Run() // This method will be invoked by Run()
protected abstract void perform(); protected abstract void perform();
public boolean isDone() { public boolean isDone() {
return isDone; return isDone;
} }
public boolean isActive() { return isActive; } public boolean isActive() {
return isActive;
}
public boolean canRun() { public boolean canRun() {
if (this.isActive) return false; if (this.isActive) return false;
for (Task reqT : requiredTasks) { for (Task reqT : requiredTasks) {
@ -42,8 +42,12 @@ public abstract class Task
} }
return true; return true;
} }
public List<Task> getRequiredTasks() { public List<Task> getRequiredTasks() {
return requiredTasks; return requiredTasks;
} }
public void addRequiredTask(Task task) {
requiredTasks.add(task);
}
} }

View File

@ -1,101 +1,107 @@
package ru.windcorp.progressia.common.modules; package ru.windcorp.progressia.common.modules;
import ru.windcorp.progressia.common.state.StateFieldBuilder;
import org.apache.logging.log4j.LogManager;
import ru.windcorp.progressia.common.util.crash.CrashReports;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.*; import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import static java.util.concurrent.Executors.newFixedThreadPool; import static java.util.concurrent.Executors.newFixedThreadPool;
public class TaskManager { public class TaskManager {
private static final TaskManager instance = new TaskManager(); private static final TaskManager instance = new TaskManager();
private final List<Task> tasks = new ArrayList<>(); private final List<Task> tasks = new ArrayList<>();
private final List<Module> modules = new ArrayList<>(); private final List<Module> modules = new ArrayList<>();
private boolean loadingDone; private final ExecutorService executorService;
private int activeThreadsCount; private final AtomicBoolean loadingDone;
private final AtomicInteger activeThreadsCount;
private final ExecutorService executorService; private TaskManager() {
loadingDone = new AtomicBoolean(false);
activeThreadsCount = new AtomicInteger(0);
executorService = newFixedThreadPool(
Runtime.getRuntime().availableProcessors(), Thread::new);
}
private TaskManager() { public static TaskManager getInstance() {
loadingDone = false; return instance;
activeThreadsCount = 0; }
executorService = newFixedThreadPool(
Runtime.getRuntime().availableProcessors(), Thread::new);
}
public static TaskManager getInstance() {
return instance;
}
public void registerModule(Module module) { public void registerModule(Module module) {
tasks.addAll(module.getTasks()); tasks.addAll(module.getTasks());
modules.add(module); modules.add(module);
} }
public boolean isLoadingDone() { public boolean isLoadingDone() {
return loadingDone; return loadingDone.get();
} }
public void startLoading() { 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();
t.run();
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();
}
}
}
});
}
for(int i = 0; i < Runtime.getRuntime().availableProcessors(); i++) { waitForLoadingEnd();
executorService.submit(() -> { if (!tasks.isEmpty()) {
while(!loadingDone) { throw CrashReports.crash(new Exception("Loading is failed"), "");
Task t = getRunnableTask(); }
if (t != null) { LogManager.getLogger().info("Loading is finished");
synchronized (this) { executorService.shutdownNow();
activeThreadsCount++; }
}
t.run();
synchronized (this) {
activeThreadsCount--;
notifyAll();
}
} else if (activeThreadsCount > 0) {
try {
synchronized (this) {
this.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
synchronized (this) {
loadingDone = true;
}
}
}
});
}
waitForLoadingEnd(); public synchronized Task getRunnableTask() {
executorService.shutdownNow(); if (!tasks.isEmpty()) {
} for (Task t :
tasks) {
if (t.canRun()) {
tasks.remove(t);
return t;
}
}
}
return null;
}
public synchronized Task getRunnableTask() { private void waitForLoadingEnd() {
if(!tasks.isEmpty()) { synchronized (this) {
for (Task t : while (!loadingDone.get()) {
tasks) { try {
if(t.canRun()) { this.wait();
tasks.remove(t); } catch (InterruptedException e) {
return t; e.printStackTrace();
} }
} }
} }
return null; }
}
private void waitForLoadingEnd() {
synchronized (this) {
while(!loadingDone) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
} }