ThreadWeaver

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
38/** Set the debug log level.
39@see debug
40*/
41extern inline void setDebugLevel(bool TWDEBUG, int level);
42
43/** This method prints a text message on the screen, if debugging is
44enabled. Otherwise, it does nothing. The message is thread safe,
45therefore providing that the messages appear in the order they where
46issued by the different threads.
47All messages are suppressed when Debug is false. All messages with a
48lower importance (higher number) than DebugLevel will be suppressed,
49too. Debug level 0 messages will always be printed as long as
50Debug 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.
56Use setDebugLevel () to integrate adapt debug () to your platform.
57*/
58inline 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. */
65inline 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
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
QStringView level(QStringView ifopt)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sun Feb 25 2024 18:40:09 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.