src/srw_shared_mutex.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "DetourModKit/srw_shared_mutex.hpp" | ||
| 2 | |||
| 3 | #include <windows.h> | ||
| 4 | #include <new> | ||
| 5 | #include <type_traits> | ||
| 6 | |||
| 7 | namespace DetourModKit | ||
| 8 | { | ||
| 9 | namespace detail | ||
| 10 | { | ||
| 11 | static_assert(sizeof(SrwSharedMutex) == sizeof(SRWLOCK)); | ||
| 12 | static_assert(alignof(SrwSharedMutex) == alignof(SRWLOCK)); | ||
| 13 | // The defaulted destructor never runs ~SRWLOCK on the placement-new'd object; that is only correct while | ||
| 14 | // SRWLOCK stays trivially destructible (releasing the storage then legally ends its lifetime). | ||
| 15 | static_assert(std::is_trivially_destructible_v<SRWLOCK>); | ||
| 16 | |||
| 17 | namespace | ||
| 18 | { | ||
| 19 | /** | ||
| 20 | * @brief Converts SrwSharedMutex opaque storage back to the native Windows lock. | ||
| 21 | * @details std::launder is required: the byte array only provides storage for the SRWLOCK created by | ||
| 22 | * placement new in the constructor, and an array element is not pointer-interconvertible with | ||
| 23 | * the object nested in it, so the bare reinterpret_cast would still designate the byte element. | ||
| 24 | * @param storage Storage owned by a live SrwSharedMutex instance. | ||
| 25 | * @return Pointer to the SRWLOCK object living in the byte buffer. | ||
| 26 | */ | ||
| 27 | 1237672 | [[nodiscard]] SRWLOCK *native_lock(std::byte *storage) noexcept | |
| 28 | { | ||
| 29 | 1237672 | return std::launder(reinterpret_cast<SRWLOCK *>(storage)); | |
| 30 | } | ||
| 31 | } // namespace | ||
| 32 | |||
| 33 | 6254 | SrwSharedMutex::SrwSharedMutex() noexcept | |
| 34 | { | ||
| 35 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 6254 times.
|
6254 | auto *lock = ::new (static_cast<void *>(m_srw_storage)) SRWLOCK{}; |
| 36 | 6254 | InitializeSRWLock(lock); | |
| 37 | 6254 | } | |
| 38 | |||
| 39 | 10218 | void SrwSharedMutex::lock() noexcept | |
| 40 | { | ||
| 41 | 10218 | AcquireSRWLockExclusive(native_lock(m_srw_storage)); | |
| 42 | 10218 | } | |
| 43 | |||
| 44 | 1201 | bool SrwSharedMutex::try_lock() noexcept | |
| 45 | { | ||
| 46 | 1201 | return TryAcquireSRWLockExclusive(native_lock(m_srw_storage)) != 0; | |
| 47 | } | ||
| 48 | |||
| 49 | 10915 | void SrwSharedMutex::unlock() noexcept | |
| 50 | { | ||
| 51 | 10915 | ReleaseSRWLockExclusive(native_lock(m_srw_storage)); | |
| 52 | 10915 | } | |
| 53 | |||
| 54 | 620230 | void SrwSharedMutex::lock_shared() noexcept | |
| 55 | { | ||
| 56 | 620230 | AcquireSRWLockShared(native_lock(m_srw_storage)); | |
| 57 | 647435 | } | |
| 58 | |||
| 59 | 19 | bool SrwSharedMutex::try_lock_shared() noexcept | |
| 60 | { | ||
| 61 | 19 | return TryAcquireSRWLockShared(native_lock(m_srw_storage)) != 0; | |
| 62 | } | ||
| 63 | |||
| 64 | 621410 | void SrwSharedMutex::unlock_shared() noexcept | |
| 65 | { | ||
| 66 | 621410 | ReleaseSRWLockShared(native_lock(m_srw_storage)); | |
| 67 | 641325 | } | |
| 68 | } // namespace detail | ||
| 69 | } // namespace DetourModKit | ||
| 70 |