TryReadLock And TryWriteLock In UE4

Introduction

I simply need to implement FTryReadScopeLock and FTryWriteScopeLock for some of my features these days.

For the moment, the only way to try get lock is to use FScopeTryLock, which is based on a critical section.

But unfortunately, there is no try get lock method for Readers-writer lock in UE4.

Thus I’ve extend the FRWLock implementation for both Windows and pthreads.

Implementation

Extending ScopeRWLock.h

Add a FTryReadScopeLock class like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

/** Try to get a FRWLock read-locked while this scope lives
* This is a utility class that handles scope level locking using TryLock.
* Scope locking helps to avoid programming errors by which a lock is acquired
* and never released.
*
* <code>
* {
* // Try to acquire a lock on CriticalSection for the current scope.
* FTryReadScopeLock ScopeTryLock(CriticalSection);
* // Check that the lock was acquired.
* if (ScopeTryLock.IsLocked())
* {
* // If the lock was acquired, we can safely access resources protected
* // by the lock.
* }
* // When ScopeTryLock goes out of scope, the critical section will be
* // released if it was ever acquired.
* }
* </code>
*/
class FTryReadScopeLock
{
public:
explicit FTryReadScopeLock(FRWLock* InLock)
: Lock(InLock)
{
check(Lock);

if (!Lock->TryReadLock())
{
Lock = nullptr;
}

}

~FTryReadScopeLock()
{
if (Lock)
{
Lock->ReadUnlock();
}

}

FORCEINLINE bool IsLocked() const
{
return nullptr != Lock;
}

private:
FRWLock* Lock;

UE_NONCOPYABLE(FTryReadScopeLock);
};

Implementation For PThreadRWLock Platform

Add TryReadLock and TryWriteLock method to PThreadRWLock.h:

1
2
3
4
5
6
7
8
9
bool TryReadLock()
{
return 0 == pthread_rwlock_tryrdlock(&Mutex);
}

bool TryWriteLock()
{
return 0 == pthread_rwlock_trywrlock(&Mutex);
}

This shall work for most of non-Windows platform.

Implementation For WindowsPlatform

Modification For MinimalWindowsApi.h

1
2
MINIMAL_WINDOWS_API bool WINAPI TryAcquireSRWLockExclusive(PSRWLOCK SRWLock);
MINIMAL_WINDOWS_API bool WINAPI TryAcquireSRWLockShared(PSRWLOCK SRWLock);

Modification For MinimalWindowsApi.cpp

1
2
3
4
5
6
7
8
9
MINIMAL_WINDOWS_API bool WINAPI TryAcquireSRWLockExclusive(PSRWLOCK SRWLock)
{
return ::TryAcquireSRWLockExclusive((::PSRWLOCK)SRWLock);
}

MINIMAL_WINDOWS_API bool WINAPI TryAcquireSRWLockShared(PSRWLOCK SRWLock)
{
return ::TryAcquireSRWLockShared((::PSRWLOCK)SRWLock);
}

Modification For WindowsCriticalSection.h

1
2
3
4
5
6
7
8
9
FORCEINLINE bool TryReadLock()
{
return Windows::TryAcquireSRWLockShared(&Mutex);
}

FORCEINLINE bool TryWriteLock()
{
return Windows::TryAcquireSRWLockExclusive(&Mutex);
}

And everything is good to go.

I am so cute, please give me money...