Add level method to recursive mutex

Enhance thread safety when making event calls
Minor cleanup of whitespace in glib event loop
pull/2/head
Timothy Pearson 12 years ago
parent 85b3c5d0ec
commit 9bff9eeefc

3
configure vendored

@ -734,6 +734,9 @@ while [ "$#" -gt 0 ]; do
glibmainloop) glibmainloop)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
CFG_GLIBMAINLOOP="$VAL" CFG_GLIBMAINLOOP="$VAL"
if [ "$VAL" = "yes" ]; then
echo "WARNING: glib main loop support is ***incomplete*** and will cause problems with threaded applications and/or those using non-standard event loops!"
fi
else else
UNKNOWN_OPT=yes UNKNOWN_OPT=yes
fi fi

@ -2767,18 +2767,21 @@ bool QApplication::internalNotify( QObject *receiver, QEvent * e)
if (!handled) { if (!handled) {
#if defined(QT_THREAD_SUPPORT) #if defined(QT_THREAD_SUPPORT)
bool locked = false; int locklevel = 0;
int llcount;
if (QApplication::qt_mutex) { if (QApplication::qt_mutex) {
locked = QApplication::qt_mutex->locked(); QApplication::qt_mutex->lock(); // 1 of 2
} locklevel = qt_mutex->level() - 1;
if (locked) { for (llcount=0; llcount<locklevel; llcount++) {
QApplication::qt_mutex->unlock(); QApplication::qt_mutex->unlock();
}
QApplication::qt_mutex->unlock(); // 2 of 2
} }
#endif #endif
consumed = receiver->event( e ); consumed = receiver->event( e );
#if defined(QT_THREAD_SUPPORT) #if defined(QT_THREAD_SUPPORT)
if (locked) { if (QApplication::qt_mutex) {
if (QApplication::qt_mutex) { for (llcount=0; llcount<locklevel; llcount++) {
QApplication::qt_mutex->lock(); QApplication::qt_mutex->lock();
} }
} }

@ -370,9 +370,9 @@ void QEventLoop::registerSocketNotifier( QSocketNotifier *notifier )
return; return;
} }
#ifdef DEBUG_QT_GLIBMAINLOOP #ifdef DEBUG_QT_GLIBMAINLOOP
printf("register socket notifier %d\n", sockfd); printf("register socket notifier %d\n", sockfd);
#endif #endif
QPtrList<QSockNotGPollFD> *list = &d->sn_list; QPtrList<QSockNotGPollFD> *list = &d->sn_list;
QSockNotGPollFD *sn; QSockNotGPollFD *sn;
@ -425,9 +425,9 @@ void QEventLoop::unregisterSocketNotifier( QSocketNotifier *notifier )
return; return;
} }
#ifdef DEBUG_QT_GLIBMAINLOOP #ifdef DEBUG_QT_GLIBMAINLOOP
printf("unregister socket notifier %d\n", sockfd); printf("unregister socket notifier %d\n", sockfd);
#endif #endif
QPtrList<QSockNotGPollFD> *list = &d->sn_list; QPtrList<QSockNotGPollFD> *list = &d->sn_list;
QSockNotGPollFD *sn; QSockNotGPollFD *sn;
@ -458,9 +458,9 @@ void QEventLoop::setSocketNotifierPending( QSocketNotifier *notifier )
return; return;
} }
#ifdef DEBUG_QT_GLIBMAINLOOP #ifdef DEBUG_QT_GLIBMAINLOOP
printf("set socket notifier pending %d\n", sockfd); printf("set socket notifier pending %d\n", sockfd);
#endif #endif
QPtrList<QSockNotGPollFD> *list = &d->sn_list; QPtrList<QSockNotGPollFD> *list = &d->sn_list;
QSockNotGPollFD *sn; QSockNotGPollFD *sn;

