mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-05-11 17:37:33 +02:00
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.
87 lines
2.5 KiB
C++
87 lines
2.5 KiB
C++
/*
|
|
* Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
|
|
* Copyright (c) 2021, Andreas Kling <andreas@ladybird.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/Queue.h>
|
|
#include <LibSync/Mutex.h>
|
|
#include <LibThreading/BackgroundAction.h>
|
|
#include <LibThreading/Thread.h>
|
|
|
|
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
static pthread_cond_t s_condition = PTHREAD_COND_INITIALIZER;
|
|
static Queue<Function<void()>>* s_all_actions;
|
|
static Threading::Thread* s_background_thread;
|
|
static Atomic<bool> s_background_thread_should_run = true;
|
|
|
|
static intptr_t background_thread_func()
|
|
{
|
|
Vector<Function<void()>> actions;
|
|
while (s_background_thread_should_run.load(AK::MemoryOrder::memory_order_acquire)) {
|
|
pthread_mutex_lock(&s_mutex);
|
|
|
|
while (s_all_actions->is_empty() && s_background_thread_should_run.load(AK::MemoryOrder::memory_order_acquire))
|
|
pthread_cond_wait(&s_condition, &s_mutex);
|
|
|
|
while (!s_all_actions->is_empty())
|
|
actions.append(s_all_actions->dequeue());
|
|
|
|
pthread_mutex_unlock(&s_mutex);
|
|
|
|
for (auto& action : actions) {
|
|
if (s_background_thread_should_run.load(AK::MemoryOrder::memory_order_acquire))
|
|
action();
|
|
}
|
|
actions.clear();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void init()
|
|
{
|
|
s_all_actions = new Queue<Function<void()>>;
|
|
s_background_thread = &Threading::Thread::construct("Background"sv, background_thread_func).leak_ref();
|
|
s_background_thread->start();
|
|
}
|
|
|
|
void Threading::quit_background_thread()
|
|
{
|
|
if (!s_background_thread)
|
|
return;
|
|
|
|
s_background_thread_should_run.store(false, AK::MemoryOrder::memory_order_release);
|
|
|
|
pthread_mutex_lock(&s_mutex);
|
|
pthread_cond_broadcast(&s_condition);
|
|
pthread_mutex_unlock(&s_mutex);
|
|
|
|
MUST(s_background_thread->join());
|
|
|
|
delete s_all_actions;
|
|
s_background_thread->unref();
|
|
s_all_actions = nullptr;
|
|
s_background_thread = nullptr;
|
|
|
|
s_background_thread_should_run.store(true, AK::MemoryOrder::memory_order_release);
|
|
}
|
|
|
|
Threading::Thread& Threading::BackgroundActionBase::background_thread()
|
|
{
|
|
if (s_background_thread == nullptr)
|
|
init();
|
|
return *s_background_thread;
|
|
}
|
|
|
|
void Threading::BackgroundActionBase::enqueue_work(Function<void()> work)
|
|
{
|
|
if (s_all_actions == nullptr)
|
|
init();
|
|
|
|
pthread_mutex_lock(&s_mutex);
|
|
s_all_actions->enqueue(move(work));
|
|
pthread_cond_broadcast(&s_condition);
|
|
pthread_mutex_unlock(&s_mutex);
|
|
}
|