A thread pool executes one or more functions asynchronously.

In multi-threaded mode, jobs run on background threads. In HTML5, this means using web workers, which impose additional restrictions (see below). In single-threaded mode, jobs run between frames on the main thread. To avoid blocking, these jobs should only do a small amount of work at a time.

In multi-threaded mode, the pool spins up new threads as jobs arrive (up to maxThreads). If too many jobs arrive at once, it places them in a queue to run when threads open up. If you run jobs frequently but not constantly, you can also set minThreads to keep a certain number of threads alive, avoiding the overhead of repeatedly spinning them up.

Sample usage:

var threadPool:ThreadPool = new ThreadPool();
threadPool.onComplete.add(onFileProcessed);

threadPool.maxThreads = 3;
for(url in urls)
{
	threadPool.run(processFile, url);
}

Guidelines to make your code work on all targets and configurations:

  • For thread safety and web worker compatibility, your work function should only return data through the WorkOutput object it receives.
  • For web worker compatibility, you should only send data to your work function via the State object. But since this can be any object, you can put an arbitrary amount of data there.
  • For web worker compatibility, your work function must be static, and you can't bind() any extra arguments.
  • For single-threaded performance, your function should only do a small amount of work at a time. Store progress in the State object so you can pick up where you left off. You don't have to worry about timing: just aim to take a small fraction of the frame's time, and ThreadPool will keep running the function until enough time passes.

Static variables

@:value(1 / 2)staticworkLoad:Float = 1 / 2

A rough estimate of how much of the app's time should be spent on single-threaded ThreadPools. For instance, the default value of 1/2 means they'll use about half the app's available time every frame.

The accuracy of this estimate depends on how often your work functions return. If you find that a ThreadPool is taking longer than scheduled, try making the work function return more often.

Static methods

staticinlineisMainThread():Bool

Returns whether the caller called this function from the main thread.

Constructor

@:value({ mode : null, maxThreads : 1, minThreads : 0 })new(minThreads:Int = 0, maxThreads:Int = 1, ?mode:ThreadMode)

Call this only from the main thread.

Parameters:

minThreads

The number of threads that will be kept alive at all times, even if there's no work to do. The threads won't spin up immediately; only after enough calls to run(). Only applies in multi-threaded mode.

maxThreads

The maximum number of threads that will run at once.

mode

Defaults to MULTI_THREADED on most targets, but SINGLE_THREADED in HTML5. In HTML5, MULTI_THREADED mode uses web workers, which impose additional restrictions.

Variables

read onlyactiveJobs:Int

The number of jobs actively being executed.

read onlycurrentThreads:Int

The number of live threads in this pool, including both active and idle threads. Does not count threads that have been instructed to shut down.

In single-threaded mode, this will equal activeJobs.

read onlyidleThreads:Int

The number of live threads in this pool that aren't currently working on anything. In single-threaded mode, this will always be 0.

maxThreads:Int

Set this only from the main thread.

The maximum number of live threads this pool can have at once. If this value decreases, active jobs will still be allowed to finish.

minThreads:Int

Set this only from the main thread.

The number of threads that will be kept alive at all times, even if there's no work to do. Setting this won't immediately spin up new threads; you must still call run() to get them started.

@:value(new Event<Dynamic>())read onlyonComplete:_Event_Dynamic_Void<Dynamic ‑> Void> = new Event<Dynamic>()

Dispatched on the main thread when doWork calls sendComplete(). Dispatched at most once per job.

@:value(new Event<Dynamic>())read onlyonError:_Event_Dynamic_Void<Dynamic ‑> Void> = new Event<Dynamic>()

Dispatched on the main thread when doWork calls sendError(). Dispatched at most once per job.

@:value(new Event<Dynamic>())read onlyonProgress:_Event_Dynamic_Void<Dynamic ‑> Void> = new Event<Dynamic>()

Dispatched on the main thread when doWork calls sendProgress(). May be dispatched any number of times per job.

@:value(new Event<State>())read onlyonRun:_Event_lime_system_State_Void<State ‑> Void> = new Event<State>()

Dispatched on the main thread when a new job begins. Dispatched exactly once per job.

@:value(1)workPriority:Float = 1

(Single-threaded mode only.) How important this pool's jobs are relative to other single-threaded pools.

For instance, if all pools use the default priority of 1, they will all run for an approximately equal amount of time each frame. If one has a value of 2, it will run approximately twice as long as the others.

Methods

@:value({ error : null })cancel(?error:Dynamic):Void

Cancels all active and queued jobs. In multi-threaded mode, leaves minThreads idle threads running.

Parameters:

error

If not null, this error will be dispatched for each active or queued job.

cancelJob(jobID:Int):Bool

Cancels one active or queued job. Does not dispatch an error event.

Returns:

Whether a job was canceled.

@:value({ state : null, doWork : null })run(?doWork:WorkFunction<(State, WorkOutput) ‑> Void>, ?state:Null<State>):Int

Runs the given function asynchronously, or queues it for later if all threads are busy.

Parameters:

doWork

The function to run. For best results, see the guidelines in the ThreadPool class overview. In brief: doWork should be static, only access its arguments, and return often.

state

An object to pass to doWork, ideally a mutable object so that doWork can save its progress.

Returns:

The job's unique ID.

Inherited Variables

Defined by WorkOutput

activeJob:Null<JobData>

The job that is currently running on this thread, or the job that triggered the ongoing onComplete, onError, or onProgress event. Will be null in all other cases.

read onlymode:ThreadMode

Whether background threads are being/will be used. If threads aren't available on this target, mode will always be SINGLE_THREADED.

@:value(new Tls())read onlyworkIterations:Tls<Int> = new Tls()

Available on Android, Linux, Mac, Windows, iOS

Thread-local storage. Tracks how many times doWork has been called for the current job, including (if applicable) the ongoing call.

In single-threaded mode, it only counts the number of calls this frame. The lower the number, the less accurate ThreadPool.workLoad becomes, but the higher the number, the more overhead there is. As a ballpark estimate, aim for 10-100 iterations.

Inherited Methods

Defined by WorkOutput

@:value({ transferList : null, message : null })sendComplete(?message:Dynamic, ?transferList:Array<Transferable>):Void

Available on Android, Flash, Linux, Mac, Windows, iOS

Dispatches onComplete on the main thread, with the given message. doWork should return after calling this.

If using web workers, you can also pass a list of transferable objects.

See also:

@:value({ transferList : null, message : null })sendError(?message:Dynamic, ?transferList:Array<Transferable>):Void

Available on Android, Flash, Linux, Mac, Windows, iOS

Dispatches onError on the main thread, with the given message. doWork should return after calling this.

If using web workers, you can also pass a list of transferable objects.

See also:

@:value({ transferList : null, message : null })sendProgress(?message:Dynamic, ?transferList:Array<Transferable>):Void

Available on Android, Flash, Linux, Mac, Windows, iOS

Dispatches onProgress on the main thread, with the given message. This can be called any number of times per job.

If using web workers, you can also pass a list of transferable objects.

See also: