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 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 
41 namespace 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 ///
52 struct 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  ///
70  int getCode(
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 ///
82 class 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.
98  Lock(
99  Lock const&
100  );
101  Lock& operator=(
102  Lock const&
103  );
104 
105 public:
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 ///
178 class LockRAII {
179 
180  Lock *const lck; ///< lock
181 
182  /// No copying or assignment for instances of this class.
183  LockRAII(
184  LockRAII const &
185  );
186  LockRAII const &operator=(
187  LockRAII const &
188  );
189 
190 public:
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 ///
237 class LockRAIIHelper : public LockRAII {
238 
239  int count;
240 
242  LockRAIIHelper const &
243  );
244  LockRAIIHelper const &operator=(
245  LockRAIIHelper const &
246  );
247 
248 public:
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.
LockRAII(Lock *l)
Constructor. The constructor calls l->lock() to acquire the lock.
Definition: paraPthLock.h:196
LockRAIIHelper(Lock *l)
Definition: paraPthLock.h:250
void lock()
Acquire this lock. The function sets the internal file/line (debugging) fields to generic values...
Definition: paraPthLock.h:133
int code
error code
Definition: paraPthLock.h:54
~Lock()
Destroy this lock.
Definition: paraPthLock.h:122
int getCode()
get error code
Definition: paraPthLock.h:70
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
LockRAIIHelper(Lock *l, char const *file, int line)
Definition: paraPthLock.h:258
void unlock()
Release this lock.
Definition: paraPthLock.h:161
pthread_mutex_t mtx
The low-level mutex that implements this lock.
Definition: paraPthLock.h:86
LockRAIIHelper & operator++()
Definition: paraPthLock.h:274
Lock *const lck
lock
Definition: paraPthLock.h:180
int line
Line at which the lock was last acquired (debugging).
Definition: paraPthLock.h:88
Class that implements a lock. The class wraps around pthread_mutex_t and adds some safeguards...
Definition: paraPthLock.h:82
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, char const *file, int line)
Constructor. The constructor calls l->lock(file,line) to acquire the lock.
Definition: paraPthLock.h:210
Same as LockRAII but with additional members to implement the LOCKED macro.
Definition: paraPthLock.h:237
Exception that is thrown whenever something goes wrong with a lock.
Definition: paraPthLock.h:52
Lock()
Initialize this lock.
Definition: paraPthLock.h:109
char const * file
File in which the lock was last acquired (debugging).
Definition: paraPthLock.h:87
~LockRAII()
Destructor. Releases the lock that was acquired in the constructor.
Definition: paraPthLock.h:225
#define LOCK_VERBOSE
Definition: paraPthLock.h:46
LockException(int c=0)
constructor
Definition: paraPthLock.h:59