ThreadWeaver 5.109.0
debuggingaids.h
1/* -*- C++ -*-
2 This file declares debugging aids for multithreaded applications.
3
4 SPDX-FileCopyrightText: 2004-2013 Mirko Boehm <mirko@kde.org>
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
18extern "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
32namespace ThreadWeaver
33{
34extern THREADWEAVER_EXPORT bool Debug;
35extern THREADWEAVER_EXPORT int DebugLevel;
36extern THREADWEAVER_EXPORT QMutex GlobalMutex;
37
41extern inline void setDebugLevel(bool TWDEBUG, int level);
42
58inline void TWDEBUG(int severity, const char *cformat, ...)
59#ifdef __GNUC__
60 __attribute__((format(printf, 2, 3)))
61#endif
62 ;
63
65inline void TWDEBUG(bool condition, int severity, const char *cformat, ...)
66#ifdef __GNUC__
67 __attribute__((format(printf, 3, 4)))
68#endif
69 ;
70
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
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
98inline 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__)
107inline 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
119inline 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:
135void THREADWEAVER_EXPORT mutexAssertUnlocked(QMutex *mutex, const char *where);
136void 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
146inline 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