Files
lime/include.xml
player-03 f6393fc107 Overhaul ThreadPool job scheduling. (#1837, #1958)
* Store the job's thread in `JobData`.

Since we're storing more and more in `JobData`, and the background thread only needs three bits of that data, I added those to `ThreadEvent` so we don't have to pass the full object. This may improve performance in HTML5 specifically, where passing a class instance incurs an overhead.

* Allow a single `ThreadPool` to run jobs in both modes.

* Remove unnecessary `@:forward.new`.

* Improve check for whether to call `Thread.returnMessage()`.

Now that thread pools can manage both types of job at once, we can't rely on `mode` to determine whether we're on a background thread. Honestly, I shouldn't have relied on it in the first place.

* Improve `ThreadPool.isMainThread()`.

No need to set `__mainThread` based on `isWorker()` when `isWorker()` already gives the information we're after.

* Correct and clarify documentation.

* Start new jobs immediately when a slot opens up.

For single-threaded jobs, this means a pool can now handle multiple per frame. For multi-threaded jobs, this only slightly reduces the delay between jobs.

* Fix missing function call.

* Add missing import.

Forgot this when overriding the "send" functions.

* Simplify comment.

It's a private variable, so all it really needs to do is mention the location it gets used.

* Don't count the main thread in `currentThreads`.

Plus, alphabetize the variables.

In 8.2.0, a single-threaded pool would report `currentThreads == 1` when running a job, meaning it counted the main thread. But in retrospect, this was both redundant (with `activeJobs`) and unexpected, so I'm counting it as a bug.

* Update documentation.

* Remove redundant check.

All the jobs in `__multiThreadedJobs` are already known to be running in multi-threaded mode. This is left over from when pools were locked to a single mode.

* Handle error case differently.

We still need to throw an error when `mode` is `MULTI_THREADED`, but this can now vary per job, so the check must happen during `run()`.

Also, the old error message was out of date. You can't pass a function to the `ThreadPool` constructor.

* Remove unnecessary `#if`s.

On other targets, it will return `true`, which will be inlined and optimized out. The conditional compilation just added clutter.

* Rewrite `ThreadPool` to use `Deque` on native targets.

Using the flag `lime_threads_deque` to distinguish between this and the old approach. Hopefully someday we can remove this flag, once we implement something akin to `Deque` in HTML5.

That aside, the hardest part is keeping track of the state of each thread. That's why there's so much more complexity: whenever the main thread sends a message to a worker, it needs to wait for confirmation, but also not send any more messages while waiting. And the code that tracks all this needs to work in both modes (with and without `Deque`).

* Bug fix: `firstLoop = false` can get skipped.

* Fix misplaced `#if`.

* Add missing `#if`.

* Make sure all events are received before removing the update listener.

After all jobs are done, threads will send `EXIT` events. These must be processed before removing `__update`, otherwise they'll linger in the queue until the next job starts.

* Keep better track of how many threads are idle.

Previously, while a thread was exiting, `ThreadPool` could think it was still idle. This would cause it not to spin up a new thread for the next job, leading to a pending job with no threads available to handle it.

* Remove redundant code.

* Fix null pointer error.

* Fix bugs in `cancel()` and `cancelJob()`.

* Don't shut down a `ThreadPool` while work events are queued.

Co-authored-by: Barış Yıldırım <25794892+barisyild@users.noreply.github.com>

* Add missing `#if`.

---------

Co-authored-by: Barış Yıldırım <25794892+barisyild@users.noreply.github.com>
2025-07-07 16:22:41 -04:00

226 lines
8.7 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<extension>
<log error="Lime ${lime} is not compatible with Haxe ${haxe} (version 3.2.0 or higher is required)" if="${haxe < 3.2.0}" />
<log error="Lime ${lime} requires Haxe 4 to target HashLink (version ${haxe} found)" if="hl ${${haxe} < 4.0}" />
<set name="lime" />
<define name="native" if="cpp || neko || nodejs || cs || java || hl" />
<define name="howlerjs" if="html5" />
<define name="lime-cairo" if="native" />
<define name="lime-canvas" if="html5" />
<define name="lime-cffi" if="native" />
<define name="lime-curl" unless="lime-console || lime-switch || emscripten || flash || html5" />
<define name="lime-dom" if="html5" />
<define name="lime-harfbuzz" if="native" />
<define name="lime-howlerjs" if="html5" />
<define name="lime-html5" if="html5" />
<define name="lime-native" if="native" />
<define name="lime-openal" unless="lime-console || flash || html5" />
<define name="lime-opengl" if="desktop" unless="html5" />
<define name="lime-opengles" if="emscripten || mobile" />
<define name="lime-vorbis" if="native" />
<define name="lime-webgl" if="html5" />
<define name="no-typedarray-inline" if="cs" />
<haxedef name="no-compilation" />
<templatePath name="templates" />
<source path="externs/air" if="air" />
<haxeflag name="--macro" value="allowPackage('sys')" if="air" />
<sample path="samples" unless="openfl" />
<haxelib name="nodejs" if="nodejs" />
<haxelib name="format" if="java" />
<target name="ps3" handler="lime-ps3" />
<haxelib name="lime-ps3" if="ps3" />
<target name="ps4" handler="lime-ps4" />
<haxelib name="lime-ps4" if="ps4" />
<target name="vita" handler="lime-vita" />
<haxelib name="lime-vita" if="vita" />
<target name="switch" handler="lime-switch" />
<haxelib name="lime-switch" if="switch" />
<target name="wiiu" handler="lime-wiiu" />
<haxelib name="lime-wiiu" if="wiiu" />
<target name="xbox1" handler="lime-xbox1" />
<haxelib name="lime-xbox1" if="xbox1" />
<target name="console-pc" handler="lime-console-pc" />
<haxelib name="lime-console-pc" if="console-pc" />
<section if="hxp" unless="lime-tools">
<target name="air" path="tools/platforms/AIRPlatform.hx" />
<target name="android" path="tools/platforms/AndroidPlatform.hx" />
<target name="emscripten" path="tools/platforms/EmscriptenPlatform.hx" />
<target name="flash" path="tools/platforms/FlashPlatform.hx" />
<target name="html5" path="tools/platforms/HTML5Platform.hx" />
<target name="ios" path="tools/platforms/IOSPlatform.hx" />
<target name="linux" path="tools/platforms/LinuxPlatform.hx" />
<target name="mac" path="tools/platforms/MacPlatform.hx" />
<target name="tvos" path="tools/platforms/TVOSPlatform.hx" />
<target name="windows" path="tools/platforms/WindowsPlatform.hx" />
</section>
<section unless="display">
<section unless="force-synchronous || force_synchronous">
<haxedef name="lime-threads" if="neko || cpp || html5" unless="emscripten" />
<!-- `target.threaded` isn't available, so enumerate the targets instead. -->
<haxedef name="lime-threads" if="cs || java || python || hl" unless="${${haxe_ver} < 4}" />
<!-- For internal use; may be removed or renamed without warning. -->
<haxedef name="lime-threads-deque" if="neko || cpp || cs || java || python || hl" />
</section>
<section if="cpp ${${haxe_ver} < 3.3}" unless="static_link">
<ndll name="std" haxelib="hxcpp" />
<ndll name="regexp" haxelib="hxcpp" />
<ndll name="zlib" haxelib="hxcpp" unless="emscripten || ios || tvos" />
</section>
<ndll name="lime" if="native" unless="lime-console static_link || lime-switch static_link" />
<dependency name="extension-api" path="dependencies/extension-api" if="android" />
<dependency path="dependencies/howler.min.js" if="html5 howlerjs" embed="true" />
<dependency path="dependencies/pako.min.js" if="html5" embed="true" allow-web-workers="true" />
<dependency path="dependencies/lzma_worker-min.js" if="html5" embed="true" />
<dependency path="dependencies/FileSaver.min.js" if="html5" embed="true" />
<dependency path="dependencies/webgl-debug.js" if="html5 webgl-debug" embed="true" />
<dependency path="dependencies/stats.min.js" if="html5 stats" embed="true" />
<dependency path="dependencies/angle/d3dcompiler_47.dll" if="windows angle" unless="static_link" />
<dependency path="dependencies/angle/libegl.dll" if="windows angle" unless="static_link" />
<dependency path="dependencies/angle/libglesv2.dll" if="windows angle" unless="static_link" />
<!-- TODO: Move to template or move all template dependencies to XML? -->
<!-- <dependency name="CoreBluetooth.framework" if="ios" /> -->
<define name="native-trace" if="flash" unless="haxe-trace || haxetrace" />
<define name="fdb" if="flash debug" unless="nofdb" />
<define name="MACOSX_DEPLOYMENT_TARGET" value="10.9" if="mac" unless="MACOSX_DEPLOYMENT_TARGET" />
<setenv name="MACOSX_DEPLOYMENT_TARGET" value="${MACOSX_DEPLOYMENT_TARGET}" if="mac" />
<architecture name="armv7" if="android" />
<section if="emscripten">
<dependency name="pthread" />
<dependency name="openal" if="lime-openal" />
</section>
<section if="lime-modular">
<set name="haxe-module-name" value="haxe" unless="haxe-module-name" />
<set name="lime-module-name" value="lime" unless="lime-module-name" />
<setenv name="HAXE_STD_PATH" value="${HAXE_STD_PATH}" if="HAXE_STD_PATH" />
<module name="${haxe-module-name}" if="html5" unless="exclude-haxe-module">
<!--<source path="${HAXE_STD_PATH}" package="js.html" />-->
<source path="${HAXE_STD_PATH}" package="haxe.ds" exclude="haxe.ds.StringMap" />
<source path="${HAXE_STD_PATH}" package="haxe.io" />
<class name="haxe.CallStack" />
<class name="haxe.Log" />
<class name="haxe.Timer" />
<!-- <class name="js.Boot" /> -->
<class name="js.Browser" />
<class name="js.Cookie" />
<class name="js.Error" />
<!-- <class name="js.Lib" /> -->
<class name="js.Promise" />
<class name="js.RegExp" />
<class name="js.Selection" />
<class name="js.XMLSocket" />
<class name="EReg" />
<class name="HxOverrides" />
<class name="List" />
<class name="Math" />
<!-- <class name="Reflect" /> -->
<!-- <class name="Std" /> -->
<class name="StringBuf" />
<class name="StringTools" />
<!-- <class name="Type" /> -->
<include type="haxe.ds._StringMap.StringMapIterator" />
<include type="haxe.ds.TreeNode" />
<!-- <include type="haxe.IMap" /> -->
<include type="haxe._Int64.___Int64" />
<include type="haxe.StackItem" />
<include type="js.html._CanvasElement.CanvasUtil" />
<!-- <include type="js._Boot.HaxeError" /> -->
<include type="_List.ListIterator" />
</module>
<module name="${lime-module-name}" if="html5" unless="exclude-lime-module">
<source path="" package="lime" exclude="lime._backend.*|lime.project.*|lime.tools.*|lime.net.*|lime.graphics.console.*|lime.text.harfbuzz.*" />
<source path="" package="lime" include="lime._backend.html5" />
<class name="lime.net.HTTPRequest" />
<include type="lime.app._Future.FutureWork" />
<include type="lime.graphics.utils._ImageDataUtil.ImageDataView" />
<include type="lime.system._ThreadPool.ThreadPoolMessageType" />
<include type="lime.AssetLibrary" />
<!-- @:expose on enums do not work in Haxe 3.4.2 -->
<class remove="lime.graphics.opengl.GLContextType" />
<class remove="lime.graphics.ImageChannel" />
<class remove="lime.graphics.ImageType" />
<class remove="lime.graphics.RendererType" />
<class remove="lime.ui.FileDialogType" />
<class remove="lime.ui.MouseCursor" />
<class remove="lime.system.Endian" />
<class remove="lime.system.SensorType" />
<exclude type="lime.graphics.console.IndexBuffer" />
<exclude type="lime.graphics.console.PointerUtil" />
<exclude type="lime.graphics.console.Primitive" />
<exclude type="lime.graphics.console.RenderState" />
<exclude type="lime.graphics.console.Shader" />
<exclude type="lime.graphics.console.Texture" />
<exclude type="lime.graphics.console.TextureAddressMode" />
<exclude type="lime.graphics.console.TextureData" />
<exclude type="lime.graphics.console.TextureFilter" />
<exclude type="lime.graphics.console.TextureFormat" />
<exclude type="lime.graphics.console.VertexBuffer" />
<exclude type="lime.graphics.console.VertexDecl" />
<exclude type="lime.graphics.console.VertexOutput" />
</module>
</section>
</section>
<haxelib name="hxcpp" if="setup" />
<haxelib name="lime-samples" if="setup" />
<include haxelib="lime-samples" if="create" />
<section if="rebuild">
<config:project>
<rebuild fulldebug="true" />
</config:project>
</section>
</extension>