CppCommon 1.0.5.0
C++ Common Library
Loading...
Searching...
No Matches
rw_lock.cpp
Go to the documentation of this file.
1
9#include "threads/rw_lock.h"
10
11#include "threads/thread.h"
13
14#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
15#include "errors/fatal.h"
16#include <pthread.h>
17#elif defined(_WIN32) || defined(_WIN64)
18#include <windows.h>
19#undef Yield
20#endif
21
22namespace CppCommon {
23
25
26class RWLock::Impl
27{
28public:
29 Impl()
30 {
31#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
32 int result = pthread_rwlock_init(&_rwlock, nullptr);
33 if (result != 0)
34 throwex SystemException("Failed to initialize a read/write lock!", result);
35#elif defined(_WIN32) || defined(_WIN64)
36 InitializeSRWLock(&_rwlock);
37#endif
38 }
39
40 ~Impl()
41 {
42#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
43 int result = pthread_rwlock_destroy(&_rwlock);
44 if (result != 0)
45 fatality(SystemException("Failed to destroy a read/write lock!", result));
46#elif defined(_WIN32) || defined(_WIN64)
47 // SRW locks do not need to be explicitly destroyed.
48#endif
49 }
50
51 bool TryLockRead()
52 {
53#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
54 int result = pthread_rwlock_tryrdlock(&_rwlock);
55 if ((result != 0) && (result != EAGAIN) && (result != EBUSY) && (result != EDEADLK))
56 throwex SystemException("Failed to try lock for read!", result);
57 return (result == 0);
58#elif defined(_WIN32) || defined(_WIN64)
59 return (TryAcquireSRWLockShared(&_rwlock) != 0);
60#endif
61 }
62
63 bool TryLockWrite()
64 {
65#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
66 int result = pthread_rwlock_trywrlock(&_rwlock);
67 if ((result != 0) && (result != EAGAIN) && (result != EBUSY) && (result != EDEADLK))
68 throwex SystemException("Failed to try lock for write!", result);
69 return (result == 0);
70#elif defined(_WIN32) || defined(_WIN64)
71 return (TryAcquireSRWLockExclusive(&_rwlock) != 0);
72#endif
73 }
74
75 void LockRead()
76 {
77#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
78 int result = pthread_rwlock_rdlock(&_rwlock);
79 if (result != 0)
80 throwex SystemException("Failed to lock for read!", result);
81#elif defined(_WIN32) || defined(_WIN64)
82 AcquireSRWLockShared(&_rwlock);
83#endif
84 }
85
86 void LockWrite()
87 {
88#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
89 int result = pthread_rwlock_wrlock(&_rwlock);
90 if (result != 0)
91 throwex SystemException("Failed to lock for write!", result);
92#elif defined(_WIN32) || defined(_WIN64)
93 AcquireSRWLockExclusive(&_rwlock);
94#endif
95 }
96
97 void UnlockRead()
98 {
99#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
100 int result = pthread_rwlock_unlock(&_rwlock);
101 if (result != 0)
102 throwex SystemException("Failed to unlock read lock!", result);
103#elif defined(_WIN32) || defined(_WIN64)
104 ReleaseSRWLockShared(&_rwlock);
105#endif
106 }
107
108 void UnlockWrite()
109 {
110#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
111 int result = pthread_rwlock_unlock(&_rwlock);
112 if (result != 0)
113 throwex SystemException("Failed to unlock write lock!", result);
114#elif defined(_WIN32) || defined(_WIN64)
115 ReleaseSRWLockExclusive(&_rwlock);
116#endif
117 }
118
119private:
120#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
121 pthread_rwlock_t _rwlock;
122#elif defined(_WIN32) || defined(_WIN64)
123 SRWLOCK _rwlock;
124#endif
125};
126
128
130{
131 // Check implementation storage parameters
132 [[maybe_unused]] ValidateAlignedStorage<sizeof(Impl), alignof(Impl), StorageSize, StorageAlign> _;
133 static_assert((StorageSize >= sizeof(Impl)), "RWLock::StorageSize must be increased!");
134 static_assert(((StorageAlign % alignof(Impl)) == 0), "RWLock::StorageAlign must be adjusted!");
135
136 // Create the implementation instance
137 new(&_storage)Impl();
138}
139
141{
142 // Delete the implementation instance
143 reinterpret_cast<Impl*>(&_storage)->~Impl();
144}
145
146bool RWLock::TryLockRead() { return impl().TryLockRead(); }
147bool RWLock::TryLockWrite() { return impl().TryLockWrite(); }
148
149bool RWLock::TryLockReadFor(const Timespan& timespan)
150{
151 // Calculate a finish timestamp
152 Timestamp finish = NanoTimestamp() + timespan;
153
154 // Try to acquire read lock at least one time
155 if (TryLockRead())
156 return true;
157 else
158 {
159 // Try lock or yield for the given timespan
160 while (NanoTimestamp() < finish)
161 {
162 if (TryLockRead())
163 return true;
164 else
166 }
167
168 // Failed to acquire read lock
169 return false;
170 }
171}
172
174{
175 // Calculate a finish timestamp
176 Timestamp finish = NanoTimestamp() + timespan;
177
178 // Try to acquire write lock at least one time
179 if (TryLockWrite())
180 return true;
181 else
182 {
183 // Try lock or yield for the given timespan
184 while (NanoTimestamp() < finish)
185 {
186 if (TryLockWrite())
187 return true;
188 else
190 }
191
192 // Failed to acquire write lock
193 return false;
194 }
195}
196
197void RWLock::LockRead() { impl().LockRead(); }
198void RWLock::LockWrite() { impl().LockWrite(); }
199void RWLock::UnlockRead() { impl().UnlockRead(); }
200void RWLock::UnlockWrite() { impl().UnlockWrite(); }
201
202} // namespace CppCommon
High resolution timestamp.
Definition timestamp.h:272
void UnlockRead()
Release read lock.
Definition rw_lock.cpp:199
void LockWrite()
Acquire write lock with block.
Definition rw_lock.cpp:198
void UnlockWrite()
Release write lock.
Definition rw_lock.cpp:200
bool TryLockRead()
Try to acquire read lock without block.
Definition rw_lock.cpp:146
void LockRead()
Acquire read lock with block.
Definition rw_lock.cpp:197
bool TryLockReadFor(const Timespan &timespan)
Try to acquire read lock for the given timespan.
Definition rw_lock.cpp:149
bool TryLockWrite()
Try to acquire write lock without block.
Definition rw_lock.cpp:147
bool TryLockWriteFor(const Timespan &timespan)
Try to acquire write lock for the given timespan.
Definition rw_lock.cpp:173
static void Yield() noexcept
Yield to other threads.
Definition thread.cpp:143
#define throwex
Throw extended exception macro.
Definition exceptions.h:23
Fatal abort execution definition.
#define fatality(...)
Fatal abort execution extended macro.
Definition fatal.h:22
C++ Common project definitions.
Read/Write lock synchronization primitive definition.
Thread definition.
Aligned storage validator definition.