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.
Idle processing needs to check whether there are still tasks scheduled to be resumed before setting the exit flag when there are no more waiters (I/O etc.).
Shuts down the pool before terminating the threads to avoid accessing an event thread waiter slot that is not associated with a valid eventcore driver anymore.
The approach for now is to keep overloads that receive system delegates and are also marked system in turn. This breaks safety promises in some places within the library, but is an acceptable first step that keeps other possible directions open.
- setTimer now starts a task to call the callback. This keeps the timer referenced and avoids issues if I/O functions are called from within the callback.
- SpinLock is now also initialized in "shared static this", so that applications using "shared static this" for initialization work properly.
This simplifies the logic by separating thread local notifications from cross-thread notifications, as well as replacing lockless operations by a spin lock. The thread local variant of ManualEvent is now also separated into a LocalManualEvent type.
- Detection of the main thread contained a race condition
- The exit flag monitor task that is started for each event loop wasn't shut down, so that many could be running if runEventLoop was called multiple times.
Removes some invalid safety annotations and adds a workaround for a starvation issue in Task.join() across threads boundaries. This is still not thread-safe, but now has a safety-net and is documented, so that it doesn't get lost.
In situations where no events were involved in an multi-task scenario, the old behavior could lead to the process to starve or hang until an event arrived.