154 lines
4.4 KiB
Java
154 lines
4.4 KiB
Java
package electrosphere.engine.threads;
|
|
|
|
import java.util.Collections;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.concurrent.Semaphore;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
import electrosphere.engine.Globals;
|
|
import electrosphere.engine.loadingthreads.LoadingThread;
|
|
import electrosphere.engine.threads.LabeledThread.ThreadLabel;
|
|
import electrosphere.util.CodeUtils;
|
|
|
|
/**
|
|
* Manages all running threads
|
|
*/
|
|
public class ThreadManager {
|
|
|
|
//Threadsafes the manager
|
|
Semaphore threadLock = new Semaphore(1);
|
|
|
|
//All threads that are actively running
|
|
private List<LabeledThread> activeThreads = new LinkedList<LabeledThread>();
|
|
|
|
//All loading threads that are actively running
|
|
private List<LoadingThread> loadingThreads = new LinkedList<LoadingThread>();
|
|
|
|
//Used by main thread to alert other threads whether they should keep running or not
|
|
private boolean shouldKeepRunning = true;
|
|
|
|
|
|
|
|
/**
|
|
* Updates what threads are being tracked
|
|
*/
|
|
public void update(){
|
|
threadLock.acquireUninterruptibly();
|
|
//
|
|
//remove loading threads
|
|
List<Thread> threadsToRemove = new LinkedList<Thread>();
|
|
for(LoadingThread thread : loadingThreads){
|
|
if(thread.isDone()){
|
|
threadsToRemove.add(thread);
|
|
}
|
|
}
|
|
for(Thread thread : threadsToRemove){
|
|
loadingThreads.remove(thread);
|
|
}
|
|
|
|
threadLock.release();
|
|
}
|
|
|
|
/**
|
|
* Starts a new thread with tracking
|
|
* @param thread The thread to start
|
|
*/
|
|
public void start(ThreadLabel label, Thread thread){
|
|
threadLock.acquireUninterruptibly();
|
|
activeThreads.add(new LabeledThread(label, thread));
|
|
thread.start();
|
|
threadLock.release();
|
|
}
|
|
|
|
/**
|
|
* Starts a new loading thread with tracking
|
|
* @param thread The loading thread to start
|
|
*/
|
|
public void start(LoadingThread thread){
|
|
threadLock.acquireUninterruptibly();
|
|
activeThreads.add(new LabeledThread(ThreadLabel.LOADING, thread));
|
|
loadingThreads.add(thread);
|
|
thread.start();
|
|
threadLock.release();
|
|
}
|
|
|
|
/**
|
|
* Checks if any loading threads are active
|
|
* @return true if there is an active loading thread, false otherwise
|
|
*/
|
|
public boolean isLoading(){
|
|
return loadingThreads.size() > 0;
|
|
}
|
|
|
|
/**
|
|
* Gets the list of loading threads
|
|
* @return The list of loading threads
|
|
*/
|
|
public List<LoadingThread> getLoadingThreads(){
|
|
return Collections.unmodifiableList(loadingThreads);
|
|
}
|
|
|
|
/**
|
|
* Tries to close all threads
|
|
*/
|
|
public void close(){
|
|
this.shouldKeepRunning = false;
|
|
threadLock.acquireUninterruptibly();
|
|
|
|
//for some reason, server must be explicitly closed
|
|
if(Globals.server != null){
|
|
Globals.server.close();
|
|
}
|
|
|
|
//
|
|
//interrupt all threads
|
|
for(int i = 0; i < 3; i++){
|
|
for(LabeledThread thread : activeThreads){
|
|
thread.getThread().interrupt();
|
|
try {
|
|
thread.getThread().join(10);
|
|
if(thread.getThread().isAlive()){
|
|
String errorMessage = "Failed to interrupt thread! " + thread.getLabel();
|
|
System.err.println(errorMessage);
|
|
throw new IllegalStateException();
|
|
}
|
|
} catch (InterruptedException e) {
|
|
CodeUtils.todo(e, "Think about how to handle this");
|
|
}
|
|
}
|
|
try {
|
|
TimeUnit.MILLISECONDS.sleep(3);
|
|
} catch (InterruptedException e) {
|
|
CodeUtils.todo(e, "Handle failing to sleep while interrupting all other threads");
|
|
}
|
|
}
|
|
threadLock.release();
|
|
}
|
|
|
|
/**
|
|
* Checks if the thread should keep running or not
|
|
* @return true if should keep running, false otherwise
|
|
*/
|
|
public boolean shouldKeepRunning(){
|
|
return this.shouldKeepRunning;
|
|
}
|
|
|
|
/**
|
|
* Interrupts all thread under a label
|
|
* @param label The label
|
|
*/
|
|
public void interruptLabel(ThreadLabel label){
|
|
threadLock.acquireUninterruptibly();
|
|
//
|
|
//interrupt threads
|
|
for(LabeledThread thread : activeThreads){
|
|
if(thread.getLabel() == label){
|
|
thread.getThread().interrupt();
|
|
}
|
|
}
|
|
threadLock.release();
|
|
}
|
|
|
|
}
|