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.