ladybird/Libraries/LibSync/RWLock.h
R-Goc 125b399a72 LibSync: Remove pthread from the RWLock interface
This commit removes any use of pthread.h from the RWLock header. It also
adds a win32 implementation of RWLock.

Support for interprocess RWLocks is left to a later PR.

Due to the API design of SRWLock the unlock methods must match the lock
method.
2026-05-08 18:58:35 -05:00

92 lines
1.8 KiB
C++

/*
* Copyright (c) 2024, Ali Mohammad Pur <mpfard@serenityos.org>
* Copyright (c) 2025, Ryszard Goc <ryszardgoc@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Noncopyable.h>
#include <AK/Platform.h>
#include <AK/Types.h>
#include <LibSync/Export.h>
#if !defined(AK_OS_WINDOWS)
# include <pthread.h>
#endif
namespace Sync {
// TODO: Implement interprocess RWLocks. This needs a hand-rolled implementation for win32.
class SYNC_API RWLock {
AK_MAKE_NONCOPYABLE(RWLock);
AK_MAKE_NONMOVABLE(RWLock);
public:
RWLock();
~RWLock();
bool try_lock_read();
bool try_lock_write();
// Recursively acquiring a RWLock is not supported
void lock_read();
void lock_write();
// NOTE: While the pthread api has one unlock method, the Win32 api has separate ones per lock mode
void unlock_read();
void unlock_write();
private:
#ifdef AK_OS_WINDOWS
using StorageType = void*;
#else
using StorageType = pthread_rwlock_t;
#endif
alignas(StorageType) unsigned char m_storage[sizeof(StorageType)];
};
enum class LockMode : u8 {
Read,
Write,
};
template<LockMode mode>
class SYNC_API RWLockLocker {
AK_MAKE_NONCOPYABLE(RWLockLocker);
AK_MAKE_NONMOVABLE(RWLockLocker);
public:
ALWAYS_INLINE explicit RWLockLocker(RWLock& l)
: m_lock(l)
{
lock();
}
ALWAYS_INLINE ~RWLockLocker()
{
unlock();
}
ALWAYS_INLINE void unlock()
{
if constexpr (mode == LockMode::Read)
m_lock.unlock_read();
else
m_lock.unlock_write();
}
ALWAYS_INLINE void lock()
{
if constexpr (mode == LockMode::Read)
m_lock.lock_read();
else
m_lock.lock_write();
}
private:
RWLock& m_lock;
};
}