61 lines
1.4 KiB
Haxe
61 lines
1.4 KiB
Haxe
package iron.culling;
|
|
|
|
#if (target.threaded)
|
|
|
|
class JobSystem {
|
|
|
|
public static var numWorkers(default, null): Int = 0;
|
|
|
|
static var jobQueue: sys.thread.Deque<Void->Void> = null;
|
|
static var doneLock: sys.thread.Lock = null;
|
|
static var jobError: Dynamic = null;
|
|
|
|
public static function init(workers: Int = 3) {
|
|
if (jobQueue != null) return;
|
|
numWorkers = workers < 1 ? 1 : workers;
|
|
jobQueue = new sys.thread.Deque();
|
|
doneLock = new sys.thread.Lock();
|
|
for (_ in 0...numWorkers) {
|
|
sys.thread.Thread.create(workerLoop);
|
|
}
|
|
}
|
|
|
|
static function workerLoop() {
|
|
while (true) {
|
|
var job = jobQueue.pop(true);
|
|
if (job == null) return;
|
|
try {
|
|
job();
|
|
} catch (e: Dynamic) {
|
|
jobError = e;
|
|
}
|
|
doneLock.release();
|
|
}
|
|
}
|
|
|
|
public static function parallelFor(count: Int, fn: Int -> Int -> Void) {
|
|
init();
|
|
var chunks = numWorkers + 1;
|
|
var chunkSize = Std.int((count + chunks - 1) / chunks);
|
|
if (chunkSize < 1) chunkSize = 1;
|
|
var jobs = 0;
|
|
var start = chunkSize; // Chunk 0 runs on the calling thread
|
|
while (start < count) {
|
|
var s = start;
|
|
var e = start + chunkSize > count ? count : start + chunkSize;
|
|
jobQueue.add(function() fn(s, e));
|
|
jobs++;
|
|
start = e;
|
|
}
|
|
fn(0, chunkSize > count ? count : chunkSize);
|
|
for (_ in 0...jobs) doneLock.wait();
|
|
if (jobError != null) {
|
|
var e = jobError;
|
|
jobError = null;
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
|
|
#end
|