1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef QREADWRITELOCK_P_H
6#define QREADWRITELOCK_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists for the convenience
13// of the implementation. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtCore/private/qlocking_p.h>
20#include <QtCore/private/qwaitcondition_p.h>
21#include <QtCore/qreadwritelock.h>
22#include <QtCore/qvarlengtharray.h>
23
24QT_REQUIRE_CONFIG(thread);
25
26QT_BEGIN_NAMESPACE
27
28namespace QReadWriteLockStates {
29enum {
30 StateMask = 0x3,
31 StateLockedForRead = 0x1,
32 StateLockedForWrite = 0x2,
33};
34enum StateForWaitCondition {
35 LockedForRead,
36 LockedForWrite,
37 Unlocked,
38 RecursivelyLocked
39};
40}
41
42class QReadWriteLockPrivate
43{
44public:
45 explicit QReadWriteLockPrivate(bool isRecursive = false)
46 : recursive(isRecursive) {}
47
48 alignas(QtPrivate::IdealMutexAlignment) std::condition_variable writerCond;
49 std::condition_variable readerCond;
50
51 alignas(QtPrivate::IdealMutexAlignment) std::mutex mutex;
52 int readerCount = 0;
53 int writerCount = 0;
54 int waitingReaders = 0;
55 int waitingWriters = 0;
56 const bool recursive;
57
58 //Called with the mutex locked
59 bool lockForWrite(std::unique_lock<std::mutex> &lock, QDeadlineTimer timeout);
60 bool lockForRead(std::unique_lock<std::mutex> &lock, QDeadlineTimer timeout);
61 void unlock();
62
63 //memory management
64 int id = 0;
65 void release();
66 static QReadWriteLockPrivate *allocate();
67
68 // Recursive mutex handling
69 Qt::HANDLE currentWriter = {};
70
71 struct Reader {
72 Qt::HANDLE handle;
73 int recursionLevel;
74 };
75
76 QVarLengthArray<Reader, 16> currentReaders;
77
78 // called with the mutex unlocked
79 bool recursiveLockForWrite(QDeadlineTimer timeout);
80 bool recursiveLockForRead(QDeadlineTimer timeout);
81 void recursiveUnlock();
82
83 static QReadWriteLockStates::StateForWaitCondition
84 stateForWaitCondition(const QReadWriteLock *lock);
85};
86Q_DECLARE_TYPEINFO(QReadWriteLockPrivate::Reader, Q_PRIMITIVE_TYPE);\
87
88/*! \internal Helper for QWaitCondition::wait */
89inline QReadWriteLockStates::StateForWaitCondition
90QReadWriteLockPrivate::stateForWaitCondition(const QReadWriteLock *q)
91{
92 using namespace QReadWriteLockStates;
93 QReadWriteLockPrivate *d = q->d_ptr.loadAcquire();
94 switch (quintptr(d) & StateMask) {
95 case StateLockedForRead: return LockedForRead;
96 case StateLockedForWrite: return LockedForWrite;
97 }
98
99 if (!d)
100 return Unlocked;
101 const auto lock = qt_scoped_lock(mutex&: d->mutex);
102 if (d->writerCount > 1)
103 return RecursivelyLocked;
104 else if (d->writerCount == 1)
105 return LockedForWrite;
106 return LockedForRead;
107
108}
109
110QT_END_NAMESPACE
111
112#endif // QREADWRITELOCK_P_H
113

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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