Add lime.system.ThreadPool
This commit is contained in:
240
lime/system/ThreadPool.hx
Normal file
240
lime/system/ThreadPool.hx
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
package lime.system;
|
||||||
|
|
||||||
|
|
||||||
|
import lime.app.Application;
|
||||||
|
import lime.app.Event;
|
||||||
|
|
||||||
|
#if cpp
|
||||||
|
import cpp.vm.Deque;
|
||||||
|
import cpp.vm.Thread;
|
||||||
|
#elseif neko
|
||||||
|
import neko.vm.Deque;
|
||||||
|
import neko.vm.Thread;
|
||||||
|
#end
|
||||||
|
|
||||||
|
|
||||||
|
class ThreadPool {
|
||||||
|
|
||||||
|
|
||||||
|
public var currentThreads (default, null):Int;
|
||||||
|
public var doWork = new Event<String->Dynamic->Void> ();
|
||||||
|
public var maxThreads:Int;
|
||||||
|
public var minThreads:Int;
|
||||||
|
public var onComplete = new Event<String->Dynamic->Void> ();
|
||||||
|
public var onError = new Event<String->Dynamic->Void> ();
|
||||||
|
public var onProgress = new Event<String->Dynamic->Void> ();
|
||||||
|
|
||||||
|
#if (cpp || neko)
|
||||||
|
private var __workCompleted:Int;
|
||||||
|
private var __workIncoming = new Deque<ThreadPoolMessage> ();
|
||||||
|
private var __workQueued:Int;
|
||||||
|
private var __workResult = new Deque<ThreadPoolMessage> ();
|
||||||
|
#end
|
||||||
|
|
||||||
|
|
||||||
|
public function new (minThreads:Int = 0, maxThreads:Int = 1) {
|
||||||
|
|
||||||
|
this.minThreads = minThreads;
|
||||||
|
this.maxThreads = maxThreads;
|
||||||
|
|
||||||
|
currentThreads = 0;
|
||||||
|
|
||||||
|
#if (cpp || neko)
|
||||||
|
__workQueued = 0;
|
||||||
|
__workCompleted = 0;
|
||||||
|
#end
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//public function cancel (id:String):Void {
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
//public function isCanceled (id:String):Bool {
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
public function queue (id:String, message:Dynamic = null):Void {
|
||||||
|
|
||||||
|
#if (cpp || neko)
|
||||||
|
|
||||||
|
__workIncoming.add (new ThreadPoolMessage (WORK, id, message));
|
||||||
|
__workQueued++;
|
||||||
|
|
||||||
|
if (currentThreads < maxThreads) {
|
||||||
|
|
||||||
|
currentThreads++;
|
||||||
|
Thread.create (__doWork);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Application.current.onUpdate.has (__update)) {
|
||||||
|
|
||||||
|
Application.current.onUpdate.add (__update);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
doWork.dispatch (id, message);
|
||||||
|
|
||||||
|
#end
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function sendComplete (id:String, message:Dynamic = null):Void {
|
||||||
|
|
||||||
|
#if (cpp || neko)
|
||||||
|
__workResult.add (new ThreadPoolMessage (COMPLETE, id, message));
|
||||||
|
#else
|
||||||
|
onComplete.dispatch (id, message);
|
||||||
|
#end
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function sendError (id:String, message:Dynamic = null):Void {
|
||||||
|
|
||||||
|
#if (cpp || neko)
|
||||||
|
__workResult.add (new ThreadPoolMessage (ERROR, id, message));
|
||||||
|
#else
|
||||||
|
onError.dispatch (id, message);
|
||||||
|
#end
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function sendProgress (id:String, message:Dynamic = null):Void {
|
||||||
|
|
||||||
|
#if (cpp || neko)
|
||||||
|
__workResult.add (new ThreadPoolMessage (PROGRESS, id, message));
|
||||||
|
#else
|
||||||
|
onProgress.dispatch (id, message);
|
||||||
|
#end
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if (cpp || neko)
|
||||||
|
|
||||||
|
private function __doWork ():Void {
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
var message = __workIncoming.pop (true);
|
||||||
|
|
||||||
|
if (message.type == WORK) {
|
||||||
|
|
||||||
|
doWork.dispatch (message.id, message.message);
|
||||||
|
|
||||||
|
} else if (message.type == EXIT) {
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function __update (deltaTime:Int):Void {
|
||||||
|
|
||||||
|
if (__workQueued > __workCompleted) {
|
||||||
|
|
||||||
|
var message = __workResult.pop (false);
|
||||||
|
|
||||||
|
while (message != null) {
|
||||||
|
|
||||||
|
switch (message.type) {
|
||||||
|
|
||||||
|
case PROGRESS:
|
||||||
|
|
||||||
|
onProgress.dispatch (message.id, message.message);
|
||||||
|
|
||||||
|
case COMPLETE, ERROR:
|
||||||
|
|
||||||
|
__workCompleted++;
|
||||||
|
|
||||||
|
if (currentThreads > (__workQueued - __workCompleted) || currentThreads > maxThreads) {
|
||||||
|
|
||||||
|
currentThreads--;
|
||||||
|
__workIncoming.add (new ThreadPoolMessage (EXIT, null, null));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message.type == COMPLETE) {
|
||||||
|
|
||||||
|
onComplete.dispatch (message.id, message.message);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
onError.dispatch (message.id, message.message);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
message = __workResult.pop (false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// TODO: Add sleep if keeping minThreads running with no work?
|
||||||
|
|
||||||
|
if (currentThreads == 0 && minThreads <= 0) {
|
||||||
|
|
||||||
|
Application.current.onUpdate.remove (__update);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#end
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private enum ThreadPoolMessageType {
|
||||||
|
|
||||||
|
COMPLETE;
|
||||||
|
ERROR;
|
||||||
|
EXIT;
|
||||||
|
PROGRESS;
|
||||||
|
WORK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class ThreadPoolMessage {
|
||||||
|
|
||||||
|
|
||||||
|
public var id:String;
|
||||||
|
public var message:Dynamic;
|
||||||
|
public var type:ThreadPoolMessageType;
|
||||||
|
|
||||||
|
|
||||||
|
public function new (type:ThreadPoolMessageType, id:String, message:Dynamic) {
|
||||||
|
|
||||||
|
this.type = type;
|
||||||
|
this.id = id;
|
||||||
|
this.message = message;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user