CoDiPack  2.2.0
A Code Differentiation Package
SciComp TU Kaiserslautern
Loading...
Searching...
No Matches
readWriteMutex.hpp
1/*
2 * CoDiPack, a Code Differentiation Package
3 *
4 * Copyright (C) 2015-2024 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau
5 * Homepage: http://www.scicomp.uni-kl.de
6 * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de)
7 *
8 * Lead developers: Max Sagebaum, Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau)
9 *
10 * This file is part of CoDiPack (http://www.scicomp.uni-kl.de/software/codi).
11 *
12 * CoDiPack is free software: you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, either version 3 of the
15 * License, or (at your option) any later version.
16 *
17 * CoDiPack is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty
19 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * See the GNU General Public License for more details.
22 * You should have received a copy of the GNU
23 * General Public License along with CoDiPack.
24 * If not, see <http://www.gnu.org/licenses/>.
25 *
26 * For other licensing options please contact us.
27 *
28 * Authors:
29 * - SciComp, University of Kaiserslautern-Landau:
30 * - Max Sagebaum
31 * - Johannes Blühdorn
32 * - Former members:
33 * - Tim Albring
34 */
35#pragma once
36
37#include "../../misc/macros.hpp"
38#include "atomicInterface.hpp"
39#include "threadInformationInterface.hpp"
40
41#ifdef __SANITIZE_THREAD__
42 #define ANNOTATE_RWLOCK_CREATE(lock) AnnotateRWLockCreate(__FILE__, __LINE__, (void*)lock)
43 #define ANNOTATE_RWLOCK_DESTROY(lock) AnnotateRWLockDestroy(__FILE__, __LINE__, (void*)lock)
44 #define ANNOTATE_RWLOCK_ACQUIRED(lock, isWrite) AnnotateRWLockAcquired(__FILE__, __LINE__, (void*)lock, isWrite)
45 #define ANNOTATE_RWLOCK_RELEASED(lock, isWrite) AnnotateRWLockReleased(__FILE__, __LINE__, (void*)lock, isWrite)
46
47extern "C" void AnnotateRWLockCreate(const char* f, int l, void* addr);
48extern "C" void AnnotateRWLockDestroy(const char* f, int l, void* addr);
49extern "C" void AnnotateRWLockAcquired(const char* f, int l, void* addr, size_t isWrite);
50extern "C" void AnnotateRWLockReleased(const char* f, int l, void* addr, size_t isWrite);
51#endif
52
54namespace codi {
55
73 template<typename T_ThreadInformation, typename T_AtomicInt>
75 public:
77 using AtomicInt = CODI_DD(T_AtomicInt, CODI_DEFAULT_ATOMIC<int>);
78
79 private:
80 AtomicInt numReaders;
81 AtomicInt numWriters;
82 int* nestingDepth;
83
84#ifdef __SANITIZE_THREAD__
85 int dummy;
86#endif
87
88 public:
91 : numReaders(0),
92 numWriters(0),
93 nestingDepth(new int[ThreadInformation::getMaxThreads()]{})
94#ifdef __SANITIZE_THREAD__
95 ,
96 dummy(0)
97#endif
98 {
99#ifdef __SANITIZE_THREAD__
100 ANNOTATE_RWLOCK_CREATE(&dummy);
101#endif
102 }
103
106 delete[] nestingDepth;
107#ifdef __SANITIZE_THREAD__
108 ANNOTATE_RWLOCK_DESTROY(&dummy);
109#endif
110 }
111
117 void lockRead() {
118 int currentWriters;
119 while (true) {
120 // nested lock for read
121 int const threadId = ThreadInformation::getThreadId();
122 if (nestingDepth[threadId] > 0) {
123 ++nestingDepth[threadId];
124 break;
125 }
126
127 // wait until there are no writers
128 do {
129 currentWriters = numWriters;
130 } while (currentWriters > 0);
131 // register reader
132 ++numReaders;
133 // success if there are still no writers
134 currentWriters = numWriters;
135 if (currentWriters == 0) {
136 ++nestingDepth[threadId];
137 break;
138 }
139 // otherwise let writers go first and try again
140 --numReaders;
141 }
142
143#ifdef __SANITIZE_THREAD__
144 ANNOTATE_RWLOCK_ACQUIRED(&dummy, false);
145#endif
146 }
147
149 void unlockRead() {
150#ifdef __SANITIZE_THREAD__
151 ANNOTATE_RWLOCK_RELEASED(&dummy, false);
152#endif
153 int const threadId = ThreadInformation::getThreadId();
154 --nestingDepth[threadId];
155 if (nestingDepth[threadId] == 0) {
156 --numReaders;
157 }
158 }
159
166 void lockWrite() {
167 int currentWriters;
168 while (true) {
169 // register writer
170 currentWriters = ++numWriters;
171 // success if we are the first/only writer
172 if (currentWriters == 1) {
173 break;
174 }
175 // otherwise try again
176 --numWriters;
177 }
178
179 int currentReaders;
180 // wait until there are no readers
181 do {
182 currentReaders = numReaders;
183 } while (currentReaders != 0);
184
185#ifdef __SANITIZE_THREAD__
186 ANNOTATE_RWLOCK_ACQUIRED(&dummy, true);
187#endif
188 }
189
191 void unlockWrite() {
192#ifdef __SANITIZE_THREAD__
193 ANNOTATE_RWLOCK_RELEASED(&dummy, true);
194#endif
195
196 --numWriters;
197 }
198 };
199
205 template<typename T_ReadWriteMutex>
206 struct LockForRead {
207 public:
209 CODI_DD(T_ReadWriteMutex,
210 CODI_T(ReadWriteMutex<DefaultThreadInformation, CODI_DEFAULT_ATOMIC<int>>));
211
212 private:
213 ReadWriteMutex& mutex;
214
215 public:
217 LockForRead(ReadWriteMutex& mutex) : mutex(mutex) {
218 mutex.lockRead();
219 }
220
223 mutex.unlockRead();
224 }
225 };
226
232 template<typename T_ReadWriteMutex>
234 public:
236 CODI_DD(T_ReadWriteMutex,
237 CODI_T(ReadWriteMutex<DefaultThreadInformation, CODI_DEFAULT_ATOMIC<int>>));
238
239 private:
240 ReadWriteMutex& mutex;
241
242 public:
244 LockForWrite(ReadWriteMutex& mutex) : mutex(mutex) {
245 mutex.lockWrite();
246 }
247
250 mutex.unlockWrite();
251 }
252 };
253}
#define CODI_INLINE
See codi::Config::ForcedInlines.
Definition: config.h:457
#define CODI_DD(Type, Default)
Abbreviation for CODI_DECLARE_DEFAULT.
Definition: macros.hpp:94
#define CODI_T(...)
Abbreviation for CODI_TEMPLATE.
Definition: macros.hpp:111
CoDiPack - Code Differentiation Package.
Definition: codi.hpp:90
Default implementation of ThreadInformationInterface for serial applications.
Definition: threadInformationInterface.hpp:63
RAII lock for read. ´
Definition: readWriteMutex.hpp:206
LockForRead(ReadWriteMutex &mutex)
Constructor. Acquires lock for read access.
Definition: readWriteMutex.hpp:217
~LockForRead()
Destructor. Releases lock for read access.
Definition: readWriteMutex.hpp:222
T_ReadWriteMutex ReadWriteMutex
See LockForRead.
Definition: readWriteMutex.hpp:210
RAII lock for write.
Definition: readWriteMutex.hpp:233
~LockForWrite()
Destructor. Releases lock for write access.
Definition: readWriteMutex.hpp:249
T_ReadWriteMutex ReadWriteMutex
See LockForWrite.
Definition: readWriteMutex.hpp:237
LockForWrite(ReadWriteMutex &mutex)
Constructor. Acquires lock for write access.
Definition: readWriteMutex.hpp:244
Mutex construct that distinguishes between lock for read and lock for write.
Definition: readWriteMutex.hpp:74
ReadWriteMutex()
Constructor.
Definition: readWriteMutex.hpp:90
T_ThreadInformation ThreadInformation
See ReadWriteMutex.
Definition: readWriteMutex.hpp:76
T_AtomicInt AtomicInt
See ReadWriteMutex.
Definition: readWriteMutex.hpp:77
void lockWrite()
Acquire mutex for write access.
Definition: readWriteMutex.hpp:166
void lockRead()
Acquire mutex for read access.
Definition: readWriteMutex.hpp:117
~ReadWriteMutex()
Destructor.
Definition: readWriteMutex.hpp:105
void unlockWrite()
Release mutex that was acquired for write access.
Definition: readWriteMutex.hpp:191
void unlockRead()
Release mutex that was acquired for read access.
Definition: readWriteMutex.hpp:149
Provides information on threads.
Definition: threadInformationInterface.hpp:45