ThreadWeaver

debuggingaids.h
1 /* -*- C++ -*-
2  This file declares debugging aids for multithreaded applications.
3 
4  SPDX-FileCopyrightText: 2004-2013 Mirko Boehm <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 
8  $Id: DebuggingAids.h 30 2005-08-16 16:16:04Z mirko $
9 */
10 
11 // krazy:excludeall=inline
12 
13 #ifndef DEBUGGINGAIDS_H
14 #define DEBUGGINGAIDS_H
15 
16 #include <QtGlobal>
17 
18 extern "C" {
19 #include <stdarg.h>
20 #ifndef Q_OS_WIN
21 #include <unistd.h>
22 #endif
23 #include <assert.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 }
27 
28 #include "threadweaver_export.h"
29 #include <QMutex>
30 #include <QString>
31 
32 namespace ThreadWeaver
33 {
34 extern THREADWEAVER_EXPORT bool Debug;
35 extern THREADWEAVER_EXPORT int DebugLevel;
36 extern THREADWEAVER_EXPORT QMutex GlobalMutex;
37 
38 /** Set the debug log level.
39 @see debug
40 */
41 extern inline void setDebugLevel(bool TWDEBUG, int level);
42 
43 /** This method prints a text message on the screen, if debugging is
44 enabled. Otherwise, it does nothing. The message is thread safe,
45 therefore providing that the messages appear in the order they where
46 issued by the different threads.
47 All messages are suppressed when Debug is false. All messages with a
48 lower importance (higher number) than DebugLevel will be suppressed,
49 too. Debug level 0 messages will always be printed as long as
50 Debug is true.
51  We use our own debugging method, since debugging threads is a more
52  complicated experience than debugging single threaded
53  contexts. This might change in future in the way that debug
54  prints its messages to another logging facility provided by
55  the platform.
56 Use setDebugLevel () to integrate adapt debug () to your platform.
57 */
58 inline void TWDEBUG(int severity, const char *cformat, ...)
59 #ifdef __GNUC__
60  __attribute__((format(printf, 2, 3)))
61 #endif
62  ;
63 
64 /** Prints the message to the console if condition is true. */
65 inline void TWDEBUG(bool condition, int severity, const char *cformat, ...)
66 #ifdef __GNUC__
67  __attribute__((format(printf, 3, 4)))
68 #endif
69  ;
70 
71 /** PROTECT executes x with GlobalMutex locked.
72  Mostly used for debugging, as in P_ASSERT. */
73 #ifdef PROTECT
74 #undef PROTECT
75 #endif
76 
77 /* clang-format off */
78 #define PROTECT(x) \
79  do { \
80  QMutexLocker l(&ThreadWeaver::GlobalMutex); \
81  (x); \
82  } while (0)
83 /* clang-format on */
84 
85 /** P_ASSERT ensures that error messages occur in the correct order. */
86 #ifdef P_ASSERT
87 #undef P_ASSERT
88 #endif
89 
90 /* clang-format off */
91 #define P_ASSERT(x) \
92  do { \
93  QMutexLocker l(&ThreadWeaver::GlobalMutex); \
94  Q_ASSERT(x); \
95  } while (0)
96 /* clang-format on */
97 
98 inline void setDebugLevel(bool debug, int level)
99 {
100  Debug = debug;
101  DebugLevel = level;
102 }
103 
104 #ifndef QT_NO_DEBUG
105 
106 #define TWDEBUG(...) ThreadWeaver::threadweaver_debug(__VA_ARGS__)
107 inline void threadweaver_debug(int severity, const char *cformat, ...)
108 {
109  if (Debug == true && (severity <= DebugLevel || severity == 0)) {
110  QString text;
111 
112  va_list ap;
113  va_start(ap, cformat);
114  PROTECT(vprintf(cformat, ap));
115  va_end(ap);
116  }
117 }
118 
119 inline void threadweaver_debug(bool condition, int severity, const char *cformat, ...)
120 {
121  if (condition && Debug == true && (severity <= DebugLevel || severity == 0)) {
122  QString text;
123 
124  va_list ap;
125  va_start(ap, cformat);
126  PROTECT(vprintf(cformat, ap));
127  va_end(ap);
128  }
129 }
130 #else
131 #define TWDEBUG(...)
132 #endif
133 
134 // Macros to ensure that mutexes are locked or unlocked:
135 void THREADWEAVER_EXPORT mutexAssertUnlocked(QMutex *mutex, const char *where);
136 void THREADWEAVER_EXPORT mutexAssertLocked(QMutex *mutex, const char *where);
137 
138 #ifndef QT_NO_DEBUG
139 #define MUTEX_ASSERT_UNLOCKED(x) mutexAssertUnlocked(x, Q_FUNC_INFO)
140 #define MUTEX_ASSERT_LOCKED(x) mutexAssertLocked(x, Q_FUNC_INFO)
141 #else
142 #define MUTEX_ASSERT_UNLOCKED(x)
143 #define MUTEX_ASSERT_LOCKED(x)
144 #endif
145 
146 inline bool invariant()
147 {
148  return true;
149 }
150 
151 #define INVARIANT Q_ASSERT_X(invariant(), __FILE__, "class invariant failed");
152 
153 /* clang-format off */
154 #define REQUIRE(x) \
155  INVARIANT \
156  Q_ASSERT_X(x, Q_FUNC_INFO, "unfulfilled requirement " #x);
157 
158 #define ENSURE(x) \
159  INVARIANT \
160  Q_ASSERT_X(x, Q_FUNC_INFO, "broken guarantee " #x);
161 /* clang-format on */
162 
163 #ifdef QT_NO_DEBUG
164 #define DEBUGONLY(x)
165 #else
166 #define DEBUGONLY(x) x
167 #endif
168 
169 }
170 
171 #endif // DEBUGGINGAIDS_H
QStringView level(QStringView ifopt)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Thu Sep 21 2023 04:10:21 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.