/* * Copyright (c) 2018-2021, Andreas Kling * Copyright (c) 2021, kleines Filmröllchen * Copyright (c) 2025, Ryszard Goc * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #if !defined(AK_OS_WINDOWS) # include #endif namespace Sync { template class MutexBase; template requires Detail::IsIntraprocess && Detail::IsNonRecursive class ConditionVariableBase; template class SYNC_API MutexBase { AK_MAKE_NONCOPYABLE(MutexBase); AK_MAKE_NONMOVABLE(MutexBase); template requires Detail::IsIntraprocess && Detail::IsNonRecursive friend class ConditionVariableBase; public: using InterprocessPolicyType = InterprocessPolicy; using RecursivePolicyType = RecursivePolicy; MutexBase(); ~MutexBase(); bool try_lock(); void lock(); void unlock(); private: static consteval u64 storage_size() { #ifdef AK_OS_WINDOWS if constexpr (IsSame) { // Size of a handle return sizeof(void*); } if constexpr (IsSame) { // The size of a critical section. This is guaranteed return 40; } // SRWLock is just a void* return sizeof(void*); #else return sizeof(pthread_mutex_t); #endif } alignas(void*) unsigned char m_storage[storage_size()]; }; using Mutex = MutexBase; using RecursiveMutex = MutexBase; using IPCMutex = MutexBase; using IPCRecursiveMutex = MutexBase; template class [[nodiscard]] SYNC_API MutexLocker { AK_MAKE_NONCOPYABLE(MutexLocker); AK_MAKE_NONMOVABLE(MutexLocker); public: ALWAYS_INLINE explicit MutexLocker(MutexType& mutex) : m_mutex(mutex) { lock(); } ALWAYS_INLINE ~MutexLocker() { unlock(); } ALWAYS_INLINE void unlock() { m_mutex.unlock(); } ALWAYS_INLINE void lock() { m_mutex.lock(); } private: MutexType& m_mutex; }; template MutexLocker(MutexType&) -> MutexLocker; }