@ -54,6 +54,8 @@
#include <glib.h> #include <glib.h>
// #define DEBUG_QT_GLIBMAINLOOP 1
// Qt-GSource Structure and Callbacks // Qt-GSource Structure and Callbacks
typedef struct { typedef struct {
@ -249,7 +251,7 @@ bool QEventLoop::processEvents( ProcessEventsFlags flags )
d->pev_flags = flags; d->pev_flags = flags;
rval = g_main_context_iteration(NULL, flags & WaitForMore ? TRUE : FALSE); rval = g_main_context_iteration(NULL, flags & WaitForMore ? TRUE : FALSE);
d->pev_flags = save_flags; d->pev_flags = save_flags;
@ -288,38 +290,38 @@ bool QEventLoop::processX11Events()
XNextEvent( QPaintDevice::x11AppDisplay(), &event ); XNextEvent( QPaintDevice::x11AppDisplay(), &event );
if ( flags & ExcludeUserInput ) { if ( flags & ExcludeUserInput ) {
switch ( event.type ) { switch ( event.type ) {
case ButtonPress: case ButtonPress:
case ButtonRelease: case ButtonRelease:
case MotionNotify: case MotionNotify:
case XKeyPress: case XKeyPress:
case XKeyRelease: case XKeyRelease:
case EnterNotify: case EnterNotify:
case LeaveNotify: case LeaveNotify:
continue;
case ClientMessage:
{
// from qapplication_x11.cpp
extern Atom qt_wm_protocols;
extern Atom qt_wm_take_focus;
extern Atom qt_qt_scrolldone;
// only keep the wm_take_focus and
// qt_qt_scrolldone protocols, discard all
// other client messages
if ( event.xclient.format != 32 )
continue; continue;
if ( event.xclient.message_type == qt_wm_protocols || case ClientMessage:
(Atom) event.xclient.data.l[0] == qt_wm_take_focus ) {
break; // from qapplication_x11.cpp
if ( event.xclient.message_type == qt_qt_scrolldone ) extern Atom qt_wm_protocols;
break; extern Atom qt_wm_take_focus;
extern Atom qt_qt_scrolldone;
// only keep the wm_take_focus and
// qt_qt_scrolldone protocols, discard all
// other client messages
if ( event.xclient.format != 32 )
continue;
if ( event.xclient.message_type == qt_wm_protocols ||
(Atom) event.xclient.data.l[0] == qt_wm_take_focus )
break;
if ( event.xclient.message_type == qt_qt_scrolldone )
break;
}
default: break;
} }
default: break;
}
} }
nevents++; nevents++;
@ -333,7 +335,7 @@ bool QEventLoop::processX11Events()
if ( d->shortcut ) { if ( d->shortcut ) {
return FALSE; return FALSE;
} }
QApplication::sendPostedEvents(); QApplication::sendPostedEvents();
const uint exclude_all = ExcludeSocketNotifiers | 0x08; const uint exclude_all = ExcludeSocketNotifiers | 0x08;
@ -595,12 +597,16 @@ bool QEventLoop::gsourceDispatch(GSource *gs) {
// color approx. optimization - only on X11 // color approx. optimization - only on X11
qt_reset_color_avail(); qt_reset_color_avail();
#if defined(QT_THREAD_SUPPORT)
locker.mutex()->unlock();
#endif
processX11Events(); processX11Events();
} }
else {
#if defined(QT_THREAD_SUPPORT) #if defined(QT_THREAD_SUPPORT)
locker.mutex()->unlock(); locker.mutex()->unlock();
#endif #endif
}
if (d->singletoolkit) { if (d->singletoolkit) {
return TRUE; // Eat the event return TRUE; // Eat the event

@ -74,6 +74,9 @@ private:
QMutex( const QMutex & ); QMutex( const QMutex & );
QMutex &operator=( const QMutex & ); QMutex &operator=( const QMutex & );
#endif #endif
public:
int level();
}; };
class Q_EXPORT QMutexLocker class Q_EXPORT QMutexLocker

@ -67,6 +67,7 @@ public:
virtual bool locked() = 0; virtual bool locked() = 0;
virtual bool trylock() = 0; virtual bool trylock() = 0;
virtual int type() const = 0; virtual int type() const = 0;
virtual int level() = 0;
}; };

@ -85,6 +85,7 @@ public:
bool locked(); bool locked();
bool trylock(); bool trylock();
int type() const; int type() const;
int level();
bool recursive; bool recursive;
}; };
@ -101,6 +102,7 @@ public:
bool locked(); bool locked();
bool trylock(); bool trylock();
int type() const; int type() const;
int level();
int count; int count;
unsigned long owner; unsigned long owner;
@ -196,6 +198,11 @@ int QRealMutexPrivate::type() const
return recursive ? Q_MUTEX_RECURSIVE : Q_MUTEX_NORMAL; return recursive ? Q_MUTEX_RECURSIVE : Q_MUTEX_NORMAL;
} }
int QRealMutexPrivate::level()
{
return locked();
}
#ifndef Q_RECURSIVE_MUTEX_TYPE #ifndef Q_RECURSIVE_MUTEX_TYPE
QRecursiveMutexPrivate::QRecursiveMutexPrivate() QRecursiveMutexPrivate::QRecursiveMutexPrivate()
@ -329,6 +336,11 @@ int QRecursiveMutexPrivate::type() const
return Q_MUTEX_RECURSIVE; return Q_MUTEX_RECURSIVE;
} }
int QRecursiveMutexPrivate::level()
{
return count;
}
#endif // !Q_RECURSIVE_MUTEX_TYPE #endif // !Q_RECURSIVE_MUTEX_TYPE
@ -510,6 +522,22 @@ bool QMutex::tryLock()
return d->trylock(); return d->trylock();
} }
/*!
Returns the current lock level of the mutex.
0 means the mutex is unlocked
This method should only be called when the mutex has already been locked
by lock(), otherwise the lock level could change before the next line
of code is executed.
WARNING: Non-recursive mutexes will never exceed a lock level of 1!
\sa lock(), unlock(), locked()
*/
int QMutex::level()
{
return d->level();
}
/*! /*!
\class QMutexLocker qmutex.h \class QMutexLocker qmutex.h
\brief The QMutexLocker class simplifies locking and unlocking QMutexes. \brief The QMutexLocker class simplifies locking and unlocking QMutexes.

Loading…
Cancel
Save