1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Copyright (C) 2016 Intel Corporation.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtDBus module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 #ifndef QDBUSTHREADDEBUG_P_H
41 #define QDBUSTHREADDEBUG_P_H
42 
43 //
44 //  W A R N I N G
45 //  -------------
46 //
47 // This file is not part of the Qt API.  It exists purely as an
48 // implementation detail.  This header file may change from version to
49 // version without notice, or even be removed.
50 //
51 // We mean it.
52 //
53 
54 #include <QtDBus/private/qtdbusglobal_p.h>
55 
56 #ifndef QT_NO_DBUS
57 
58 #if !defined(QDBUS_THREAD_DEBUG) && defined(QT_BUILD_INTERNAL)
59 # define QDBUS_THREAD_DEBUG 1
60 #endif
61 
62 #if QDBUS_THREAD_DEBUG
63 QT_BEGIN_NAMESPACE
64 typedef void (*qdbusThreadDebugFunc)(int, int, QDBusConnectionPrivate *);
65 Q_DBUS_EXPORT void qdbusDefaultThreadDebug(int, int, QDBusConnectionPrivate *);
66 extern Q_DBUS_EXPORT qdbusThreadDebugFunc qdbusThreadDebug;
67 QT_END_NAMESPACE
68 #endif
69 
70 enum ThreadAction {
71     ConnectAction = 0,
72     DisconnectAction = 1,
73     RegisterObjectAction = 2,
74     UnregisterObjectAction = 3,
75     ObjectRegisteredAtAction = 4,
76 
77     CloseConnectionAction = 10,
78     ObjectDestroyedAction = 11,
79     RelaySignalAction = 12,
80     HandleObjectCallAction = 13,
81     HandleSignalAction = 14,
82     ConnectRelayAction = 15,
83     DisconnectRelayAction = 16,
84     FindMetaObject1Action = 17,
85     FindMetaObject2Action = 18,
86     RegisterServiceAction = 19,
87     UnregisterServiceAction = 20,
88     UpdateSignalHookOwnerAction = 21,
89     HandleObjectCallPostEventAction = 22,
90     HandleObjectCallSemaphoreAction = 23,
91     DoDispatchAction = 24,
92     SetDispatchEnabledAction = 25,
93     MessageResultReceivedAction = 26,
94     ActivateSignalAction = 27,
95     PendingCallBlockAction = 28,
96     SendMessageAction = 29,
97     HuntAndEmitAction = 30,
98 };
99 
100 struct QDBusLockerBase
101 {
102     enum Condition
103     {
104         BeforeLock,
105         AfterLock,
106         BeforeUnlock,
107         AfterUnlock,
108 
109         BeforePost,
110         AfterPost,
111         BeforeDeliver,
112         AfterDeliver,
113 
114         BeforeAcquire,
115         AfterAcquire,
116         BeforeRelease,
117         AfterRelease
118     };
119 
120 #if QDBUS_THREAD_DEBUG
reportThreadActionQDBusLockerBase121     static inline void reportThreadAction(int action, int condition, QDBusConnectionPrivate *ptr)
122     { if (qdbusThreadDebug) qdbusThreadDebug(action, condition, ptr); }
123 #else
reportThreadActionQDBusLockerBase124     static inline void reportThreadAction(int, int, QDBusConnectionPrivate *) { }
125 #endif
126 };
127 
128 struct QDBusReadLocker: QDBusLockerBase
129 {
130     QDBusConnectionPrivate *self;
131     ThreadAction action;
QDBusReadLockerQDBusReadLocker132     inline QDBusReadLocker(ThreadAction a, QDBusConnectionPrivate *s)
133         : self(s), action(a)
134     {
135         reportThreadAction(action, BeforeLock, self);
136         self->lock.lockForRead();
137         reportThreadAction(action, AfterLock, self);
138     }
139 
~QDBusReadLockerQDBusReadLocker140     inline ~QDBusReadLocker()
141     {
142         reportThreadAction(action, BeforeUnlock, self);
143         self->lock.unlock();
144         reportThreadAction(action, AfterUnlock, self);
145     }
146 };
147 
148 struct QDBusWriteLocker: QDBusLockerBase
149 {
150     QDBusConnectionPrivate *self;
151     ThreadAction action;
QDBusWriteLockerQDBusWriteLocker152     inline QDBusWriteLocker(ThreadAction a, QDBusConnectionPrivate *s)
153         : self(s), action(a)
154     {
155         reportThreadAction(action, BeforeLock, self);
156         self->lock.lockForWrite();
157         reportThreadAction(action, AfterLock, self);
158     }
159 
~QDBusWriteLockerQDBusWriteLocker160     inline ~QDBusWriteLocker()
161     {
162         reportThreadAction(action, BeforeUnlock, self);
163         self->lock.unlock();
164         reportThreadAction(action, AfterUnlock, self);
165     }
166 };
167 
168 #if QDBUS_THREAD_DEBUG
169 # define SEM_ACQUIRE(action, sem)                                       \
170     do {                                                                \
171     QDBusLockerBase::reportThreadAction(action, QDBusLockerBase::BeforeAcquire, this); \
172     sem.acquire();                                                      \
173     QDBusLockerBase::reportThreadAction(action, QDBusLockerBase::AfterAcquire, this); \
174     } while (false)
175 
176 # define SEM_RELEASE(action, sem)                                       \
177     do {                                                                \
178     QDBusLockerBase::reportThreadAction(action, QDBusLockerBase::BeforeRelease, that); \
179     sem.release();                                                      \
180     QDBusLockerBase::reportThreadAction(action, QDBusLockerBase::AfterRelease, that); \
181     } while (false)
182 
183 #else
184 # define SEM_ACQUIRE(action, sem)       sem.acquire()
185 # define SEM_RELEASE(action, sem)       sem.release()
186 #endif
187 
188 #endif // QT_NO_DBUS
189 #endif
190