Scippy

UG

Ubiquity Generator framework

paraPthLock.h
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and software framework */
4/* UG --- Ubquity Generator Framework */
5/* */
6/* Copyright Written by Yuji Shinano <shinano@zib.de>, */
7/* Copyright (C) 2021-2024 by Zuse Institute Berlin, */
8/* licensed under LGPL version 3 or later. */
9/* Commercial licenses are available through <licenses@zib.de> */
10/* */
11/* This code is free software; you can redistribute it and/or */
12/* modify it under the terms of the GNU Lesser General Public License */
13/* as published by the Free Software Foundation; either version 3 */
14/* of the License, or (at your option) any later version. */
15/* */
16/* This program is distributed in the hope that it will be useful, */
17/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
18/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
19/* GNU Lesser General Public License for more details. */
20/* */
21/* You should have received a copy of the GNU Lesser General Public License */
22/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
23/* */
24/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
25
26/**@file paraPthLock.h
27 * @brief Pthread lock for UG Framework
28 * @author Yuji Shinano
29 *
30 * Many thanks to Daniel Junglas.
31 *
32 */
33
34/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35
36#ifndef __PARA_PTH_LOCK_H__
37#define __PARA_PTH_LOCK_H__
38#include <pthread.h>
39#include <iostream>
40
41namespace UG
42{
43
44// #define LOCK_VERBOSE 1 // undef or define to 0 to disable output
45#ifndef LOCK_VERBOSE
46# define LOCK_VERBOSE 0
47#endif
48
49///
50/// Exception that is thrown whenever something goes wrong with a lock.
51///
52struct LockException : public std::exception {
53
54 int code; ///< error code
55
56 ///
57 /// constructor
58 ///
60 int c = 0 ///< no error is assumed
61 )
62 : code(c)
63 {
64 }
65
66 ///
67 /// get error code
68 /// @return error code
69 ///
71 )
72 {
73 return code;
74 }
75
76};
77
78///
79/// Class that implements a lock.
80/// The class wraps around pthread_mutex_t and adds some safeguards.
81///
82class Lock {
83
84 friend class ConditionVariable;
85
86 pthread_mutex_t mtx; ///< The low-level mutex that implements this lock.
87 char const *file; ///< File in which the lock was last acquired (debugging).
88 int line; ///< Line at which the lock was last acquired (debugging).
89
90 /// Code like this
91 /// pthread_mutex_t m1, m2;
92 /// pthread_mutex_init(&m1, 0);
93 /// m2 = m1;
94 /// results in undefined behavior. So we must never assign one instance
95 /// of pthread_mutex_t to another. To do that we make the copy constructor
96 /// and the assignment operator private and do not implement it. This way
97 /// locks can be passed around only by reference or pointer.
99 Lock const&
100 );
102 Lock const&
103 );
104
105public:
106 ///
107 /// Initialize this lock.
108 ///
110 )
111 : file(0),
112 line(-1)
113 {
114 int const error = pthread_mutex_init(&mtx, 0);
115 if ( error )
116 throw LockException(error);
117 }
118
119 ///
120 /// Destroy this lock.
121 ///
123 )
124 {
125 pthread_mutex_destroy(&mtx);
126 }
127
128 ///
129 /// Acquire this lock.
130 /// The function sets the internal file/line (debugging) fields to
131 /// generic values.
132 ///
133 void lock(
134 )
135 {
136 lock("?", 0);
137 }
138
139 ///
140 /// Acquire this lock.
141 /// The function sets the internal file/line (debugging) fields to
142 /// the values specified by f and l.
143 ///
144 void lock(
145 char const *f, ///< file name
146 int l ///< line number
147 )
148 {
149 int const error = pthread_mutex_lock(&mtx);
150 if ( error )
151 throw LockException(error);
152 file = f;
153 line = l;
154 if ( LOCK_VERBOSE )
155 std::cout << "locked:" << &mtx << std::endl;
156 }
157
158 ///
159 /// Release this lock.
160 ///
161 void unlock(
162 )
163 {
164 if ( LOCK_VERBOSE )
165 std::cout << "unlocked:" << &mtx << std::endl;
166 file = 0;
167 line = -1;
168 int const error = pthread_mutex_unlock(&mtx);
169 if ( error )
170 throw LockException(error);
171 }
172};
173
174///
175/// Class to do RAII with a lock.
176/// The constructor will acquire the lock and the destructor will delete it.
177///
178class LockRAII {
179
180 Lock *const lck; ///< lock
181
182 /// No copying or assignment for instances of this class.
184 LockRAII const &
185 );
187 LockRAII const &
188 );
189
190public:
191
192 ///
193 /// Constructor.
194 /// The constructor calls l->lock() to acquire the lock.
195 ///
197 Lock *l
198 )
199 : lck(l)
200 {
201 if ( !lck )
202 throw LockException(-1);
203 lck->lock();
204 }
205
206 ///
207 /// Constructor.
208 /// The constructor calls l->lock(file,line) to acquire the lock.
209 ///
211 Lock *l,
212 char const *file,
213 int line
214 )
215 : lck(l)
216 {
217 if ( !lck )
218 throw LockException(-1);
219 lck->lock(file, line);
220 }
221 ///
222 /// Destructor.
223 /// Releases the lock that was acquired in the constructor.
224 ///
226 )
227 {
228 lck->unlock();
229 }
230
231};
232
233///
234/// Same as LockRAII but with additional members to implement the LOCKED
235/// macro.
236///
237class LockRAIIHelper : public LockRAII {
238
239 int count;
240
242 LockRAIIHelper const &
243 );
245 LockRAIIHelper const &
246 );
247
248public:
249
251 Lock *l
252 )
253 : LockRAII(l),
254 count(0)
255 {
256 }
257
259 Lock *l,
260 char const *file,
261 int line
262 )
263 : LockRAII(l, file, line),
264 count(0)
265 {
266 }
267
268 operator bool(
269 ) const
270 {
271 return count == 0;
272 }
273
275 )
276 {
277 ++count; return *this;
278 }
279
280};
281
282/** Macro to execute code that is guarded by a lock.
283 * Usage is like this:
284 * <code>
285 Lock l;
286 LOCKED(&l) CODE
287 </code>
288 * where CODE is either a single statement or a block.
289 * The macro acquires l, executes CODE and then releases l. Acquisition
290 * and release of the lock are exception safe.
291 */
292#define LOCKED(lck) \
293 for (LockRAIIHelper raii_(lck,__FILE__, __LINE__); raii_; ++raii_)
294
295#define LOCK_RAII(lck) \
296 LockRAII raii_(lck, __FILE__, __LINE__)
297
298}
299
300#endif // __PARA_PTH_LOCK_H__
Condition variable.
Same as LockRAII but with additional members to implement the LOCKED macro.
Definition: paraPthLock.h:237
LockRAIIHelper(Lock *l, char const *file, int line)
Definition: paraPthLock.h:258
LockRAIIHelper const & operator=(LockRAIIHelper const &)
LockRAIIHelper(Lock *l)
Definition: paraPthLock.h:250
LockRAIIHelper(LockRAIIHelper const &)
LockRAIIHelper & operator++()
Definition: paraPthLock.h:274
Class to do RAII with a lock. The constructor will acquire the lock and the destructor will delete it...
Definition: paraPthLock.h:178
LockRAII(Lock *l)
Constructor. The constructor calls l->lock() to acquire the lock.
Definition: paraPthLock.h:196
LockRAII(Lock *l, char const *file, int line)
Constructor. The constructor calls l->lock(file,line) to acquire the lock.
Definition: paraPthLock.h:210
LockRAII(LockRAII const &)
No copying or assignment for instances of this class.
Lock *const lck
lock
Definition: paraPthLock.h:180
LockRAII const & operator=(LockRAII const &)
~LockRAII()
Destructor. Releases the lock that was acquired in the constructor.
Definition: paraPthLock.h:225
Class that implements a lock. The class wraps around pthread_mutex_t and adds some safeguards.
Definition: paraPthLock.h:82
void lock(char const *f, int l)
Acquire this lock. The function sets the internal file/line (debugging) fields to the values specifie...
Definition: paraPthLock.h:144
pthread_mutex_t mtx
The low-level mutex that implements this lock.
Definition: paraPthLock.h:86
int line
Line at which the lock was last acquired (debugging).
Definition: paraPthLock.h:88
char const * file
File in which the lock was last acquired (debugging).
Definition: paraPthLock.h:87
Lock(Lock const &)
Code like this pthread_mutex_t m1, m2; pthread_mutex_init(&m1, 0); m2 = m1; results in undefined beha...
Lock & operator=(Lock const &)
Lock()
Initialize this lock.
Definition: paraPthLock.h:109
void unlock()
Release this lock.
Definition: paraPthLock.h:161
void lock()
Acquire this lock. The function sets the internal file/line (debugging) fields to generic values.
Definition: paraPthLock.h:133
~Lock()
Destroy this lock.
Definition: paraPthLock.h:122
#define LOCK_VERBOSE
Definition: paraPthLock.h:46
Exception that is thrown whenever something goes wrong with a lock.
Definition: paraPthLock.h:52
int code
error code
Definition: paraPthLock.h:54
int getCode()
get error code
Definition: paraPthLock.h:70
LockException(int c=0)
constructor
Definition: paraPthLock.h:59