1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Copyright (C) 2016 Intel Corporation.
5** Copyright (C) 2012 Olivier Goffart <ogoffart@woboq.com>
6** Contact: https://www.qt.io/licensing/
7**
8** This file is part of the QtCore module of the Qt Toolkit.
9**
10** $QT_BEGIN_LICENSE:LGPL$
11** Commercial License Usage
12** Licensees holding valid commercial Qt licenses may use this file in
13** accordance with the commercial license agreement provided with the
14** Software or, alternatively, in accordance with the terms contained in
15** a written agreement between you and The Qt Company. For licensing terms
16** and conditions see https://www.qt.io/terms-conditions. For further
17** information use the contact form at https://www.qt.io/contact-us.
18**
19** GNU Lesser General Public License Usage
20** Alternatively, this file may be used under the terms of the GNU Lesser
21** General Public License version 3 as published by the Free Software
22** Foundation and appearing in the file LICENSE.LGPL3 included in the
23** packaging of this file. Please review the following information to
24** ensure the GNU Lesser General Public License version 3 requirements
25** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
26**
27** GNU General Public License Usage
28** Alternatively, this file may be used under the terms of the GNU
29** General Public License version 2.0 or (at your option) the GNU General
30** Public license version 3 or any later version approved by the KDE Free
31** Qt Foundation. The licenses are as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
33** included in the packaging of this file. Please review the following
34** information to ensure the GNU General Public License requirements will
35** be met: https://www.gnu.org/licenses/gpl-2.0.html and
36** https://www.gnu.org/licenses/gpl-3.0.html.
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifndef QMUTEX_P_H
43#define QMUTEX_P_H
44
45//
46// W A R N I N G
47// -------------
48//
49// This file is not part of the Qt API. It exists for the convenience
50// of qmutex.cpp, qmutex_unix.cpp, and qmutex_win.cpp. This header
51// file may change from version to version without notice, or even be
52// removed.
53//
54// We mean it.
55//
56
57#include <QtCore/private/qglobal_p.h>
58#include <QtCore/qnamespace.h>
59#include <QtCore/qmutex.h>
60#include <QtCore/qatomic.h>
61#include <QtCore/qdeadlinetimer.h>
62
63#if defined(Q_OS_MAC)
64# include <mach/semaphore.h>
65#elif defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
66// use Linux mutexes everywhere except for LSB builds
67# define QT_LINUX_FUTEX
68#elif defined(Q_OS_UNIX)
69# if _POSIX_VERSION-0 >= 200112L || _XOPEN_VERSION-0 >= 600
70# include <semaphore.h>
71# define QT_UNIX_SEMAPHORE
72# endif
73#endif
74
75struct timespec;
76
77QT_BEGIN_NAMESPACE
78
79class QMutexData
80{
81public:
82 bool recursive;
83 QMutexData(QMutex::RecursionMode mode = QMutex::NonRecursive)
84 : recursive(mode == QMutex::Recursive) {}
85};
86
87#if !defined(QT_LINUX_FUTEX)
88class QMutexPrivate : public QMutexData
89{
90public:
91 ~QMutexPrivate();
92 QMutexPrivate();
93
94 bool wait(int timeout = -1);
95 void wakeUp() noexcept;
96
97 // Control the lifetime of the privates
98 QAtomicInt refCount;
99 int id;
100
101 bool ref() {
102 Q_ASSERT(refCount.loadRelaxed() >= 0);
103 int c;
104 do {
105 c = refCount.loadRelaxed();
106 if (c == 0)
107 return false;
108 } while (!refCount.testAndSetRelaxed(c, c + 1));
109 Q_ASSERT(refCount.loadRelaxed() >= 0);
110 return true;
111 }
112 void deref() {
113 Q_ASSERT(refCount.loadRelaxed() >= 0);
114 if (!refCount.deref())
115 release();
116 Q_ASSERT(refCount.loadRelaxed() >= 0);
117 }
118 void release();
119 static QMutexPrivate *allocate();
120
121 QAtomicInt waiters; // Number of threads waiting on this mutex. (may be offset by -BigNumber)
122 QAtomicInt possiblyUnlocked; /* Boolean indicating that a timed wait timed out.
123 When it is true, a reference is held.
124 It is there to avoid a race that happens if unlock happens right
125 when the mutex is unlocked.
126 */
127 enum { BigNumber = 0x100000 }; //Must be bigger than the possible number of waiters (number of threads)
128 void derefWaiters(int value) noexcept;
129
130 //platform specific stuff
131#if defined(Q_OS_MAC)
132 semaphore_t mach_semaphore;
133#elif defined(QT_UNIX_SEMAPHORE)
134 sem_t semaphore;
135#elif defined(Q_OS_UNIX)
136 bool wakeup;
137 pthread_mutex_t mutex;
138 pthread_cond_t cond;
139#elif defined(Q_OS_WIN)
140 Qt::HANDLE event;
141#endif
142};
143#endif //QT_LINUX_FUTEX
144
145
146#ifdef Q_OS_UNIX
147// helper functions for qmutex_unix.cpp and qwaitcondition_unix.cpp
148// they are in qwaitcondition_unix.cpp actually
149void qt_initialize_pthread_cond(pthread_cond_t *cond, const char *where);
150void qt_abstime_for_timeout(struct timespec *ts, QDeadlineTimer deadline);
151#endif
152
153QT_END_NAMESPACE
154
155#endif // QMUTEX_P_H
156

source code of qtbase/src/corelib/thread/qmutex_p.h