This commit splits out synchronization primitives from LibThreading into
LibSync. This is because LibThreading depends on LibCore, while LibCore
needs the synchronization primitives from LibThreading. This worked
while they were header only, but when I tried to add an implementation
file it ran into the circular dependency. To abstract away the pthread
implementation using cpp files is necessary so the synchronization
primitives were moved to a separate library.
Once.h provides a way to run a function once without relying on system
libraries at the call site. It also allows use of any function as long
as it satisfies the VoidFunction concept. For similarity with the STL I
would have preferred it to be in AK, but it needs a mutex to work so
that would cause a circular dependency.
With some templates and an optional it could be modified to return non
void types, but since that isn't an existing pattern in the codebase
that could be implemented in a follow-up.
Performance wise compared to pthread_once it should be very similar
in the already initialized case as both use an atomic. On the first call
this might be slightly slower since we use a mutex while pthread may be
doing something fancier with a futex or similar, but it shouldn't
matter.
The generic unlock() wrote to m_write_locked from every thread
regardless of whether a read or write lock was held. When multiple
threads held concurrent read locks, their unlock() calls would race
on the non-atomic m_write_locked and m_read_locked_with_write_lock
fields.
Split unlock() into unlock_read() and unlock_write() so that read
unlocks never touch the write-lock tracking fields. The RWLockLocker
template dispatches at compile time based on LockMode.
Add a simple thread pool with a fixed number of worker threads and a
shared work queue. The pool is accessed via ThreadPool::the() which
lazily creates a singleton with 4 worker threads.
submit() enqueues a work item and signals a condvar. Worker threads
loop waiting on the condvar, picking up and executing work items.
Worker threads use 8 MiB stacks to match the main thread, since
the JS parser can build deep call stacks during off-thread parsing.
Using a Promise in BackgroundAction was not doing anything since the
change to use a weak reference to the event loop, so let's just drop
that.
The thread will now always move itself (and therefore its callbacks)
over to the originating thread before completing, regardless of the
presence of callbacks. This ensures that ref counting remains on the
main thread.
In addition, BackgroundAction's completion callback can no longer
return errors. This functionality wasn't actually used anywhere, it was
a holdover from the behavior of Core::Promise.
Weakable is not thread-safe, so taking a strong reference from a
WeakPtr<Thread> may result in a use-after-free. We don't use this
functionality anywhere anyway, so remove it.
I created this file a couple years ago, but had a copy/pasted copyright
comment from another file, without the authors being changed. It's now
corrected to attribute it to myself, as it should have been already.
- `Threading::Thread` is not polymorphic, there is no need for a virtual
destructor.
- `HTMLAnchorElement::has_download_preference` isn't overridden by
anything.
This warning was introduced in llvm/llvm-project#131188.
When a BackgroundAction completes, it resolves a Promise (stored on the
BackgroundAction object) with a reference to itself. The Promise will
never unset this resolved value, thus it will hold a strong reference to
the BackgroundAction until it is destroyed. But because the Promise is
owned by the BackgroundAction itself, we have a reference cycle, and
neither object can be destroyed.
The only user of BackgroundAction is the ImageDecoder process. The
consequence was that the ImageDecoder process would never release any
image data for successfully decoded images.
To fix this, instead of storing the promise on the class itself, we can
just create it as a local variable and pass it around.