1. Removes the marker task used by schedule() and instead limits the number of task resumptions to the initial length of the task queue
2. Assigns a static and a dynamic priority to each task. The dynamic priority starts with the same value as the static priority and gets incremented by the static priority each time the task gets overtaken by a higher priority task, eventually leading to the task becoming the highest priority (unless the static priority is zero). Tasks with a higher dynamic priority generally take precedence, unless the concurrency exceeds 10 scheduled tasks, in which case the front of the queue is scheduled in normal FIFO order.
Uninitialized YieldLock values can happen in various ways, dispite the default constructor being disabled. If any such value got destroyed, it would lead to a negative lock count. Since this is handled properly now, the default constructor is also enabled in this commit.
`runApplication` takes an `args_out` parameter which, if non-null, is
supposed to be set to match unrecognized command-line args. However,
the parameter is never passed to `finalizeCommandLineOptions`, which
will therefore log an error and throw an exception if any command line
arguments are unrecognized.
This patch fixes the oversight, ensuring that `runApplication` will
correctly populate a non-null `args_out` parameter with unrecognized
command-line arguments, and not throw an exception in this case.
Since the signal handler can be called in any thread of the application, it may happen so in a non-D thread where Thread.getThis() returns null. This change works around this and also removes the need to call SpinLock.setup on thread startup.
The status of the task was erroneously reported as not running until the task was actually executed for the first time (which only happens after the yield lock has been lifted).
This change modifies destructors to anticipate that they can be called form a foreign thread if the GC is involved. The actual release of the reference will then happen deferred in the original thread.
If the lambda is a concrete function, two different versions will end up for it in the final binary on macOS when compiled with LDC. Using argument inference works around that issue.