QRecursiveMutexPrivate should not inherit from QMutexPrivate
QMutexPrivate takes more memory than necessary, and also initialize platform specific ressources. Change-Id: I70be1b89b1c21499645785ae47693a6b2514e28b Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
This commit is contained in:
parent
72257f6429
commit
73b682d816
@ -150,11 +150,16 @@ QMutex::QMutex(RecursionMode mode)
|
|||||||
*/
|
*/
|
||||||
QMutex::~QMutex()
|
QMutex::~QMutex()
|
||||||
{
|
{
|
||||||
if (isRecursive())
|
QMutexData *d = d_ptr.load();
|
||||||
delete static_cast<QRecursiveMutexPrivate *>(d_ptr.load());
|
if (quintptr(d) > 0x3 && d->recursive) {
|
||||||
else if (d_ptr.load()) {
|
delete static_cast<QRecursiveMutexPrivate *>(d);
|
||||||
|
} else if (d) {
|
||||||
#ifndef Q_OS_LINUX
|
#ifndef Q_OS_LINUX
|
||||||
if (d_ptr.load()->possiblyUnlocked.load() && tryLock()) { unlock(); return; }
|
if (d != dummyLocked() && static_cast<QMutexPrivate *>(d)->possiblyUnlocked.load()
|
||||||
|
&& tryLock()) {
|
||||||
|
unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
qWarning("QMutex: destroying locked mutex");
|
qWarning("QMutex: destroying locked mutex");
|
||||||
}
|
}
|
||||||
@ -233,7 +238,7 @@ QMutex::~QMutex()
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
bool QBasicMutex::isRecursive() {
|
bool QBasicMutex::isRecursive() {
|
||||||
QMutexPrivate *d = d_ptr.load();
|
QMutexData *d = d_ptr.load();
|
||||||
if (quintptr(d) <= 0x3)
|
if (quintptr(d) <= 0x3)
|
||||||
return false;
|
return false;
|
||||||
return d->recursive;
|
return d->recursive;
|
||||||
@ -342,30 +347,31 @@ bool QBasicMutex::isRecursive() {
|
|||||||
bool QBasicMutex::lockInternal(int timeout)
|
bool QBasicMutex::lockInternal(int timeout)
|
||||||
{
|
{
|
||||||
while (!fastTryLock()) {
|
while (!fastTryLock()) {
|
||||||
QMutexPrivate *d = d_ptr.loadAcquire();
|
QMutexData *copy = d_ptr.loadAcquire();
|
||||||
if (!d) // if d is 0, the mutex is unlocked
|
if (!copy) // if d is 0, the mutex is unlocked
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (d == dummyLocked()) {
|
if (copy == dummyLocked()) {
|
||||||
if (timeout == 0)
|
if (timeout == 0)
|
||||||
return false;
|
return false;
|
||||||
QMutexPrivate *newD = QMutexPrivate::allocate();
|
QMutexPrivate *newD = QMutexPrivate::allocate();
|
||||||
if (!d_ptr.testAndSetOrdered(d, newD)) {
|
if (!d_ptr.testAndSetOrdered(dummyLocked(), newD)) {
|
||||||
//Either the mutex is already unlocked, or another thread already set it.
|
//Either the mutex is already unlocked, or another thread already set it.
|
||||||
newD->deref();
|
newD->deref();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
d = newD;
|
copy = newD;
|
||||||
//the d->refCount is already 1 the deref will occurs when we unlock
|
//the d->refCount is already 1 the deref will occurs when we unlock
|
||||||
} else if (d->recursive) {
|
} else if (copy->recursive) {
|
||||||
return static_cast<QRecursiveMutexPrivate *>(d)->lock(timeout);
|
return static_cast<QRecursiveMutexPrivate *>(copy)->lock(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QMutexPrivate *d = static_cast<QMutexPrivate *>(copy);
|
||||||
if (timeout == 0 && !d->possiblyUnlocked.load())
|
if (timeout == 0 && !d->possiblyUnlocked.load())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!d->ref())
|
if (!d->ref())
|
||||||
continue; //that QMutexPrivate was already released
|
continue; //that QMutexData was already released
|
||||||
|
|
||||||
if (d != d_ptr.loadAcquire()) {
|
if (d != d_ptr.loadAcquire()) {
|
||||||
//Either the mutex is already unlocked, or relocked with another mutex
|
//Either the mutex is already unlocked, or relocked with another mutex
|
||||||
@ -433,15 +439,17 @@ bool QBasicMutex::lockInternal(int timeout)
|
|||||||
*/
|
*/
|
||||||
void QBasicMutex::unlockInternal()
|
void QBasicMutex::unlockInternal()
|
||||||
{
|
{
|
||||||
QMutexPrivate *d = d_ptr.loadAcquire();
|
QMutexData *copy = d_ptr.loadAcquire();
|
||||||
Q_ASSERT(d); //we must be locked
|
Q_ASSERT(copy); //we must be locked
|
||||||
Q_ASSERT(d != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
|
Q_ASSERT(copy != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
|
||||||
|
|
||||||
if (d->recursive) {
|
if (copy->recursive) {
|
||||||
static_cast<QRecursiveMutexPrivate *>(d)->unlock();
|
static_cast<QRecursiveMutexPrivate *>(copy)->unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QMutexPrivate *d = reinterpret_cast<QMutexPrivate *>(copy);
|
||||||
|
|
||||||
if (d->waiters.fetchAndAddRelease(-QMutexPrivate::BigNumber) == 0) {
|
if (d->waiters.fetchAndAddRelease(-QMutexPrivate::BigNumber) == 0) {
|
||||||
//there is no one waiting on this mutex anymore, set the mutex as unlocked (d = 0)
|
//there is no one waiting on this mutex anymore, set the mutex as unlocked (d = 0)
|
||||||
if (d_ptr.testAndSetRelease(d, 0)) {
|
if (d_ptr.testAndSetRelease(d, 0)) {
|
||||||
|
@ -54,7 +54,7 @@ QT_MODULE(Core)
|
|||||||
|
|
||||||
#if !defined(QT_NO_THREAD) && !defined(qdoc)
|
#if !defined(QT_NO_THREAD) && !defined(qdoc)
|
||||||
|
|
||||||
class QMutexPrivate;
|
class QMutexData;
|
||||||
|
|
||||||
class Q_CORE_EXPORT QBasicMutex
|
class Q_CORE_EXPORT QBasicMutex
|
||||||
{
|
{
|
||||||
@ -83,13 +83,13 @@ private:
|
|||||||
bool lockInternal(int timeout = -1);
|
bool lockInternal(int timeout = -1);
|
||||||
void unlockInternal();
|
void unlockInternal();
|
||||||
|
|
||||||
QBasicAtomicPointer<QMutexPrivate> d_ptr;
|
QBasicAtomicPointer<QMutexData> d_ptr;
|
||||||
static inline QMutexPrivate *dummyLocked() {
|
static inline QMutexData *dummyLocked() {
|
||||||
return reinterpret_cast<QMutexPrivate *>(quintptr(1));
|
return reinterpret_cast<QMutexData *>(quintptr(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class QMutex;
|
friend class QMutex;
|
||||||
friend class QMutexPrivate;
|
friend class QMutexData;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Q_CORE_EXPORT QMutex : public QBasicMutex {
|
class Q_CORE_EXPORT QMutex : public QBasicMutex {
|
||||||
|
@ -65,16 +65,11 @@ static inline int _q_futex(void *addr, int op, int val, const struct timespec *t
|
|||||||
return syscall(SYS_futex, int_addr, op, val, timeout, addr2, val2);
|
return syscall(SYS_futex, int_addr, op, val, timeout, addr2, val2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline QMutexPrivate *dummyFutexValue()
|
static inline QMutexData *dummyFutexValue()
|
||||||
{
|
{
|
||||||
return reinterpret_cast<QMutexPrivate *>(quintptr(3));
|
return reinterpret_cast<QMutexData *>(quintptr(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QMutexPrivate::~QMutexPrivate() {}
|
|
||||||
QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
|
|
||||||
: recursive(mode == QMutex::Recursive) {}
|
|
||||||
|
|
||||||
bool QBasicMutex::lockInternal(int timeout)
|
bool QBasicMutex::lockInternal(int timeout)
|
||||||
{
|
{
|
||||||
QElapsedTimer elapsedTimer;
|
QElapsedTimer elapsedTimer;
|
||||||
@ -82,7 +77,7 @@ bool QBasicMutex::lockInternal(int timeout)
|
|||||||
elapsedTimer.start();
|
elapsedTimer.start();
|
||||||
|
|
||||||
while (!fastTryLock()) {
|
while (!fastTryLock()) {
|
||||||
QMutexPrivate *d = d_ptr.load();
|
QMutexData *d = d_ptr.load();
|
||||||
if (!d) // if d is 0, the mutex is unlocked
|
if (!d) // if d is 0, the mutex is unlocked
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -118,7 +113,7 @@ bool QBasicMutex::lockInternal(int timeout)
|
|||||||
|
|
||||||
void QBasicMutex::unlockInternal()
|
void QBasicMutex::unlockInternal()
|
||||||
{
|
{
|
||||||
QMutexPrivate *d = d_ptr.load();
|
QMutexData *d = d_ptr.load();
|
||||||
Q_ASSERT(d); //we must be locked
|
Q_ASSERT(d); //we must be locked
|
||||||
Q_ASSERT(d != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
|
Q_ASSERT(d != dummyLocked()); // testAndSetRelease(dummyLocked(), 0) failed
|
||||||
|
|
||||||
|
@ -53,8 +53,7 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
|
QMutexPrivate::QMutexPrivate()
|
||||||
: recursive(mode == QMutex::Recursive)
|
|
||||||
{
|
{
|
||||||
kern_return_t r = semaphore_create(mach_task_self(), &mach_semaphore, SYNC_POLICY_FIFO, 0);
|
kern_return_t r = semaphore_create(mach_task_self(), &mach_semaphore, SYNC_POLICY_FIFO, 0);
|
||||||
if (r != KERN_SUCCESS)
|
if (r != KERN_SUCCESS)
|
||||||
|
@ -65,15 +65,23 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QMutexPrivate {
|
class QMutexData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool recursive;
|
||||||
|
QMutexData(QMutex::RecursionMode mode = QMutex::NonRecursive)
|
||||||
|
: recursive(mode == QMutex::Recursive) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined(Q_OS_LINUX)
|
||||||
|
class QMutexPrivate : public QMutexData {
|
||||||
public:
|
public:
|
||||||
~QMutexPrivate();
|
~QMutexPrivate();
|
||||||
QMutexPrivate(QMutex::RecursionMode mode = QMutex::NonRecursive);
|
QMutexPrivate();
|
||||||
|
|
||||||
bool wait(int timeout = -1);
|
bool wait(int timeout = -1);
|
||||||
void wakeUp();
|
void wakeUp();
|
||||||
|
|
||||||
#if !defined(Q_OS_LINUX)
|
|
||||||
// Conrol the lifetime of the privates
|
// Conrol the lifetime of the privates
|
||||||
QAtomicInt refCount;
|
QAtomicInt refCount;
|
||||||
int id;
|
int id;
|
||||||
@ -102,15 +110,11 @@ public:
|
|||||||
QAtomicInt possiblyUnlocked; //bool saying that a timed wait timed out
|
QAtomicInt possiblyUnlocked; //bool saying that a timed wait timed out
|
||||||
enum { BigNumber = 0x100000 }; //Must be bigger than the possible number of waiters (number of threads)
|
enum { BigNumber = 0x100000 }; //Must be bigger than the possible number of waiters (number of threads)
|
||||||
void derefWaiters(int value);
|
void derefWaiters(int value);
|
||||||
#endif
|
|
||||||
|
|
||||||
// handle recursive mutex
|
|
||||||
bool recursive;
|
|
||||||
|
|
||||||
//platform specific stuff
|
//platform specific stuff
|
||||||
#if defined(Q_OS_MAC)
|
#if defined(Q_OS_MAC)
|
||||||
semaphore_t mach_semaphore;
|
semaphore_t mach_semaphore;
|
||||||
#elif defined(Q_OS_UNIX) && !defined(Q_OS_LINUX)
|
#elif defined(Q_OS_UNIX)
|
||||||
bool wakeup;
|
bool wakeup;
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
@ -118,12 +122,13 @@ public:
|
|||||||
HANDLE event;
|
HANDLE event;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
#endif //Q_OS_LINUX
|
||||||
|
|
||||||
class QRecursiveMutexPrivate : public QMutexPrivate
|
class QRecursiveMutexPrivate : public QMutexData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QRecursiveMutexPrivate()
|
QRecursiveMutexPrivate()
|
||||||
: QMutexPrivate(QMutex::Recursive), owner(0), count(0) {}
|
: QMutexData(QMutex::Recursive), owner(0), count(0) {}
|
||||||
Qt::HANDLE owner;
|
Qt::HANDLE owner;
|
||||||
uint count;
|
uint count;
|
||||||
QMutex mutex;
|
QMutex mutex;
|
||||||
|
@ -60,8 +60,8 @@ static void report_error(int code, const char *where, const char *what)
|
|||||||
qWarning("%s: %s failure: %s", where, what, qPrintable(qt_error_string(code)));
|
qWarning("%s: %s failure: %s", where, what, qPrintable(qt_error_string(code)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
|
QMutexPrivate::QMutexPrivate()
|
||||||
: recursive(mode == QMutex::Recursive), wakeup(false)
|
: wakeup(false)
|
||||||
{
|
{
|
||||||
report_error(pthread_mutex_init(&mutex, NULL), "QMutex", "mutex init");
|
report_error(pthread_mutex_init(&mutex, NULL), "QMutex", "mutex init");
|
||||||
report_error(pthread_cond_init(&cond, NULL), "QMutex", "cv init");
|
report_error(pthread_cond_init(&cond, NULL), "QMutex", "cv init");
|
||||||
|
@ -47,12 +47,11 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode)
|
QMutexPrivate::QMutexPrivate()
|
||||||
: recursive(mode)
|
|
||||||
{
|
{
|
||||||
event = CreateEvent(0, FALSE, FALSE, 0);
|
event = CreateEvent(0, FALSE, FALSE, 0);
|
||||||
if (!event)
|
if (!event)
|
||||||
qWarning("QMutexPrivate::QMutexPrivate: Cannot create event");
|
qWarning("QMutexData::QMutexData: Cannot create event");
|
||||||
}
|
}
|
||||||
|
|
||||||
QMutexPrivate::~QMutexPrivate()
|
QMutexPrivate::~QMutexPrivate()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user