LibThreading/LibSync: Split out sync primitives

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.
This commit is contained in:
R-Goc 2025-10-30 13:29:29 +01:00 committed by Gregory Bertilson
parent 1d8751363b
commit 02bb892d7a
72 changed files with 296 additions and 264 deletions

View file

@ -3,6 +3,7 @@ add_subdirectory(LibFileSystem)
add_subdirectory(LibIDL)
add_subdirectory(LibMain)
add_subdirectory(LibRegex)
add_subdirectory(LibSync)
add_subdirectory(LibTextCodec)
add_subdirectory(LibUnicode)
add_subdirectory(LibURL)

View file

@ -91,7 +91,7 @@ if (APPLE)
endif()
ladybird_lib(LibCore core EXPLICIT_SYMBOL_EXPORT)
target_link_libraries(LibCore PRIVATE LibUnicode LibURL Threads::Threads LibTextCodec)
target_link_libraries(LibCore PRIVATE LibSync Threads::Threads LibUnicode LibURL LibTextCodec)
if (${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
# NetBSD has its shm_open and shm_unlink functions in librt so we need to link that

View file

@ -173,7 +173,7 @@ WeakEventLoopReference::WeakEventLoopReference(EventLoop& event_loop)
void WeakEventLoopReference::revoke()
{
Threading::RWLockLocker<Threading::LockMode::Write> locker { m_lock };
Sync::RWLockLocker<Sync::LockMode::Write> locker { m_lock };
m_event_loop = nullptr;
}

View file

@ -17,7 +17,7 @@
#include <AK/RefPtr.h>
#include <LibCore/Export.h>
#include <LibCore/Forward.h>
#include <LibThreading/RWLock.h>
#include <LibSync/RWLock.h>
namespace Core {
@ -118,7 +118,7 @@ private:
void revoke();
EventLoop* m_event_loop;
Threading::RWLock m_lock;
Sync::RWLock m_lock;
};
class CORE_API StrongEventLoopReference {

View file

@ -17,8 +17,8 @@
#include <LibCore/Platform/ScopedAutoreleasePool.h>
#include <LibCore/System.h>
#include <LibCore/ThreadEventQueue.h>
#include <LibThreading/Mutex.h>
#include <LibThreading/RWLock.h>
#include <LibSync/Mutex.h>
#include <LibSync/RWLock.h>
#include <pthread.h>
#include <sys/select.h>
#include <unistd.h>
@ -31,7 +31,7 @@ struct ThreadData;
class TimeoutSet;
HashMap<pthread_t, ThreadData*> s_thread_data;
Threading::RWLock s_thread_data_lock;
Sync::RWLock s_thread_data_lock;
thread_local pthread_t s_thread_id;
thread_local OwnPtr<ThreadData> s_this_thread_data;
@ -231,7 +231,7 @@ struct ThreadData {
data = new ThreadData;
s_this_thread_data = adopt_own(*data);
Threading::RWLockLocker<Threading::LockMode::Write> locker(s_thread_data_lock);
Sync::RWLockLocker<Sync::LockMode::Write> locker(s_thread_data_lock);
s_thread_data.set(s_thread_id, s_this_thread_data.ptr());
} else {
data = s_this_thread_data.ptr();
@ -267,11 +267,11 @@ struct ThreadData {
close(wake_pipe_fds[0]);
close(wake_pipe_fds[1]);
Threading::RWLockLocker<Threading::LockMode::Write> locker(s_thread_data_lock);
Sync::RWLockLocker<Sync::LockMode::Write> locker(s_thread_data_lock);
s_thread_data.remove(s_thread_id);
}
Threading::Mutex mutex;
Sync::Mutex mutex;
// Each thread has its own timers, notifiers and a wake pipe.
TimeoutSet timeouts;
@ -334,7 +334,7 @@ void EventLoopImplementationUnix::wake()
void EventLoopManagerUnix::wait_for_events(EventLoopImplementation::PumpMode mode)
{
auto& thread_data = ThreadData::the();
Threading::MutexLocker locker(thread_data.mutex);
Sync::MutexLocker locker(thread_data.mutex);
retry:
bool has_pending_events = ThreadEventQueue::current().has_pending_events();
@ -626,7 +626,7 @@ intptr_t EventLoopManagerUnix::register_timer(EventReceiver& object, int millise
{
VERIFY(milliseconds >= 0);
auto& thread_data = ThreadData::the();
Threading::MutexLocker locker(thread_data.mutex);
Sync::MutexLocker locker(thread_data.mutex);
auto timer = new EventLoopTimer;
timer->owner_thread = s_thread_id;
timer->owner = object;
@ -640,11 +640,11 @@ intptr_t EventLoopManagerUnix::register_timer(EventReceiver& object, int millise
void EventLoopManagerUnix::unregister_timer(intptr_t timer_id)
{
auto* timer = bit_cast<EventLoopTimer*>(timer_id);
Threading::RWLockLocker<Threading::LockMode::Read> locker(s_thread_data_lock);
Sync::RWLockLocker<Sync::LockMode::Read> locker(s_thread_data_lock);
auto* thread_data_ptr = ThreadData::for_thread(timer->owner_thread);
if (!thread_data_ptr)
return;
Threading::MutexLocker thread_data_content_locker(thread_data_ptr->mutex);
Sync::MutexLocker thread_data_content_locker(thread_data_ptr->mutex);
auto& thread_data = *thread_data_ptr;
auto expected = false;
if (timer->is_being_deleted.compare_exchange_strong(expected, true, AK::MemoryOrder::memory_order_acq_rel)) {
@ -657,7 +657,7 @@ void EventLoopManagerUnix::unregister_timer(intptr_t timer_id)
void EventLoopManagerUnix::register_notifier(Notifier& notifier)
{
auto& thread_data = ThreadData::the();
Threading::MutexLocker locker(thread_data.mutex);
Sync::MutexLocker locker(thread_data.mutex);
thread_data.notifier_to_index.set(&notifier, thread_data.poll_fds.size());
thread_data.notifiers.append(&notifier);
@ -670,11 +670,11 @@ void EventLoopManagerUnix::register_notifier(Notifier& notifier)
void EventLoopManagerUnix::unregister_notifier(Notifier& notifier)
{
Threading::RWLockLocker<Threading::LockMode::Read> locker(s_thread_data_lock);
Sync::RWLockLocker<Sync::LockMode::Read> locker(s_thread_data_lock);
auto* thread_data = ThreadData::for_thread(notifier.owner_thread());
if (!thread_data)
return;
Threading::MutexLocker thread_data_content_locker(thread_data->mutex);
Sync::MutexLocker thread_data_content_locker(thread_data->mutex);
auto notifier_index = thread_data->notifier_to_index.take(&notifier).release_value();

View file

@ -16,8 +16,8 @@
#include <LibCore/Notifier.h>
#include <LibCore/ThreadEventQueue.h>
#include <LibCore/Timer.h>
#include <LibThreading/Mutex.h>
#include <LibThreading/MutexProtected.h>
#include <LibSync/Mutex.h>
#include <LibSync/MutexProtected.h>
struct OwnHandle {
HANDLE handle = NULL;
@ -152,7 +152,7 @@ struct ThreadData {
NonnullOwnPtr<EventLoopWake> wake_data;
};
static Threading::MutexProtected<HashMap<pid_t, NonnullOwnPtr<EventLoopProcess>>> s_processes;
static Sync::MutexProtected<HashMap<pid_t, NonnullOwnPtr<EventLoopProcess>>> s_processes;
EventLoopImplementationWindows::EventLoopImplementationWindows()
: m_wake_event(ThreadData::the()->wake_data->wait_event.handle)

View file

@ -9,8 +9,8 @@
#include <LibCore/EventReceiver.h>
#include <LibCore/Promise.h>
#include <LibCore/ThreadEventQueue.h>
#include <LibThreading/Mutex.h>
#include <LibThreading/Once.h>
#include <LibSync/Mutex.h>
#include <LibSync/Once.h>
#include <errno.h>
#include <pthread.h>
@ -41,16 +41,16 @@ struct ThreadEventQueue::Private {
u8 event_type { Event::Type::Invalid };
};
Threading::Mutex mutex;
Sync::Mutex mutex;
Vector<QueuedEvent> queued_events;
};
static pthread_key_t s_current_thread_event_queue_key;
static Threading::OnceFlag s_current_thread_event_queue_key_once {};
static Sync::OnceFlag s_current_thread_event_queue_key_once {};
ThreadEventQueue* ThreadEventQueue::current_or_null()
{
call_once(s_current_thread_event_queue_key_once, [] {
Sync::call_once(s_current_thread_event_queue_key_once, [] {
pthread_key_create(&s_current_thread_event_queue_key, [](void* value) {
if (value)
delete static_cast<ThreadEventQueue*>(value);
@ -80,7 +80,7 @@ ThreadEventQueue::~ThreadEventQueue() = default;
void ThreadEventQueue::post_event(Core::EventReceiver* receiver, Core::Event::Type event_type)
{
{
Threading::MutexLocker lock(m_private->mutex);
Sync::MutexLocker lock(m_private->mutex);
m_private->queued_events.empend(receiver, event_type);
}
Core::EventLoopManager::the().did_post_event();
@ -89,7 +89,7 @@ void ThreadEventQueue::post_event(Core::EventReceiver* receiver, Core::Event::Ty
void ThreadEventQueue::deferred_invoke(Function<void()>&& invokee)
{
{
Threading::MutexLocker lock(m_private->mutex);
Sync::MutexLocker lock(m_private->mutex);
m_private->queued_events.empend(move(invokee));
}
Core::EventLoopManager::the().did_post_event();
@ -99,7 +99,7 @@ size_t ThreadEventQueue::process()
{
decltype(m_private->queued_events) events;
{
Threading::MutexLocker locker(m_private->mutex);
Sync::MutexLocker locker(m_private->mutex);
events = move(m_private->queued_events);
}
@ -133,7 +133,7 @@ size_t ThreadEventQueue::process()
bool ThreadEventQueue::has_pending_events() const
{
Threading::MutexLocker locker(m_private->mutex);
Sync::MutexLocker locker(m_private->mutex);
return !m_private->queued_events.is_empty();
}

View file

@ -13,7 +13,7 @@
#include <AK/Concepts.h>
#include <LibCore/EventLoop.h>
#include <LibCore/EventReceiver.h>
#include <LibThreading/Mutex.h>
#include <LibSync/Mutex.h>
namespace Core {
@ -75,7 +75,7 @@ public:
template<CallableAs<ErrorOr<void>, ResultType&&> ResolvedHandler>
ThreadedPromise& when_resolved(ResolvedHandler handler)
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
VERIFY(!m_resolution_handler);
m_resolution_handler = move(handler);
return *this;
@ -112,7 +112,7 @@ public:
template<CallableAs<void, ErrorType&&> RejectedHandler>
ThreadedPromise& when_rejected(RejectedHandler when_rejected = [](ErrorType&) { })
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
VERIFY(!m_rejection_handler);
m_rejection_handler = move(when_rejected);
return *this;
@ -148,7 +148,7 @@ private:
template<typename F>
static void deferred_handler_check(NonnullRefPtr<ThreadedPromise> self, F&& function)
{
Threading::MutexLocker locker { self->m_mutex };
Sync::MutexLocker locker { self->m_mutex };
if (self->m_rejection_handler) {
function();
return;
@ -168,7 +168,7 @@ private:
// to spin extremely briefly. Therefore, sleeping the thread should not be
// necessary.
while (true) {
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
if (m_rejection_handler)
break;
}
@ -181,7 +181,7 @@ private:
Function<ErrorOr<void>(ResultType&&)> m_resolution_handler;
Function<void(ErrorType&&)> m_rejection_handler;
Threading::Mutex m_mutex;
Sync::Mutex m_mutex;
Atomic<bool> m_has_completed;
};

View file

@ -3,4 +3,4 @@ set(SOURCES
)
ladybird_lib(LibDNS dns EXPLICIT_SYMBOL_EXPORT)
target_link_libraries(LibDNS PRIVATE LibCore PUBLIC LibCrypto LibThreading)
target_link_libraries(LibDNS PRIVATE LibCore PUBLIC LibCrypto LibSync LibThreading)

View file

@ -24,7 +24,7 @@
#include <LibCrypto/Curves/EdwardsCurve.h>
#include <LibCrypto/PK/RSA.h>
#include <LibDNS/Message.h>
#include <LibThreading/RWLockProtected.h>
#include <LibSync/RWLockProtected.h>
#include <LibThreading/ThreadPool.h>
#define TRY_OR_REJECT_PROMISE(promise, expr) \
@ -1412,10 +1412,10 @@ private:
});
}
Threading::RWLockProtected<HashMap<ByteString, NonnullRefPtr<LookupResult>>> m_cache;
Threading::RWLockProtected<HashMap<ByteString, NonnullRefPtr<PendingSystemResolution>>> m_pending_system_resolutions;
Threading::RWLockProtected<NonnullOwnPtr<RedBlackTree<u16, PendingLookup>>> m_pending_lookups;
Threading::RWLockProtected<Optional<MaybeOwned<Core::Socket>>> m_socket;
Sync::RWLockProtected<HashMap<ByteString, NonnullRefPtr<LookupResult>>> m_cache;
Sync::RWLockProtected<HashMap<ByteString, NonnullRefPtr<PendingSystemResolution>>> m_pending_system_resolutions;
Sync::RWLockProtected<NonnullOwnPtr<RedBlackTree<u16, PendingLookup>>> m_pending_lookups;
Sync::RWLockProtected<Optional<MaybeOwned<Core::Socket>>> m_socket;
Function<ErrorOr<SocketResult>()> m_create_socket;
bool m_attempting_restart { false };
ConnectionMode m_mode { ConnectionMode::UDP };

View file

@ -110,8 +110,8 @@ private:
void run();
void process_one(BlockAllocator&);
Threading::Mutex m_mutex;
Threading::ConditionVariable m_cv { m_mutex };
Sync::Mutex m_mutex;
Sync::ConditionVariable m_cv { m_mutex };
RefPtr<Threading::Thread> m_thread;
Vector<BlockAllocator*> m_pending;
bool m_kicked { false };
@ -135,20 +135,20 @@ DecommitWorker::DecommitWorker()
void DecommitWorker::register_pending(BlockAllocator& a)
{
Threading::MutexLocker locker(m_mutex);
Sync::MutexLocker locker(m_mutex);
m_pending.append(&a);
}
void DecommitWorker::deregister(BlockAllocator& a)
{
Threading::MutexLocker locker(m_mutex);
Sync::MutexLocker locker(m_mutex);
m_pending.remove_first_matching([&](auto* p) { return p == &a; });
}
void DecommitWorker::kick()
{
{
Threading::MutexLocker locker(m_mutex);
Sync::MutexLocker locker(m_mutex);
m_kicked = true;
}
m_cv.signal();
@ -159,7 +159,7 @@ void DecommitWorker::run()
while (true) {
Vector<BlockAllocator*> snapshot;
{
Threading::MutexLocker locker(m_mutex);
Sync::MutexLocker locker(m_mutex);
while (!m_kicked)
m_cv.wait();
m_kicked = false;
@ -182,7 +182,7 @@ void DecommitWorker::run()
process_one(*a);
int prev_refcount = a->m_worker_refcount.fetch_sub(1);
if (prev_refcount == 1) {
Threading::MutexLocker locker(a->m_mutex);
Sync::MutexLocker locker(a->m_mutex);
a->m_worker_cv.broadcast();
}
}
@ -193,7 +193,7 @@ void DecommitWorker::process_one(BlockAllocator& a)
{
Vector<void*> to_process;
{
Threading::MutexLocker locker(a.m_mutex);
Sync::MutexLocker locker(a.m_mutex);
a.m_in_decommit_registry = false;
to_process = move(a.m_freshly_freed);
}
@ -209,7 +209,7 @@ void DecommitWorker::process_one(BlockAllocator& a)
}
{
Threading::MutexLocker locker(a.m_mutex);
Sync::MutexLocker locker(a.m_mutex);
for (auto* slot : to_process)
a.m_blocks.append(slot);
}
@ -232,14 +232,14 @@ BlockAllocator::~BlockAllocator()
// in-flight processing of *this before our storage goes away.
DecommitWorker::the().deregister(*this);
Threading::MutexLocker locker(m_mutex);
Sync::MutexLocker locker(m_mutex);
while (m_worker_refcount.load() != 0)
m_worker_cv.wait();
}
size_t BlockAllocator::block_count()
{
Threading::MutexLocker locker(m_mutex);
Sync::MutexLocker locker(m_mutex);
return m_blocks.size();
}
@ -249,7 +249,7 @@ void* BlockAllocator::allocate_block([[maybe_unused]] char const* name)
bool needs_madvise_reuse = false;
{
Threading::MutexLocker locker(m_mutex);
Sync::MutexLocker locker(m_mutex);
// Prefer m_freshly_freed: those slots were never madvised, so we
// can hand them back out with zero syscalls. This is the deferred-
@ -302,7 +302,7 @@ void* BlockAllocator::allocate_block([[maybe_unused]] char const* name)
ASAN_POISON_MEMORY_REGION(chunk_base, CHUNK_SIZE);
Threading::MutexLocker locker(m_mutex);
Sync::MutexLocker locker(m_mutex);
for (size_t i = 0; i < BLOCKS_PER_CHUNK; ++i)
m_blocks.append(static_cast<u8*>(chunk_base) + i * HeapBlock::BLOCK_SIZE);
block = m_blocks.take_last();
@ -335,7 +335,7 @@ void BlockAllocator::deallocate_block(void* block)
bool need_to_register = false;
{
Threading::MutexLocker locker(m_mutex);
Sync::MutexLocker locker(m_mutex);
m_freshly_freed.append(block);
if (!m_in_decommit_registry) {
m_in_decommit_registry = true;

View file

@ -9,8 +9,8 @@
#include <AK/Atomic.h>
#include <AK/Vector.h>
#include <LibGC/Forward.h>
#include <LibThreading/ConditionVariable.h>
#include <LibThreading/Mutex.h>
#include <LibSync/ConditionVariable.h>
#include <LibSync/Mutex.h>
namespace GC {
@ -44,13 +44,13 @@ private:
// Protects m_blocks, m_freshly_freed, and m_in_decommit_registry. Held
// briefly on the alloc/dealloc hot path; uncontended in the common case.
Threading::Mutex m_mutex;
Sync::Mutex m_mutex;
// Refcount the decommit worker bumps while it has a reference to this
// allocator. The destructor waits on m_worker_cv until it hits zero so
// we never let our storage go away while the worker is still running.
AK::Atomic<int> m_worker_refcount { 0 };
Threading::ConditionVariable m_worker_cv;
Sync::ConditionVariable m_worker_cv;
// True iff this allocator is currently in the worker's pending list.
// Avoids re-registering on every dealloc; cleared by the worker at the

View file

@ -14,7 +14,7 @@ set(SOURCES
ladybird_lib(LibGC gc EXPLICIT_SYMBOL_EXPORT)
target_link_libraries(LibGC PRIVATE LibCore)
target_link_libraries(LibGC PUBLIC LibThreading)
target_link_libraries(LibGC PUBLIC LibSync LibThreading)
if(cpptrace_FOUND AND LADYBIRD_ENABLE_CPPTRACE)
target_link_libraries(LibGC PRIVATE cpptrace::cpptrace)

View file

@ -75,7 +75,7 @@ endif()
ladybird_lib(LibGfx gfx)
target_link_libraries(LibGfx PRIVATE LibCompress LibCore LibCrypto LibFileSystem LibTextCodec LibIPC LibUnicode)
target_link_libraries(LibGfx PRIVATE LibCompress LibCore LibCrypto LibFileSystem LibTextCodec LibIPC LibSync LibUnicode)
set(generated_sources TIFFMetadata.h TIFFTagHandler.cpp)
list(TRANSFORM generated_sources PREPEND "ImageFormats/")

View file

@ -25,4 +25,4 @@ else()
endif()
ladybird_lib(LibIPC ipc)
target_link_libraries(LibIPC PRIVATE LibCore LibURL LibThreading)
target_link_libraries(LibIPC PRIVATE LibCore LibSync LibThreading LibURL)

View file

@ -11,6 +11,7 @@
#include <LibCore/System.h>
#include <LibIPC/MachBootstrapMessages.h>
#include <LibIPC/TransportBootstrapMach.h>
#include <LibSync/Mutex.h>
#include <mach/mach.h>
@ -112,7 +113,7 @@ ErrorOr<TransportBootstrapMachServer::BootstrapRequestResult> TransportBootstrap
{
Optional<TransportBootstrapMachPorts> child_transport;
{
Threading::MutexLocker locker(m_child_registration_mutex);
Sync::MutexLocker locker(m_child_registration_mutex);
child_transport = m_child_transports.take(pid);
}

View file

@ -16,7 +16,7 @@
#endif
#include <LibCore/MachPort.h>
#include <LibThreading/Mutex.h>
#include <LibSync/Mutex.h>
namespace IPC {
@ -43,7 +43,7 @@ public:
// Hold this lock across process spawn and child transport registration so a
// child bootstrap request cannot observe an unregistered pid.
Threading::Mutex& child_registration_lock() { return m_child_registration_mutex; }
Sync::Mutex& child_registration_lock() { return m_child_registration_mutex; }
// Must be called while holding child_registration_lock().
void register_child_transport(pid_t, TransportBootstrapMachPorts);
@ -53,7 +53,7 @@ private:
static void send_transport_ports_to_child(Core::MachPort reply_port, TransportBootstrapMachPorts ports);
static ErrorOr<TransportBootstrapMachPorts> create_on_demand_local_transport(Core::MachPort reply_port);
Threading::Mutex m_child_registration_mutex;
Sync::Mutex m_child_registration_mutex;
HashMap<pid_t, TransportBootstrapMachPorts> m_child_transports;
};

View file

@ -9,6 +9,7 @@
#include <LibCore/Notifier.h>
#include <LibCore/System.h>
#include <LibIPC/TransportMachPort.h>
#include <LibSync/Mutex.h>
#include <LibThreading/Thread.h>
#include <mach/mach.h>
@ -145,7 +146,7 @@ void TransportMachPort::notify_read_available()
void TransportMachPort::mark_peer_eof()
{
{
Threading::MutexLocker locker(m_incoming_mutex);
Sync::MutexLocker locker(m_incoming_mutex);
m_peer_eof = true;
}
m_incoming_cv.broadcast();
@ -164,14 +165,14 @@ intptr_t TransportMachPort::io_thread_loop()
Vector<PendingMessage> messages_to_send;
{
Threading::MutexLocker locker(m_send_mutex);
Sync::MutexLocker locker(m_send_mutex);
messages_to_send = move(m_pending_send_messages);
}
for (auto& message : messages_to_send)
send_mach_message(message);
if (m_io_thread_state.load() == IOThreadState::SendPendingMessagesAndStop) {
Threading::MutexLocker locker(m_send_mutex);
Sync::MutexLocker locker(m_send_mutex);
if (!m_pending_send_messages.is_empty())
continue;
m_io_thread_state = IOThreadState::Stopped;
@ -308,7 +309,7 @@ void TransportMachPort::process_received_message(u8* buffer)
return;
{
Threading::MutexLocker locker(m_incoming_mutex);
Sync::MutexLocker locker(m_incoming_mutex);
m_incoming_messages.append(move(message));
}
m_incoming_cv.signal();
@ -327,7 +328,7 @@ void TransportMachPort::set_up_read_hook(Function<void()> hook)
};
{
Threading::MutexLocker locker(m_incoming_mutex);
Sync::MutexLocker locker(m_incoming_mutex);
if (!m_incoming_messages.is_empty())
notify_read_available();
}
@ -352,7 +353,7 @@ void TransportMachPort::close_after_sending_all_pending_messages()
void TransportMachPort::wait_until_readable()
{
Threading::MutexLocker lock(m_incoming_mutex);
Sync::MutexLocker lock(m_incoming_mutex);
while (m_incoming_messages.is_empty() && !m_peer_eof)
m_incoming_cv.wait();
}
@ -360,7 +361,7 @@ void TransportMachPort::wait_until_readable()
void TransportMachPort::post_message(Vector<u8> const& bytes, Vector<Attachment>& attachments)
{
{
Threading::MutexLocker locker(m_send_mutex);
Sync::MutexLocker locker(m_send_mutex);
m_pending_send_messages.append(PendingMessage { bytes, move(attachments) });
}
wake_io_thread();
@ -370,7 +371,7 @@ TransportMachPort::ShouldShutdown TransportMachPort::read_as_many_messages_as_po
{
Vector<NonnullOwnPtr<Message>> messages;
{
Threading::MutexLocker locker(m_incoming_mutex);
Sync::MutexLocker locker(m_incoming_mutex);
messages = move(m_incoming_messages);
}
for (auto& message : messages)

View file

@ -21,7 +21,8 @@
#include <LibIPC/Attachment.h>
#include <LibIPC/AutoCloseFileDescriptor.h>
#include <LibIPC/TransportHandle.h>
#include <LibThreading/ConditionVariable.h>
#include <LibSync/ConditionVariable.h>
#include <LibSync/Mutex.h>
#include <LibThreading/Thread.h>
namespace IPC {
@ -101,11 +102,11 @@ private:
Atomic<bool> m_peer_eof { false };
Vector<PendingMessage> m_pending_send_messages;
Threading::Mutex m_send_mutex;
Sync::Mutex m_send_mutex;
Vector<u8> m_send_buffer;
Threading::Mutex m_incoming_mutex;
Threading::ConditionVariable m_incoming_cv { m_incoming_mutex };
Sync::Mutex m_incoming_mutex;
Sync::ConditionVariable m_incoming_cv { m_incoming_mutex };
Vector<NonnullOwnPtr<Message>> m_incoming_messages;
RefPtr<AutoCloseFileDescriptor> m_notify_hook_read_fd;

View file

@ -16,6 +16,7 @@
#include <LibIPC/Limits.h>
#include <LibIPC/TransportHandle.h>
#include <LibIPC/TransportSocket.h>
#include <LibSync/Mutex.h>
#include <LibThreading/Thread.h>
namespace IPC {
@ -50,7 +51,7 @@ ErrorOr<TransportSocket::Paired> TransportSocket::create_paired()
void SendQueue::enqueue_message(ReadonlyBytes header, ReadonlyBytes payload, Vector<int>&& fds)
{
Threading::MutexLocker locker(m_mutex);
Sync::MutexLocker locker(m_mutex);
VERIFY(MUST(m_stream.write_some(header)) == header.size());
VERIFY(MUST(m_stream.write_some(payload)) == payload.size());
m_fds.append(fds.data(), fds.size());
@ -58,7 +59,7 @@ void SendQueue::enqueue_message(ReadonlyBytes header, ReadonlyBytes payload, Vec
SendQueue::BytesAndFds SendQueue::peek(size_t max_bytes)
{
Threading::MutexLocker locker(m_mutex);
Sync::MutexLocker locker(m_mutex);
BytesAndFds result;
auto bytes_to_send = min(max_bytes, m_stream.used_buffer_size());
result.bytes.resize(bytes_to_send);
@ -74,7 +75,7 @@ SendQueue::BytesAndFds SendQueue::peek(size_t max_bytes)
void SendQueue::discard(size_t bytes_count, size_t fds_count)
{
Threading::MutexLocker locker(m_mutex);
Sync::MutexLocker locker(m_mutex);
MUST(m_stream.discard(bytes_count));
m_fds.remove(0, fds_count);
}
@ -222,7 +223,7 @@ void TransportSocket::set_up_read_hook(Function<void()> hook)
};
{
Threading::MutexLocker locker(m_incoming_mutex);
Sync::MutexLocker locker(m_incoming_mutex);
if (!m_incoming_messages.is_empty()) {
Array<u8, 1> bytes = { 0 };
MUST(Core::System::write(m_notify_hook_write_fd->value(), bytes));
@ -249,7 +250,7 @@ void TransportSocket::close_after_sending_all_pending_messages()
void TransportSocket::wait_until_readable()
{
Threading::MutexLocker lock(m_incoming_mutex);
Sync::MutexLocker lock(m_incoming_mutex);
while (m_incoming_messages.is_empty() && m_io_thread_state == IOThreadState::Running) {
m_incoming_cv.wait();
}
@ -284,7 +285,7 @@ void TransportSocket::post_message(Vector<u8> const& bytes_to_write, Vector<Atta
auto raw_fds = Vector<int, 1> {};
if (num_fds_to_transfer > 0) {
raw_fds.ensure_capacity(num_fds_to_transfer);
Threading::MutexLocker locker(m_fds_retained_until_received_by_peer_mutex);
Sync::MutexLocker locker(m_fds_retained_until_received_by_peer_mutex);
for (auto& attachment : attachments) {
int fd = attachment.to_fd();
auto auto_fd = adopt_ref(*new AutoCloseFileDescriptor(fd));
@ -463,7 +464,7 @@ void TransportSocket::read_incoming_messages()
}
if (acknowledged_fd_count > 0u) {
Threading::MutexLocker locker(m_fds_retained_until_received_by_peer_mutex);
Sync::MutexLocker locker(m_fds_retained_until_received_by_peer_mutex);
while (acknowledged_fd_count > 0u) {
if (m_fds_retained_until_received_by_peer.is_empty()) {
dbgln("TransportSocket: Peer acknowledged more FDs than we sent");
@ -494,7 +495,7 @@ void TransportSocket::read_incoming_messages()
}
if (!batch.is_empty()) {
Threading::MutexLocker locker(m_incoming_mutex);
Sync::MutexLocker locker(m_incoming_mutex);
m_incoming_messages.extend(move(batch));
m_incoming_cv.broadcast();
notify_read_available();
@ -510,7 +511,7 @@ TransportSocket::ShouldShutdown TransportSocket::read_as_many_messages_as_possib
{
Vector<NonnullOwnPtr<Message>> messages;
{
Threading::MutexLocker locker(m_incoming_mutex);
Sync::MutexLocker locker(m_incoming_mutex);
messages = move(m_incoming_messages);
}
for (auto& message : messages)

View file

@ -13,7 +13,8 @@
#include <LibIPC/Attachment.h>
#include <LibIPC/AutoCloseFileDescriptor.h>
#include <LibIPC/TransportHandle.h>
#include <LibThreading/ConditionVariable.h>
#include <LibSync/ConditionVariable.h>
#include <LibSync/Mutex.h>
#include <LibThreading/Forward.h>
namespace IPC {
@ -31,7 +32,7 @@ public:
private:
AllocatingMemoryStream m_stream;
Vector<int> m_fds;
Threading::Mutex m_mutex;
Sync::Mutex m_mutex;
};
class TransportSocket {
@ -99,7 +100,7 @@ private:
// This is necessary to handle a specific behavior of the macOS kernel, which may prematurely garbage-collect the file
// descriptor contained in the message before the peer receives it. https://openradar.me/9477351
Queue<NonnullRefPtr<AutoCloseFileDescriptor>> m_fds_retained_until_received_by_peer;
Threading::Mutex m_fds_retained_until_received_by_peer_mutex;
Sync::Mutex m_fds_retained_until_received_by_peer_mutex;
RefPtr<Threading::Thread> m_io_thread;
RefPtr<SendQueue> m_send_queue;
@ -108,8 +109,8 @@ private:
Atomic<bool> m_peer_eof { false };
ByteBuffer m_unprocessed_bytes;
Queue<Attachment> m_unprocessed_attachments;
Threading::Mutex m_incoming_mutex;
Threading::ConditionVariable m_incoming_cv { m_incoming_mutex };
Sync::Mutex m_incoming_mutex;
Sync::ConditionVariable m_incoming_cv { m_incoming_mutex };
Vector<NonnullOwnPtr<Message>> m_incoming_messages;
RefPtr<AutoCloseFileDescriptor> m_wakeup_io_thread_read_fd;

View file

@ -13,7 +13,7 @@
#include <AK/kmalloc.h>
#include <LibCore/ThreadedPromise.h>
#include <LibMedia/Audio/PlaybackStreamAudioUnit.h>
#include <LibThreading/Mutex.h>
#include <LibSync/Mutex.h>
#include <AudioToolbox/AudioFormat.h>
#include <AudioUnit/AudioUnit.h>
@ -211,7 +211,7 @@ public:
void queue_task(AudioTask task)
{
Threading::MutexLocker lock(m_task_queue_mutex);
Sync::MutexLocker lock(m_task_queue_mutex);
m_task_queue.append(move(task));
m_task_queue_is_empty = false;
}
@ -237,7 +237,7 @@ private:
if (m_task_queue_is_empty.load())
return {};
Threading::MutexLocker lock(m_task_queue_mutex);
Sync::MutexLocker lock(m_task_queue_mutex);
m_task_queue_is_empty = m_task_queue.size() == 1;
return m_task_queue.take_first();
@ -306,7 +306,7 @@ private:
AudioComponentInstance m_audio_unit { nullptr };
SampleSpecification m_sample_specification;
Threading::Mutex m_task_queue_mutex;
Sync::Mutex m_task_queue_mutex;
Vector<AudioTask, 4> m_task_queue;
Atomic<bool> m_task_queue_is_empty { true };

View file

@ -175,7 +175,7 @@ RefPtr<PulseAudioStream> const& PlaybackStreamPulseAudio::InternalState::stream(
void PlaybackStreamPulseAudio::InternalState::enqueue(Function<void()>&& task)
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
m_tasks.enqueue(forward<Function<void()>>(task));
m_wake_condition.signal();
}
@ -184,7 +184,7 @@ void PlaybackStreamPulseAudio::InternalState::thread_loop()
{
while (true) {
auto task = [this]() -> Function<void()> {
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
while (m_tasks.is_empty() && !m_exit)
m_wake_condition.wait();

View file

@ -9,8 +9,8 @@
#include "PlaybackStream.h"
#include "PulseAudioWrappers.h"
#include <AK/Queue.h>
#include <LibThreading/ConditionVariable.h>
#include <LibThreading/Mutex.h>
#include <LibSync/ConditionVariable.h>
#include <LibSync/Mutex.h>
namespace Audio {
@ -48,8 +48,8 @@ private:
RefPtr<PulseAudioStream> m_stream { nullptr };
Queue<Function<void()>> m_tasks;
Threading::Mutex m_mutex;
Threading::ConditionVariable m_wake_condition { m_mutex };
Sync::Mutex m_mutex;
Sync::ConditionVariable m_wake_condition { m_mutex };
Atomic<bool> m_exit { false };
};

View file

@ -25,7 +25,7 @@
#include <LibMedia/Audio/ChannelMap.h>
#include <LibMedia/Audio/PlaybackStreamWasapi.h>
#include <LibMedia/Audio/SampleSpecification.h>
#include <LibThreading/Mutex.h>
#include <LibSync/Mutex.h>
#include <LibThreading/Thread.h>
#include <AK/Windows.h>
@ -100,7 +100,7 @@ struct PlaybackStreamWASAPI::AudioState : public AtomicRefCounted<PlaybackStream
PlaybackStreamWASAPI::AudioDataRequestCallback data_request_callback;
Function<void()> underrun_callback;
Threading::Mutex task_queue_mutex;
Sync::Mutex task_queue_mutex;
Queue<Variant<TaskPlay, TaskDrainAndSuspend, TaskDiscardAndSuspend>> task_queue;
// FIXME: Create a owning handle type to be shared in the codebase
HANDLE task_event = 0;

View file

@ -7,16 +7,16 @@
#include "PulseAudioWrappers.h"
#include <LibMedia/Audio/SampleSpecification.h>
#include <LibThreading/Mutex.h>
#include <LibSync/Mutex.h>
namespace Audio {
static PulseAudioContext* s_pulse_audio_context;
static Threading::Mutex s_pulse_audio_context_mutex;
static Sync::Mutex s_pulse_audio_context_mutex;
ErrorOr<NonnullRefPtr<PulseAudioContext>> PulseAudioContext::the()
{
auto instantiation_locker = Threading::MutexLocker(s_pulse_audio_context_mutex);
auto instantiation_locker = Sync::MutexLocker(s_pulse_audio_context_mutex);
// Lock and unlock the mutex to ensure that the mutex is fully unlocked at application
// exit.
@ -112,7 +112,7 @@ ErrorOr<NonnullRefPtr<PulseAudioContext>> PulseAudioContext::the()
bool PulseAudioContext::is_connected()
{
auto locker = Threading::MutexLocker(s_pulse_audio_context_mutex);
auto locker = Sync::MutexLocker(s_pulse_audio_context_mutex);
return s_pulse_audio_context != nullptr;
}
@ -125,7 +125,7 @@ PulseAudioContext::PulseAudioContext(pa_threaded_mainloop* main_loop, pa_mainloo
PulseAudioContext::~PulseAudioContext()
{
auto locker = Threading::MutexLocker(s_pulse_audio_context_mutex);
auto locker = Sync::MutexLocker(s_pulse_audio_context_mutex);
{
auto loop_locker = main_loop_locker();

View file

@ -20,7 +20,7 @@ set(SOURCES
)
ladybird_lib(LibMedia media EXPLICIT_SYMBOL_EXPORT)
target_link_libraries(LibMedia PRIVATE LibCore LibCrypto LibIPC LibGfx LibThreading LibUnicode)
target_link_libraries(LibMedia PRIVATE LibCore LibCrypto LibIPC LibGfx LibSync LibThreading LibUnicode)
target_sources(LibMedia PRIVATE
FFmpeg/FFmpegAudioConverter.cpp

View file

@ -48,7 +48,7 @@ static TrackEntry::TrackType matroska_track_type_from_track_type(TrackType type)
DecoderErrorOr<void> MatroskaDemuxer::create_context_for_track(Track const& track)
{
auto iterator = TRY(m_reader.create_sample_iterator(m_stream->create_cursor(), track.identifier()));
Threading::MutexLocker locker(m_track_statuses_mutex);
Sync::MutexLocker locker(m_track_statuses_mutex);
VERIFY(m_track_statuses.set(track, TrackStatus(move(iterator))) == HashSetResult::InsertedNewEntry);
return {};
}
@ -81,7 +81,7 @@ DecoderErrorOr<Optional<Track>> MatroskaDemuxer::get_preferred_track_for_type(Tr
MatroskaDemuxer::TrackStatus& MatroskaDemuxer::get_track_status(Track const& track)
{
Threading::MutexLocker locker(m_track_statuses_mutex);
Sync::MutexLocker locker(m_track_statuses_mutex);
auto track_status = m_track_statuses.get(track);
VERIFY(track_status.has_value());
return track_status.release_value();

View file

@ -11,7 +11,7 @@
#include <LibMedia/Export.h>
#include <LibMedia/Forward.h>
#include <LibMedia/IncrementallyPopulatedStream.h>
#include <LibThreading/Mutex.h>
#include <LibSync/Mutex.h>
#include "Reader.h"
@ -64,7 +64,7 @@ private:
NonnullRefPtr<MediaStream> m_stream;
Reader m_reader;
mutable Threading::Mutex m_track_statuses_mutex;
mutable Sync::Mutex m_track_statuses_mutex;
HashMap<Track, TrackStatus> m_track_statuses;
};

View file

@ -39,7 +39,7 @@ IncrementallyPopulatedStream::~IncrementallyPopulatedStream() = default;
void IncrementallyPopulatedStream::set_data_request_callback(DataRequestCallback callback)
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
if (!callback) {
m_callback_event_loop = nullptr;
@ -58,7 +58,7 @@ void IncrementallyPopulatedStream::add_chunk_at(u64 offset, ReadonlyBytes data)
auto new_chunk_end = offset + data.size();
m_last_chunk_end = new_chunk_end;
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
auto previous_chunk_iter = m_chunks.find_largest_not_above_iterator(offset);
@ -103,7 +103,7 @@ void IncrementallyPopulatedStream::add_chunk_at(u64 offset, ReadonlyBytes data)
void IncrementallyPopulatedStream::close()
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
m_expected_size = m_last_chunk_end;
m_closed = true;
m_state_changed.broadcast();
@ -111,7 +111,7 @@ void IncrementallyPopulatedStream::close()
u64 IncrementallyPopulatedStream::size()
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
while (!m_expected_size.has_value())
m_state_changed.wait();
return m_expected_size.value();
@ -119,14 +119,14 @@ u64 IncrementallyPopulatedStream::size()
void IncrementallyPopulatedStream::set_expected_size(u64 expected_size)
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
m_expected_size = expected_size;
m_state_changed.broadcast();
}
Optional<u64> IncrementallyPopulatedStream::expected_size() const
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
return m_expected_size;
}
@ -215,7 +215,7 @@ size_t IncrementallyPopulatedStream::read_from_chunks_while_locked(u64 position,
DecoderErrorOr<size_t> IncrementallyPopulatedStream::read_at(Cursor& cursor, size_t position, Bytes& bytes)
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
auto now = MonotonicTime::now_coarse();
cursor.m_active_timeout = now + CURSOR_ACTIVE_TIME;
@ -249,13 +249,13 @@ NonnullRefPtr<MediaStreamCursor> IncrementallyPopulatedStream::create_cursor()
IncrementallyPopulatedStream::Cursor::Cursor(NonnullRefPtr<IncrementallyPopulatedStream> const& stream)
: m_stream(stream)
{
Threading::MutexLocker locker { m_stream->m_mutex };
Sync::MutexLocker locker { m_stream->m_mutex };
m_stream->m_cursors.append(*this);
}
IncrementallyPopulatedStream::Cursor::~Cursor()
{
Threading::MutexLocker locker { m_stream->m_mutex };
Sync::MutexLocker locker { m_stream->m_mutex };
VERIFY(m_stream->m_cursors.remove_first_matching([&](Cursor const& cursor) { return this == &cursor; }));
}
@ -288,7 +288,7 @@ DecoderErrorOr<size_t> IncrementallyPopulatedStream::Cursor::read_into(Bytes byt
void IncrementallyPopulatedStream::Cursor::abort()
{
Threading::MutexLocker locker { m_stream->m_mutex };
Sync::MutexLocker locker { m_stream->m_mutex };
m_aborted = true;
m_stream->m_state_changed.broadcast();
}

View file

@ -18,8 +18,8 @@
#include <LibMedia/DecoderError.h>
#include <LibMedia/Export.h>
#include <LibMedia/MediaStream.h>
#include <LibThreading/ConditionVariable.h>
#include <LibThreading/Mutex.h>
#include <LibSync/ConditionVariable.h>
#include <LibSync/Mutex.h>
namespace Media {
@ -109,9 +109,9 @@ private:
bool check_if_data_is_available_or_begin_request_while_locked(MonotonicTime now, u64 position, u64 length);
size_t read_from_chunks_while_locked(u64 position, Bytes& bytes) const;
mutable Threading::Mutex m_mutex;
mutable Sync::Mutex m_mutex;
Vector<Cursor&> m_cursors;
Threading::ConditionVariable m_state_changed { m_mutex };
Sync::ConditionVariable m_state_changed { m_mutex };
Chunks m_chunks;
Optional<u64> m_expected_size;

View file

@ -22,7 +22,7 @@
#include <LibMedia/Providers/MediaTimeProvider.h>
#include <LibMedia/TimeRanges.h>
#include <LibMedia/Track.h>
#include <LibThreading/Mutex.h>
#include <LibSync/Mutex.h>
namespace Media {
@ -223,7 +223,7 @@ public:
void revoke(Badge<PlaybackManager>)
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
m_manager = nullptr;
}
@ -234,7 +234,7 @@ private:
VERIFY(&Core::EventLoop::current() == &m_originating_event_loop);
}
mutable Threading::Mutex m_mutex;
mutable Sync::Mutex m_mutex;
PlaybackManager* m_manager { nullptr };
Core::EventLoop& m_originating_event_loop;
};

View file

@ -11,7 +11,7 @@
#include <LibMedia/FFmpeg/FFmpegAudioConverter.h>
#include <LibMedia/FFmpeg/FFmpegAudioDecoder.h>
#include <LibMedia/Sinks/AudioSink.h>
#include <LibThreading/Mutex.h>
#include <LibSync/Mutex.h>
#include <LibThreading/Thread.h>
#include "AudioDataProvider.h"

View file

@ -20,9 +20,9 @@
#include <LibMedia/IncrementallyPopulatedStream.h>
#include <LibMedia/TimeRanges.h>
#include <LibMedia/Track.h>
#include <LibThreading/ConditionVariable.h>
#include <LibSync/ConditionVariable.h>
#include <LibSync/Mutex.h>
#include <LibThreading/Forward.h>
#include <LibThreading/Mutex.h>
namespace Media {
@ -103,7 +103,7 @@ private:
void seek(AK::Duration timestamp, SeekCompletionHandler&&);
[[nodiscard]] Threading::MutexLocker take_lock() const { return Threading::MutexLocker(m_mutex); }
[[nodiscard]] Sync::MutexLocker take_lock() const { return Sync::MutexLocker(m_mutex); }
void wake() const { m_wait_condition.broadcast(); }
AudioDecoder const& decoder() const { return *m_decoder; }
@ -120,8 +120,8 @@ private:
NonnullRefPtr<Core::WeakEventLoopReference> m_main_thread_event_loop;
mutable Threading::Mutex m_mutex;
mutable Threading::ConditionVariable m_wait_condition { m_mutex };
mutable Sync::Mutex m_mutex;
mutable Sync::ConditionVariable m_wait_condition { m_mutex };
RequestedState m_requested_state { RequestedState::None };
NonnullRefPtr<Demuxer> m_demuxer;

View file

@ -20,8 +20,8 @@
#include <LibMedia/SeekMode.h>
#include <LibMedia/TimeRanges.h>
#include <LibMedia/Track.h>
#include <LibThreading/ConditionVariable.h>
#include <LibThreading/Mutex.h>
#include <LibSync/ConditionVariable.h>
#include <LibSync/Mutex.h>
namespace Media {
@ -100,7 +100,7 @@ private:
TimeRanges buffered_time_ranges() const;
[[nodiscard]] Threading::MutexLocker take_lock() const { return Threading::MutexLocker(m_mutex); }
[[nodiscard]] Sync::MutexLocker take_lock() const { return Sync::MutexLocker(m_mutex); }
void wake() const { m_wait_condition.broadcast(); }
private:
@ -113,8 +113,8 @@ private:
NonnullRefPtr<Core::WeakEventLoopReference> m_main_thread_event_loop;
mutable Threading::Mutex m_mutex;
mutable Threading::ConditionVariable m_wait_condition { m_mutex };
mutable Sync::Mutex m_mutex;
mutable Sync::ConditionVariable m_wait_condition { m_mutex };
RequestedState m_requested_state { RequestedState::None };
NonnullRefPtr<Demuxer> m_demuxer;

View file

@ -39,7 +39,7 @@ AudioMixingSink::~AudioMixingSink()
void AudioMixingSink::set_provider(Track const& track, RefPtr<AudioDataProvider> const& provider)
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
m_track_mixing_datas.remove(track);
if (provider == nullptr)
return;
@ -89,7 +89,7 @@ void AudioMixingSink::create_playback_stream()
if (self->m_temporary_time.has_value())
self->set_time(self->m_temporary_time.value());
Threading::MutexLocker locker { self->m_mutex };
Sync::MutexLocker locker { self->m_mutex };
self->m_sample_specification = stream->sample_specification();
for (auto& [track, track_data] : self->m_track_mixing_datas) {
@ -121,7 +121,7 @@ ReadonlySpan<float> AudioMixingSink::write_audio_data_to_playback_stream(Span<fl
auto sample_count = buffer.size() / channel_count;
buffer.fill(0.0f);
Threading::MutexLocker mixing_data_locker { m_mutex };
Sync::MutexLocker mixing_data_locker { m_mutex };
auto buffer_start = m_next_sample_to_write.load();
auto samples_end = buffer_start + static_cast<i64>(sample_count);
@ -341,7 +341,7 @@ void AudioMixingSink::set_time(AK::Duration time)
self->m_last_media_time = self->m_temporary_time.release_value();
{
Threading::MutexLocker mixing_locker { self->m_mutex };
Sync::MutexLocker mixing_locker { self->m_mutex };
self->m_next_sample_to_write = self->m_last_media_time.to_time_units(1, self->m_sample_specification.sample_rate());
}

View file

@ -15,8 +15,8 @@
#include <LibMedia/Forward.h>
#include <LibMedia/Providers/MediaTimeProvider.h>
#include <LibMedia/Sinks/AudioSink.h>
#include <LibThreading/ConditionVariable.h>
#include <LibThreading/Mutex.h>
#include <LibSync/ConditionVariable.h>
#include <LibSync/Mutex.h>
namespace Media {
@ -53,17 +53,17 @@ private:
void emplace(AudioMixingSink& sink) { m_ptr = &sink; }
RefPtr<AudioMixingSink> take_strong() const
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
return m_ptr;
}
void revoke()
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
m_ptr = nullptr;
}
private:
mutable Threading::Mutex m_mutex;
mutable Sync::Mutex m_mutex;
AudioMixingSink* m_ptr { nullptr };
};
@ -84,8 +84,8 @@ private:
Core::EventLoop& m_main_thread_event_loop;
NonnullRefPtr<AudioMixingSinkWeakReference> m_weak_self;
Threading::Mutex m_mutex;
Threading::ConditionVariable m_wait_condition { m_mutex };
Sync::Mutex m_mutex;
Sync::ConditionVariable m_wait_condition { m_mutex };
bool m_creating_playback_stream { false };
RefPtr<Audio::PlaybackStream> m_playback_stream;
Audio::SampleSpecification m_sample_specification;

View file

@ -0,0 +1,5 @@
set(SOURCES
Mutex.cpp
)
ladybird_lib(LibSync sync EXPLICIT_SYMBOL_EXPORT)

View file

@ -7,11 +7,11 @@
#pragma once
#include <AK/Function.h>
#include <LibThreading/Mutex.h>
#include <LibSync/Mutex.h>
#include <pthread.h>
#include <sys/types.h>
namespace Threading {
namespace Sync {
// A signaling condition variable that wraps over the pthread_cond_* APIs.
class ConditionVariable {

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2018-2021, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2021, kleines Filmröllchen <malu.bertsch@gmail.com>
* Copyright (c) 2025, Ryszard Goc <ryszardgoc@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibSync/Mutex.h>
#include <pthread.h>
namespace Sync {
Mutex::Mutex()
: m_lock_count(0)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_mutex, &attr);
pthread_mutexattr_destroy(&attr);
}
Mutex::~Mutex()
{
VERIFY(m_lock_count == 0);
pthread_mutex_destroy(&m_mutex);
}
}

View file

@ -10,30 +10,19 @@
#include <AK/Assertions.h>
#include <AK/Noncopyable.h>
#include <AK/Types.h>
#include <LibSync/Export.h>
#include <pthread.h>
namespace Threading {
namespace Sync {
class Mutex {
class SYNC_API Mutex {
AK_MAKE_NONCOPYABLE(Mutex);
AK_MAKE_NONMOVABLE(Mutex);
friend class ConditionVariable;
public:
Mutex()
: m_lock_count(0)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_mutex, &attr);
pthread_mutexattr_destroy(&attr);
}
~Mutex()
{
VERIFY(m_lock_count == 0);
pthread_mutex_destroy(&m_mutex);
}
Mutex();
~Mutex();
void lock();
void unlock();
@ -43,7 +32,7 @@ private:
unsigned m_lock_count { 0 };
};
class [[nodiscard]] MutexLocker {
class [[nodiscard]] SYNC_API MutexLocker {
AK_MAKE_NONCOPYABLE(MutexLocker);
AK_MAKE_NONMOVABLE(MutexLocker);

View file

@ -8,9 +8,9 @@
#include <AK/Concepts.h>
#include <AK/Noncopyable.h>
#include <LibThreading/Mutex.h>
#include <LibSync/Mutex.h>
namespace Threading {
namespace Sync {
template<typename T>
class MutexProtected {

View file

@ -8,12 +8,12 @@
#include <AK/Atomic.h>
#include <AK/Concepts.h>
#include <LibThreading/Mutex.h>
#include <LibSync/Mutex.h>
namespace Threading {
namespace Sync {
struct OnceFlag {
Mutex mutex;
Sync::Mutex mutex;
Atomic<bool> has_been_called { false };
};
@ -21,7 +21,7 @@ template<VoidFunction Callable>
void call_once(OnceFlag& flag, Callable&& callable)
{
if (!flag.has_been_called.load(MemoryOrder::memory_order_acquire)) {
MutexLocker lock(flag.mutex);
Sync::MutexLocker lock(flag.mutex);
// Another thread may have called the function while we were waiting on the mutex
// The mutex guarantees exclusivity so we can use relaxed ordering

View file

@ -11,7 +11,7 @@
#include <AK/Types.h>
#include <pthread.h>
namespace Threading {
namespace Sync {
class RWLock {
AK_MAKE_NONCOPYABLE(RWLock);

View file

@ -8,9 +8,9 @@
#include <AK/Concepts.h>
#include <AK/Noncopyable.h>
#include <LibThreading/RWLock.h>
#include <LibSync/RWLock.h>
namespace Threading {
namespace Sync {
template<typename T>
class RWLockProtected {

View file

@ -6,8 +6,8 @@
*/
#include <AK/Queue.h>
#include <LibSync/Mutex.h>
#include <LibThreading/BackgroundAction.h>
#include <LibThreading/Mutex.h>
#include <LibThreading/Thread.h>
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;

View file

@ -5,7 +5,7 @@ set(SOURCES
)
ladybird_lib(LibThreading threading)
target_link_libraries(LibThreading PRIVATE LibCore)
target_link_libraries(LibThreading PRIVATE LibCore LibSync)
if (WIN32)
target_include_directories(LibThreading PUBLIC $<BUILD_INTERFACE:${PTHREAD_INCLUDE_DIR}>)

View file

@ -36,7 +36,7 @@ intptr_t ThreadPool::worker_thread_func()
Function<void()> work;
{
MutexLocker locker(m_mutex);
Sync::MutexLocker locker(m_mutex);
m_condition.wait_while([this] { return m_work_queue.is_empty(); });
work = m_work_queue.dequeue();
}
@ -47,7 +47,7 @@ intptr_t ThreadPool::worker_thread_func()
void ThreadPool::submit(Function<void()> work)
{
MutexLocker locker(m_mutex);
Sync::MutexLocker locker(m_mutex);
m_work_queue.enqueue(move(work));
m_condition.signal();
}

View file

@ -9,8 +9,8 @@
#include <AK/Function.h>
#include <AK/Queue.h>
#include <AK/Vector.h>
#include <LibThreading/ConditionVariable.h>
#include <LibThreading/Mutex.h>
#include <LibSync/ConditionVariable.h>
#include <LibSync/Mutex.h>
#include <LibThreading/Thread.h>
namespace Threading {
@ -26,8 +26,8 @@ private:
intptr_t worker_thread_func();
Mutex m_mutex;
ConditionVariable m_condition { m_mutex };
Sync::Mutex m_mutex;
Sync::ConditionVariable m_condition { m_mutex };
Queue<Function<void()>> m_work_queue;
Vector<NonnullRefPtr<Thread>> m_threads;
};

View file

@ -1247,7 +1247,7 @@ set(GENERATED_SOURCES
ladybird_lib(LibWeb web EXPLICIT_SYMBOL_EXPORT)
target_link_libraries(LibWeb PRIVATE LibCore LibCompress LibCrypto LibJS LibHTTP LibGfx LibIPC LibRegex LibSyntax LibTextCodec LibUnicode LibMedia LibWasm LibXML LibIDL LibURL LibTLS LibRequests LibGC LibThreading skia ${ANGLE_TARGETS} SDL3::SDL3 LibXml2::LibXml2)
target_link_libraries(LibWeb PRIVATE LibCore LibCompress LibCrypto LibJS LibHTTP LibGfx LibIPC LibRegex LibSyntax LibTextCodec LibUnicode LibMedia LibWasm LibXML LibIDL LibURL LibTLS LibRequests LibGC LibSync LibThreading skia ${ANGLE_TARGETS} SDL3::SDL3 LibXml2::LibXml2)
import_rust_crate(MANIFEST_PATH Rust/Cargo.toml CRATE_NAME libweb_rust FFI_HEADER RustFFI.h)
target_link_libraries(LibWeb PRIVATE libweb_rust)

View file

@ -145,13 +145,13 @@ public:
void set_presentation_mode(RenderingThread::PresentationMode mode)
{
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
m_presentation_mode = move(mode);
}
void exit()
{
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
m_exit = true;
m_command_ready.signal();
m_ready_to_paint.signal();
@ -160,14 +160,14 @@ public:
void enqueue_command(CompositorCommand&& command)
{
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
m_command_queue.enqueue(move(command));
m_command_ready.signal();
}
u64 set_needs_present(Gfx::IntRect viewport_rect)
{
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
m_needs_present = true;
m_pending_viewport_rect = viewport_rect;
m_submitted_frame_id++;
@ -177,14 +177,14 @@ public:
void mark_frame_complete(u64 frame_id)
{
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
m_completed_frame_id = frame_id;
m_frame_completed.broadcast();
}
void wait_for_frame(u64 frame_id)
{
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
while (m_completed_frame_id < frame_id && !m_exit)
m_frame_completed.wait();
}
@ -195,7 +195,7 @@ public:
while (true) {
{
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
while (m_command_queue.is_empty() && !m_needs_present && !m_exit) {
m_command_ready.wait();
}
@ -209,7 +209,7 @@ public:
while (true) {
auto command = [this]() -> Optional<CompositorCommand> {
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
if (m_command_queue.is_empty())
return {};
return m_command_queue.dequeue();
@ -250,7 +250,7 @@ public:
Gfx::IntRect viewport_rect;
u64 presenting_frame_id = 0;
{
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
if (m_needs_present) {
should_present = true;
viewport_rect = m_pending_viewport_rect;
@ -262,7 +262,7 @@ public:
if (should_present) {
// Block if we already have a frame queued (back pressure)
{
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
while (m_queued_rasterization_tasks > 1 && !m_exit) {
m_ready_to_paint.wait();
}
@ -271,7 +271,7 @@ public:
}
auto presentation_mode = [this] {
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
return m_presentation_mode;
}();
@ -368,8 +368,8 @@ private:
NonnullRefPtr<Core::WeakEventLoopReference> m_main_thread_event_loop;
RenderingThread::PresentationCallback m_presentation_callback;
mutable Threading::Mutex m_mutex;
mutable Threading::ConditionVariable m_command_ready { m_mutex };
mutable Sync::Mutex m_mutex;
mutable Sync::ConditionVariable m_command_ready { m_mutex };
Atomic<bool> m_exit { false };
Queue<CompositorCommand> m_command_queue;
@ -382,19 +382,19 @@ private:
RenderingThread::PresentationMode m_presentation_mode { RenderingThread::PresentToUI {} };
Atomic<i32> m_queued_rasterization_tasks { 0 };
mutable Threading::ConditionVariable m_ready_to_paint { m_mutex };
mutable Sync::ConditionVariable m_ready_to_paint { m_mutex };
bool m_needs_present { false };
Gfx::IntRect m_pending_viewport_rect;
u64 m_submitted_frame_id { 0 };
u64 m_completed_frame_id { 0 };
mutable Threading::ConditionVariable m_frame_completed { m_mutex };
mutable Sync::ConditionVariable m_frame_completed { m_mutex };
public:
void decrement_queued_tasks()
{
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
VERIFY(m_queued_rasterization_tasks >= 1 && m_queued_rasterization_tasks <= 2);
m_queued_rasterization_tasks--;
m_ready_to_paint.signal();

View file

@ -11,9 +11,8 @@
#include <AK/Queue.h>
#include <AK/Variant.h>
#include <LibGfx/SharedImage.h>
#include <LibThreading/ConditionVariable.h>
#include <LibSync/ConditionVariable.h>
#include <LibThreading/Forward.h>
#include <LibThreading/Mutex.h>
#include <LibWeb/Forward.h>
#include <LibWeb/Page/Page.h>

View file

@ -20,7 +20,7 @@ TrackBufferDemuxer::~TrackBufferDemuxer() = default;
Media::TimeRanges TrackBufferDemuxer::track_buffer_ranges() const
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
// https://w3c.github.io/media-source/#track-buffer-ranges
// NOTE: Implementations MAY coalesce adjacent ranges separated by a gap smaller than 2 times the
// maximum frame duration buffered so far in this track buffer.
@ -32,7 +32,7 @@ Media::TimeRanges TrackBufferDemuxer::track_buffer_ranges() const
void TrackBufferDemuxer::add_coded_frame(Media::CodedFrame frame)
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
auto start = frame.timestamp();
auto end = frame.timestamp() + frame.duration();
m_last_frame_duration = frame.duration();
@ -60,7 +60,7 @@ void TrackBufferDemuxer::add_coded_frame(Media::CodedFrame frame)
void TrackBufferDemuxer::remove_coded_frames_and_dependants_in_range(AK::Duration start, AK::Duration end)
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
// https://w3c.github.io/media-source/#sourcebuffer-coded-frame-processing
// 1.13. Remove all coded frames from track buffer that have a presentation timestamp greater than
@ -107,14 +107,14 @@ void TrackBufferDemuxer::remove_coded_frames_and_dependants_in_range(AK::Duratio
void TrackBufferDemuxer::set_reached_end_of_stream()
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
m_reached_end_of_stream = true;
m_data_changed.broadcast();
}
void TrackBufferDemuxer::clear_reached_end_of_stream()
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
m_reached_end_of_stream = false;
}
@ -155,7 +155,7 @@ bool TrackBufferDemuxer::next_frame_is_in_gap_while_locked() const
Media::DecoderErrorOr<Media::CodedFrame> TrackBufferDemuxer::get_next_sample_for_track(Media::Track const&)
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
while (m_read_position >= m_coded_frames.size() || next_frame_is_in_gap_while_locked()) {
if (m_aborted.load())
@ -181,7 +181,7 @@ Media::DecoderErrorOr<ReadonlyBytes> TrackBufferDemuxer::get_codec_initializatio
Media::DecoderErrorOr<Media::DemuxerSeekResult> TrackBufferDemuxer::seek_to_most_recent_keyframe(Media::Track const&, AK::Duration timestamp, Media::DemuxerSeekOptions)
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
size_t best_position = 0;
AK::Duration best_timestamp;
@ -254,7 +254,7 @@ Media::TimeRanges TrackBufferDemuxer::buffered_time_ranges() const
void TrackBufferDemuxer::set_blocking_reads_aborted_for_track(Media::Track const&)
{
m_aborted.store(true);
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
m_data_changed.broadcast();
}
@ -265,7 +265,7 @@ void TrackBufferDemuxer::reset_blocking_reads_aborted_for_track(Media::Track con
bool TrackBufferDemuxer::is_read_blocked_for_track(Media::Track const&)
{
Threading::MutexLocker locker { m_mutex };
Sync::MutexLocker locker { m_mutex };
if (m_aborted.load())
return false;
return m_read_position >= m_coded_frames.size() || next_frame_is_in_gap_while_locked();

View file

@ -13,8 +13,8 @@
#include <LibMedia/CodedFrame.h>
#include <LibMedia/Demuxer.h>
#include <LibMedia/TimeRanges.h>
#include <LibThreading/ConditionVariable.h>
#include <LibThreading/Mutex.h>
#include <LibSync/ConditionVariable.h>
#include <LibSync/Mutex.h>
namespace Web::MediaSourceExtensions {
@ -60,8 +60,8 @@ private:
Media::CodecID m_codec_id;
ByteBuffer m_codec_initialization_data;
mutable Threading::Mutex m_mutex;
Threading::ConditionVariable m_data_changed { m_mutex };
mutable Sync::Mutex m_mutex;
Sync::ConditionVariable m_data_changed { m_mutex };
Vector<Media::CodedFrame> m_coded_frames;
size_t m_read_position { 0 };

View file

@ -26,7 +26,7 @@ void ExternalContentSource::update(Optional<Gfx::DecodedImageFrame> frame)
{
Optional<Gfx::DecodedImageFrame> old;
{
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
old = move(m_frame);
m_frame = move(frame);
}
@ -36,14 +36,14 @@ void ExternalContentSource::clear()
{
Optional<Gfx::DecodedImageFrame> old;
{
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
old = move(m_frame);
}
}
Optional<Gfx::DecodedImageFrame> ExternalContentSource::current_frame() const
{
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
return m_frame;
}

View file

@ -11,7 +11,7 @@
#include <AK/Optional.h>
#include <LibGfx/DecodedImageFrame.h>
#include <LibGfx/Forward.h>
#include <LibThreading/Mutex.h>
#include <LibSync/Mutex.h>
namespace Web::Painting {
@ -29,7 +29,7 @@ private:
ExternalContentSource();
u64 m_id { 0 };
mutable Threading::Mutex m_mutex;
mutable Sync::Mutex m_mutex;
Optional<Gfx::DecodedImageFrame> m_frame;
};

View file

@ -28,7 +28,7 @@ void VideoFrameSource::update(RefPtr<Media::VideoFrame> frame)
{
RefPtr<Media::VideoFrame> old;
{
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
old = move(m_frame);
m_frame = move(frame);
}
@ -38,14 +38,14 @@ void VideoFrameSource::clear()
{
RefPtr<Media::VideoFrame> old;
{
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
old = move(m_frame);
}
}
RefPtr<Media::VideoFrame> VideoFrameSource::current_frame() const
{
Threading::MutexLocker const locker { m_mutex };
Sync::MutexLocker const locker { m_mutex };
return m_frame;
}

View file

@ -9,7 +9,7 @@
#include <AK/AtomicRefCounted.h>
#include <AK/RefPtr.h>
#include <LibMedia/Forward.h>
#include <LibThreading/Mutex.h>
#include <LibSync/Mutex.h>
namespace Web::Painting {
@ -28,7 +28,7 @@ private:
VideoFrameSource();
u64 m_id { 0 };
mutable Threading::Mutex m_mutex;
mutable Sync::Mutex m_mutex;
RefPtr<Media::VideoFrame> m_frame;
};

View file

@ -9,13 +9,13 @@ namespace Web::WebAudio {
void ControlMessageQueue::enqueue(ControlMessage message)
{
Threading::MutexLocker locker(m_mutex);
Sync::MutexLocker locker(m_mutex);
m_messages.append(move(message));
}
Vector<ControlMessage> ControlMessageQueue::drain()
{
Threading::MutexLocker locker(m_mutex);
Sync::MutexLocker locker(m_mutex);
return move(m_messages);
}

View file

@ -7,7 +7,7 @@
#pragma once
#include <AK/Vector.h>
#include <LibThreading/Mutex.h>
#include <LibSync/Mutex.h>
#include <LibWeb/Export.h>
#include <LibWeb/WebAudio/ControlMessage.h>
@ -21,7 +21,7 @@ public:
Vector<ControlMessage> drain(); // Called by the rendering thread.
private:
mutable Threading::Mutex m_mutex;
mutable Sync::Mutex m_mutex;
Vector<ControlMessage> m_messages;
};

View file

@ -75,7 +75,7 @@ compile_ipc(${LADYBIRD_SOURCE_DIR}/Services/WebContent/WebUIClient.ipc ${CMAKE_B
compile_ipc(${LADYBIRD_SOURCE_DIR}/Services/WebContent/WebUIServer.ipc ${CMAKE_BINARY_DIR}/Services/WebContent/WebUIServerEndpoint.h)
ladybird_lib(LibWebView webview EXPLICIT_SYMBOL_EXPORT)
target_link_libraries(LibWebView PRIVATE LibCore LibDatabase LibDevTools LibFileSystem LibGfx LibHTTP LibImageDecoderClient LibIPC LibRequests LibJS LibWeb LibUnicode LibURL LibSyntax LibTextCodec)
target_link_libraries(LibWebView PRIVATE LibCore LibDatabase LibDevTools LibFileSystem LibGfx LibHTTP LibImageDecoderClient LibIPC LibRequests LibJS LibWeb LibUnicode LibURL LibSync LibSyntax LibTextCodec)
# Third-party
if (HAS_FONTCONFIG)

View file

@ -69,7 +69,7 @@ ErrorOr<Process::ProcessAndIPCTransport> Process::spawn_and_connect_to_process(C
auto port_b_recv = TRY(Core::MachPort::create_with_right(Core::MachPort::PortRight::Receive));
auto port_b_send = TRY(port_b_recv.insert_right(Core::MachPort::MessageRight::MakeSend));
Threading::MutexLocker child_registration_locker(Application::transport_bootstrap_server().child_registration_lock());
Sync::MutexLocker child_registration_locker(Application::transport_bootstrap_server().child_registration_lock());
auto process = TRY(Core::Process::spawn(spawn_options));
Application::transport_bootstrap_server().register_child_transport(process.pid(), IPC::TransportBootstrapMachPorts { move(port_b_recv), move(port_a_send) });

View file

@ -23,7 +23,7 @@ target_include_directories(imagedecoderservice PRIVATE ${CMAKE_CURRENT_BINARY_DI
target_include_directories(imagedecoderservice PRIVATE ${LADYBIRD_SOURCE_DIR}/Services/)
target_link_libraries(ImageDecoder PRIVATE imagedecoderservice LibCore LibMain LibThreading)
target_link_libraries(imagedecoderservice PRIVATE LibCore LibGfx LibIPC LibImageDecoderClient LibMain LibThreading)
target_link_libraries(imagedecoderservice PRIVATE LibCore LibGfx LibIPC LibImageDecoderClient LibMain LibSync LibThreading)
if (WIN32)
ladybird_windows_bin(ImageDecoder CONSOLE)

View file

@ -12,7 +12,7 @@ target_include_directories(WebDriver PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/../..)
target_include_directories(WebDriver PRIVATE ${LADYBIRD_SOURCE_DIR})
target_include_directories(WebDriver PRIVATE ${LADYBIRD_SOURCE_DIR}/Services)
target_link_libraries(WebDriver PRIVATE LibCore LibFileSystem LibGfx LibIPC LibJS LibMain LibWeb LibWebSocket LibWebView)
target_link_libraries(WebDriver PRIVATE LibCore LibFileSystem LibGfx LibIPC LibJS LibMain LibSync LibWeb LibWebSocket LibWebView)
target_link_libraries(WebDriver PRIVATE OpenSSL::Crypto OpenSSL::SSL)
if (WIN32)

View file

@ -20,12 +20,12 @@ foreach(source IN LISTS TEST_SOURCES)
ladybird_test("${source}" LibCore)
endforeach()
target_link_libraries(TestLibCorePromise PRIVATE LibThreading)
target_link_libraries(TestLibCoreStream PRIVATE LibThreading)
target_link_libraries(TestLibCorePromise PRIVATE LibSync LibThreading)
target_link_libraries(TestLibCoreStream PRIVATE LibSync LibThreading)
if(NOT WIN32)
# These tests use the .txt files in the current directory
set_tests_properties(TestLibCoreMappedFile TestLibCoreStream PROPERTIES WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
target_link_libraries(TestLibCoreEventLoop PRIVATE LibThreading)
target_link_libraries(TestLibCoreEventLoop PRIVATE LibSync LibThreading)

View file

@ -18,7 +18,7 @@ set(TEST_SOURCES
)
foreach(source IN LISTS TEST_SOURCES)
ladybird_test("${source}" LibMedia LIBS LibMedia LibFileSystem)
ladybird_test("${source}" LibMedia LIBS LibMedia LibFileSystem LibSync)
endforeach()
target_link_libraries(TestFFmpegDemuxer PRIVATE LibThreading)

View file

@ -6,3 +6,5 @@ set(TEST_SOURCES
foreach(source IN LISTS TEST_SOURCES)
ladybird_test("${source}" LibThreading LIBS LibThreading)
endforeach()
target_link_libraries(TestBackgroundAction PRIVATE LibSync)

View file

@ -24,6 +24,7 @@ endforeach()
ladybird_utility(css-tokenizer SOURCES css-tokenizer.cpp LIBS LibFileSystem LibMain LibWeb)
target_link_libraries(TestContentFilter PRIVATE LibURL)
target_link_libraries(TestControlMessageQueue PRIVATE LibSync)
target_link_libraries(TestFetchURL PRIVATE LibURL)
target_link_libraries(TestSourceHighlighter PRIVATE LibURL LibWebView)

View file

@ -13,7 +13,7 @@
#include <LibCore/Event.h>
#include <LibCore/Notifier.h>
#include <LibCore/ThreadEventQueue.h>
#include <LibThreading/RWLock.h>
#include <LibSync/RWLock.h>
#import <Cocoa/Cocoa.h>
#import <CoreFoundation/CoreFoundation.h>
@ -28,7 +28,7 @@ struct ThreadData;
static thread_local OwnPtr<ThreadData> s_this_thread_data;
static HashMap<pthread_t, ThreadData*> s_thread_data;
static thread_local pthread_t s_thread_id;
static Threading::RWLock s_thread_data_lock;
static Sync::RWLock s_thread_data_lock;
struct ThreadData {
static ThreadData& the()
@ -37,7 +37,7 @@ struct ThreadData {
s_thread_id = pthread_self();
if (!s_this_thread_data) {
s_this_thread_data = make<ThreadData>();
Threading::RWLockLocker<Threading::LockMode::Write> locker(s_thread_data_lock);
Sync::RWLockLocker<Sync::LockMode::Write> locker(s_thread_data_lock);
s_thread_data.set(s_thread_id, s_this_thread_data);
}
return *s_this_thread_data;
@ -45,13 +45,13 @@ struct ThreadData {
static ThreadData* for_thread(pthread_t thread_id)
{
Threading::RWLockLocker<Threading::LockMode::Read> locker(s_thread_data_lock);
Sync::RWLockLocker<Sync::LockMode::Read> locker(s_thread_data_lock);
return s_thread_data.get(thread_id).value_or(nullptr);
}
~ThreadData()
{
Threading::RWLockLocker<Threading::LockMode::Write> locker(s_thread_data_lock);
Sync::RWLockLocker<Sync::LockMode::Write> locker(s_thread_data_lock);
s_thread_data.remove(s_thread_id);
}

View file

@ -59,7 +59,7 @@ else()
set(LADYBIRD_TARGET ladybird PRIVATE)
endif()
set(LADYBIRD_LIBS AK LibCore LibFileSystem LibGfx LibImageDecoderClient LibIPC LibJS LibMain LibWeb LibWebView LibRequests LibURL)
set(LADYBIRD_LIBS AK LibCore LibFileSystem LibGfx LibImageDecoderClient LibIPC LibJS LibMain LibWeb LibWebView LibRequests LibSync LibURL)
target_link_libraries(${LADYBIRD_TARGET} PRIVATE ${LADYBIRD_LIBS})
target_link_libraries(${LADYBIRD_TARGET} PRIVATE OpenSSL::Crypto OpenSSL::SSL)

View file

@ -10,7 +10,7 @@
#include <LibCore/Notifier.h>
#include <LibCore/System.h>
#include <LibCore/ThreadEventQueue.h>
#include <LibThreading/Mutex.h>
#include <LibSync/Mutex.h>
#include <UI/Gtk/EventLoopImplementationGtk.h>
#include <glib-unix.h>
@ -19,7 +19,7 @@
namespace Ladybird {
static HashMap<Core::Notifier*, guint> s_notifiers;
static Threading::Mutex s_notifiers_mutex;
static Sync::Mutex s_notifiers_mutex;
// Signal handling for signals not supported by g_unix_signal_add
// (which only handles SIGHUP, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, SIGWINCH).
@ -144,13 +144,13 @@ void EventLoopManagerGtk::register_notifier(Core::Notifier& notifier)
auto weak_notifier = new WeakPtr<Core::EventReceiver>(notifier.make_weak_ptr());
auto source_id = g_unix_fd_add_full(G_PRIORITY_DEFAULT, notifier.fd(), condition, notifier_callback, weak_notifier, notifier_destroy);
Threading::MutexLocker locker(s_notifiers_mutex);
Sync::MutexLocker locker(s_notifiers_mutex);
s_notifiers.set(&notifier, source_id);
}
void EventLoopManagerGtk::unregister_notifier(Core::Notifier& notifier)
{
Threading::MutexLocker locker(s_notifiers_mutex);
Sync::MutexLocker locker(s_notifiers_mutex);
auto it = s_notifiers.find(&notifier);
if (it == s_notifiers.end())
return;

View file

@ -14,9 +14,9 @@
#include <LibCore/SocketAddress.h>
#include <LibCore/System.h>
#include <LibCore/ThreadEventQueue.h>
#include <LibThreading/Mutex.h>
#include <LibThreading/MutexProtected.h>
#include <LibThreading/RWLock.h>
#include <LibSync/Mutex.h>
#include <LibSync/MutexProtected.h>
#include <LibSync/RWLock.h>
#include <UI/Qt/EventLoopImplementationQt.h>
#include <UI/Qt/EventLoopImplementationQtEventTarget.h>
@ -36,10 +36,10 @@ namespace Ladybird {
struct ThreadData;
static thread_local OwnPtr<ThreadData> s_this_thread_data;
static HashMap<pthread_t, ThreadData*> s_thread_data;
static Threading::RWLock s_thread_data_lock;
static Sync::RWLock s_thread_data_lock;
static thread_local Optional<pthread_t> s_thread_id;
#if defined(AK_OS_WINDOWS)
static Threading::MutexProtected<HashMap<pid_t, QWinEventNotifier*>> s_processes;
static Sync::MutexProtected<HashMap<pid_t, QWinEventNotifier*>> s_processes;
#endif
struct ThreadData {
@ -49,7 +49,7 @@ struct ThreadData {
s_thread_id = pthread_self();
if (!s_this_thread_data) {
s_this_thread_data = make<ThreadData>();
Threading::RWLockLocker<Threading::LockMode::Write> locker(s_thread_data_lock);
Sync::RWLockLocker<Sync::LockMode::Write> locker(s_thread_data_lock);
s_thread_data.set(s_thread_id.value(), s_this_thread_data.ptr());
}
return *s_this_thread_data;
@ -57,17 +57,17 @@ struct ThreadData {
static ThreadData* for_thread(pthread_t thread_id)
{
Threading::RWLockLocker<Threading::LockMode::Read> locker(s_thread_data_lock);
Sync::RWLockLocker<Sync::LockMode::Read> locker(s_thread_data_lock);
return s_thread_data.get(thread_id).value_or(nullptr);
}
~ThreadData()
{
Threading::RWLockLocker<Threading::LockMode::Write> locker(s_thread_data_lock);
Sync::RWLockLocker<Sync::LockMode::Write> locker(s_thread_data_lock);
s_thread_data.remove(s_thread_id.value());
}
Threading::Mutex mutex;
Sync::Mutex mutex;
HashMap<Core::Notifier*, NonnullOwnPtr<QSocketNotifier>> notifiers;
};
@ -325,7 +325,7 @@ void EventLoopManagerQt::register_notifier(Core::Notifier& notifier)
{
auto& thread_data = ThreadData::the();
Threading::MutexLocker locker(thread_data.mutex);
Sync::MutexLocker locker(thread_data.mutex);
thread_data.notifiers.set(&notifier, move(socket_notifier));
}
notifier.set_owner_thread(s_thread_id.value());
@ -336,7 +336,7 @@ void EventLoopManagerQt::unregister_notifier(Core::Notifier& notifier)
auto* thread_data = ThreadData::for_thread(notifier.owner_thread());
if (!thread_data)
return;
Threading::MutexLocker locker(thread_data->mutex);
Sync::MutexLocker locker(thread_data->mutex);
auto deleted_notifier = thread_data->notifiers.take(&notifier).release_value();
if (QThread::currentThread() != deleted_notifier->thread()) {
auto* deleted_notifier_ptr = deleted_notifier.ptr();