mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2026-04-19 02:10:26 +00:00
LibCore: Add thread-safe weak deferred_invoke()
Add a thread-safe deferred_invoke() API on WeakEventLoopReference that queues work onto the owning thread's event queue and wakes that thread via EventLoopManager hooks. This avoids calling wake() from foreign threads during teardown. Implement current_thread_handle()/wake_thread() in each backend and track per-thread data so handles are validated before waking: - Unix: wake via per-thread wake pipe - Windows: wake via thread wake event - macOS: wake via stored CFRunLoopRef - Qt: wake via event target or QEventLoop::wakeUp() - Android: wake via stored ALooper
This commit is contained in:
parent
367296fce6
commit
96ce468b60
Notes:
github-actions[bot]
2026-02-06 11:08:22 +00:00
Author: https://github.com/awesomekling
Commit: 96ce468b60
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/7582
13 changed files with 220 additions and 0 deletions
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/BinaryHeap.h>
|
||||
#include <AK/HashTable.h>
|
||||
#include <AK/Singleton.h>
|
||||
#include <AK/TemporaryChange.h>
|
||||
#include <AK/Time.h>
|
||||
|
|
@ -30,6 +31,7 @@ struct ThreadData;
|
|||
class TimeoutSet;
|
||||
|
||||
HashMap<pthread_t, ThreadData*> s_thread_data;
|
||||
HashTable<ThreadData*> s_thread_data_by_ptr;
|
||||
Threading::RWLock s_thread_data_lock;
|
||||
thread_local pthread_t s_thread_id;
|
||||
thread_local OwnPtr<ThreadData> s_this_thread_data;
|
||||
|
|
@ -232,6 +234,7 @@ struct ThreadData {
|
|||
|
||||
Threading::RWLockLocker<Threading::LockMode::Write> locker(s_thread_data_lock);
|
||||
s_thread_data.set(s_thread_id, s_this_thread_data.ptr());
|
||||
s_thread_data_by_ptr.set(s_this_thread_data.ptr());
|
||||
} else {
|
||||
data = s_this_thread_data.ptr();
|
||||
}
|
||||
|
|
@ -244,6 +247,17 @@ struct ThreadData {
|
|||
return s_thread_data.get(thread_id).value_or(nullptr);
|
||||
}
|
||||
|
||||
static ThreadData* for_handle(EventLoopThreadHandle handle)
|
||||
{
|
||||
if (handle == 0)
|
||||
return nullptr;
|
||||
auto* ptr = reinterpret_cast<ThreadData*>(handle);
|
||||
Threading::RWLockLocker<Threading::LockMode::Read> locker(s_thread_data_lock);
|
||||
if (!s_thread_data_by_ptr.contains(ptr))
|
||||
return nullptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
ThreadData()
|
||||
{
|
||||
pid = getpid();
|
||||
|
|
@ -265,6 +279,7 @@ struct ThreadData {
|
|||
{
|
||||
Threading::RWLockLocker<Threading::LockMode::Write> locker(s_thread_data_lock);
|
||||
s_thread_data.remove(s_thread_id);
|
||||
s_thread_data_by_ptr.remove(this);
|
||||
}
|
||||
|
||||
Threading::Mutex mutex;
|
||||
|
|
@ -676,6 +691,20 @@ void EventLoopManagerUnix::did_post_event()
|
|||
{
|
||||
}
|
||||
|
||||
EventLoopThreadHandle EventLoopManagerUnix::current_thread_handle()
|
||||
{
|
||||
return reinterpret_cast<EventLoopThreadHandle>(&ThreadData::the());
|
||||
}
|
||||
|
||||
void EventLoopManagerUnix::wake_thread(EventLoopThreadHandle handle)
|
||||
{
|
||||
auto* thread_data = ThreadData::for_handle(handle);
|
||||
if (!thread_data)
|
||||
return;
|
||||
int wake_event = 0;
|
||||
(void)Core::System::write(thread_data->wake_pipe_fds[1], { &wake_event, sizeof(wake_event) });
|
||||
}
|
||||
|
||||
EventLoopManagerUnix::~EventLoopManagerUnix() = default;
|
||||
|
||||
NonnullOwnPtr<EventLoopImplementation> EventLoopManagerUnix::make_implementation()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue