src/corelib/kernel/qabstracteventdispatcher.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtCore module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qabstracteventdispatcher.h"
       
    43 #include "qabstracteventdispatcher_p.h"
       
    44 
       
    45 #include "qthread.h"
       
    46 #include <private/qthread_p.h>
       
    47 #include <private/qcoreapplication_p.h>
       
    48 
       
    49 QT_BEGIN_NAMESPACE
       
    50 
       
    51 // we allow for 2^24 = 8^8 = 16777216 simultaneously running timers
       
    52 enum { NumberOfBuckets = 8, FirstBucketSize = 8 };
       
    53 
       
    54 static const int BucketSize[NumberOfBuckets] =
       
    55     { 8, 64, 512, 4096, 32768, 262144, 2097152, 16777216 - 2396744 };
       
    56 static const int BucketOffset[NumberOfBuckets] =
       
    57     { 0,  8,  72,  584,  4680,  37448,  299592,  2396744 };
       
    58 
       
    59 static int FirstBucket[FirstBucketSize] = { 1, 2, 3, 4, 5, 6, 7, 8 };
       
    60 static QBasicAtomicPointer<int> timerIds[NumberOfBuckets] =
       
    61     { Q_BASIC_ATOMIC_INITIALIZER(FirstBucket),
       
    62       Q_BASIC_ATOMIC_INITIALIZER(0),
       
    63       Q_BASIC_ATOMIC_INITIALIZER(0),
       
    64       Q_BASIC_ATOMIC_INITIALIZER(0),
       
    65       Q_BASIC_ATOMIC_INITIALIZER(0),
       
    66       Q_BASIC_ATOMIC_INITIALIZER(0),
       
    67       Q_BASIC_ATOMIC_INITIALIZER(0),
       
    68       Q_BASIC_ATOMIC_INITIALIZER(0) };
       
    69 
       
    70 static void timerIdsDestructorFunction()
       
    71 {
       
    72     // start at one, the first bucket is pre-allocated
       
    73     for (int i = 1; i < NumberOfBuckets; ++i)
       
    74         delete [] static_cast<int *>(timerIds[i]);
       
    75 }
       
    76 Q_DESTRUCTOR_FUNCTION(timerIdsDestructorFunction)
       
    77 
       
    78 static QBasicAtomicInt nextFreeTimerId = Q_BASIC_ATOMIC_INITIALIZER(1);
       
    79 
       
    80 // avoid the ABA-problem by using 7 of the top 8 bits of the timerId as a serial number
       
    81 static inline int prepareNewValueWithSerialNumber(int oldId, int newId)
       
    82 {
       
    83     return (newId & 0x00FFFFFF) | ((oldId + 0x01000000) & 0x7f000000);
       
    84 }
       
    85 
       
    86 static inline int bucketOffset(int timerId)
       
    87 {
       
    88     for (int i = 0; i < NumberOfBuckets; ++i) {
       
    89         if (timerId < BucketSize[i])
       
    90             return i;
       
    91         timerId -= BucketSize[i];
       
    92     }
       
    93     qFatal("QAbstractEventDispatcher: INTERNAL ERROR, timer ID %d is too large", timerId);
       
    94     return -1;
       
    95 }
       
    96 
       
    97 static inline int bucketIndex(int bucket, int timerId)
       
    98 {
       
    99     return timerId - BucketOffset[bucket];
       
   100 }
       
   101 
       
   102 static inline int *allocateBucket(int bucket)
       
   103 {
       
   104     // allocate a new bucket
       
   105     const int size = BucketSize[bucket];
       
   106     const int offset = BucketOffset[bucket];
       
   107     int *b = new int[size];
       
   108     for (int i = 0; i != size; ++i)
       
   109         b[i] = offset + i + 1;
       
   110     return b;
       
   111 }
       
   112 
       
   113 void QAbstractEventDispatcherPrivate::init()
       
   114 {
       
   115     Q_Q(QAbstractEventDispatcher);
       
   116     if (threadData->eventDispatcher != 0) {
       
   117         qWarning("QAbstractEventDispatcher: An event dispatcher has already been created for this thread");
       
   118     } else {
       
   119         threadData->eventDispatcher = q;
       
   120     }
       
   121 }
       
   122 
       
   123 int QAbstractEventDispatcherPrivate::allocateTimerId()
       
   124 {
       
   125     int timerId, newTimerId;
       
   126     do {
       
   127         timerId = nextFreeTimerId;
       
   128 
       
   129         // which bucket are we looking in?
       
   130         int which = timerId & 0x00ffffff;
       
   131         int bucket = bucketOffset(which);
       
   132         int at = bucketIndex(bucket, which);
       
   133         int *b = timerIds[bucket];
       
   134 
       
   135         if (!b) {
       
   136             // allocate a new bucket
       
   137             b = allocateBucket(bucket);
       
   138             if (!timerIds[bucket].testAndSetRelease(0, b)) {
       
   139                 // another thread won the race to allocate the bucket
       
   140                 delete [] b;
       
   141                 b = timerIds[bucket];
       
   142             }
       
   143         }
       
   144 
       
   145         newTimerId = b[at];
       
   146     } while (!nextFreeTimerId.testAndSetRelaxed(timerId, newTimerId));
       
   147 
       
   148     return timerId;
       
   149 }
       
   150 
       
   151 void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId)
       
   152 {
       
   153     int which = timerId & 0x00ffffff;
       
   154     int bucket = bucketOffset(which);
       
   155     int at = bucketIndex(bucket, which);
       
   156     int *b = timerIds[bucket];
       
   157 
       
   158     int freeId, newTimerId;
       
   159     do {
       
   160         freeId = nextFreeTimerId;
       
   161         b[at] = freeId & 0x00ffffff;
       
   162 
       
   163         newTimerId = prepareNewValueWithSerialNumber(freeId, timerId);
       
   164     } while (!nextFreeTimerId.testAndSetRelease(freeId, newTimerId));
       
   165 }
       
   166 
       
   167 /*!
       
   168     \class QAbstractEventDispatcher
       
   169     \brief The QAbstractEventDispatcher class provides an interface to manage Qt's event queue.
       
   170 
       
   171     \ingroup events
       
   172 
       
   173     An event dispatcher receives events from the window system and other
       
   174     sources. It then sends them to the QCoreApplication or QApplication
       
   175     instance for processing and delivery. QAbstractEventDispatcher provides
       
   176     fine-grained control over event delivery.
       
   177 
       
   178     For simple control of event processing use
       
   179     QCoreApplication::processEvents().
       
   180 
       
   181     For finer control of the application's event loop, call
       
   182     instance() and call functions on the QAbstractEventDispatcher
       
   183     object that is returned. If you want to use your own instance of
       
   184     QAbstractEventDispatcher or of a QAbstractEventDispatcher
       
   185     subclass, you must create your instance \e before you create the
       
   186     QApplication object.
       
   187 
       
   188     The main event loop is started by calling
       
   189     QCoreApplication::exec(), and stopped by calling
       
   190     QCoreApplication::exit(). Local event loops can be created using
       
   191     QEventLoop.
       
   192 
       
   193     Programs that perform long operations can call processEvents()
       
   194     with a bitwise OR combination of various QEventLoop::ProcessEventsFlag
       
   195     values to control which events should be delivered.
       
   196 
       
   197     QAbstractEventDispatcher also allows the integration of an
       
   198     external event loop with the Qt event loop. For example, the
       
   199     \l{Qt Solutions}{Motif Extension Qt Solution} includes a
       
   200     reimplementation of QAbstractEventDispatcher that merges Qt and
       
   201     Motif events together.
       
   202 
       
   203     \sa QEventLoop, QCoreApplication
       
   204 */
       
   205 
       
   206 /*!
       
   207     Constructs a new event dispatcher with the given \a parent.
       
   208 */
       
   209 QAbstractEventDispatcher::QAbstractEventDispatcher(QObject *parent)
       
   210     : QObject(*new QAbstractEventDispatcherPrivate, parent)
       
   211 {
       
   212     Q_D(QAbstractEventDispatcher);
       
   213     d->init();
       
   214 }
       
   215 
       
   216 /*!
       
   217     \internal
       
   218 */
       
   219 QAbstractEventDispatcher::QAbstractEventDispatcher(QAbstractEventDispatcherPrivate &dd,
       
   220                                                    QObject *parent)
       
   221     : QObject(dd, parent)
       
   222 {
       
   223     Q_D(QAbstractEventDispatcher);
       
   224     d->init();
       
   225 }
       
   226 
       
   227 /*!
       
   228     Destroys the event dispatcher.
       
   229 */
       
   230 QAbstractEventDispatcher::~QAbstractEventDispatcher()
       
   231 { }
       
   232 
       
   233 /*!
       
   234     Returns a pointer to the event dispatcher object for the specified
       
   235     \a thread. If \a thread is zero, the current thread is used. If no
       
   236     event dispatcher exists for the specified thread, this function
       
   237     returns 0.
       
   238 
       
   239     \bold{Note:} If Qt is built without thread support, the \a thread
       
   240     argument is ignored.
       
   241  */
       
   242 QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
       
   243 {
       
   244     QThreadData *data = thread ? QThreadData::get2(thread) : QThreadData::current();
       
   245     return data->eventDispatcher;
       
   246 }
       
   247 
       
   248 /*!
       
   249     \fn bool QAbstractEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
       
   250 
       
   251     Processes pending events that match \a flags until there are no
       
   252     more events to process. Returns true if an event was processed;
       
   253     otherwise returns false.
       
   254 
       
   255     This function is especially useful if you have a long running
       
   256     operation and want to show its progress without allowing user
       
   257     input; i.e. by using the QEventLoop::ExcludeUserInputEvents flag.
       
   258 
       
   259     If the QEventLoop::WaitForMoreEvents flag is set in \a flags, the
       
   260     behavior of this function is as follows:
       
   261 
       
   262     \list
       
   263 
       
   264     \i If events are available, this function returns after processing
       
   265     them.
       
   266 
       
   267     \i If no events are available, this function will wait until more
       
   268     are available and return after processing newly available events.
       
   269 
       
   270     \endlist
       
   271 
       
   272     If the QEventLoop::WaitForMoreEvents flag is not set in \a flags,
       
   273     and no events are available, this function will return
       
   274     immediately.
       
   275 
       
   276     \bold{Note:} This function does not process events continuously; it
       
   277     returns after all available events are processed.
       
   278 
       
   279     \sa hasPendingEvents()
       
   280 */
       
   281 
       
   282 /*! \fn bool QAbstractEventDispatcher::hasPendingEvents()
       
   283 
       
   284     Returns true if there is an event waiting; otherwise returns
       
   285     false.
       
   286 */
       
   287 
       
   288 /*!
       
   289     \fn void QAbstractEventDispatcher::registerSocketNotifier(QSocketNotifier *notifier)
       
   290 
       
   291     Registers \a notifier with the event loop. Subclasses must
       
   292     implement this method to tie a socket notifier into another
       
   293     event loop.
       
   294 */
       
   295 
       
   296 /*! \fn void QAbstractEventDispatcher::unregisterSocketNotifier(QSocketNotifier *notifier)
       
   297 
       
   298     Unregisters \a notifier from the event dispatcher. Subclasses must
       
   299     reimplement this method to tie a socket notifier into another
       
   300     event loop. Reimplementations must call the base
       
   301     implementation.
       
   302 */
       
   303 
       
   304 /*!
       
   305     \fn int QAbstractEventDispatcher::registerTimer(int interval, QObject *object)
       
   306 
       
   307     Registers a timer with the specified \a interval for the given \a object.
       
   308 */
       
   309 int QAbstractEventDispatcher::registerTimer(int interval, QObject *object)
       
   310 {
       
   311     int id = QAbstractEventDispatcherPrivate::allocateTimerId();
       
   312     registerTimer(id, interval, object);
       
   313     return id;
       
   314 }
       
   315 
       
   316 /*!
       
   317     \fn void QAbstractEventDispatcher::registerTimer(int timerId, int interval, QObject *object)
       
   318 
       
   319     Register a timer with the specified \a timerId and \a interval for
       
   320     the given \a object.
       
   321 */
       
   322 
       
   323 /*!
       
   324     \fn bool QAbstractEventDispatcher::unregisterTimer(int timerId)
       
   325 
       
   326     Unregisters the timer with the given \a timerId.
       
   327     Returns true if successful; otherwise returns false.
       
   328 
       
   329     \sa registerTimer(), unregisterTimers()
       
   330 */
       
   331 
       
   332 /*!
       
   333     \fn bool QAbstractEventDispatcher::unregisterTimers(QObject *object)
       
   334 
       
   335     Unregisters all the timers associated with the given \a object.
       
   336     Returns true if all timers were successful removed; otherwise returns false.
       
   337 
       
   338     \sa unregisterTimer(), registeredTimers()
       
   339 */
       
   340 
       
   341 /*!
       
   342     \fn QList<TimerInfo> QAbstractEventDispatcher::registeredTimers(QObject *object) const
       
   343 
       
   344     Returns a list of registered timers for \a object. The timer ID
       
   345     is the first member in each pair; the interval is the second.
       
   346 */
       
   347 
       
   348 /*! \fn void QAbstractEventDispatcher::wakeUp()
       
   349     \threadsafe
       
   350 
       
   351     Wakes up the event loop.
       
   352 
       
   353     \sa awake()
       
   354 */
       
   355 
       
   356 /*!
       
   357     \fn void QAbstractEventDispatcher::interrupt()
       
   358 
       
   359     Interrupts event dispatching; i.e. the event dispatcher will
       
   360     return from processEvents() as soon as possible.
       
   361 */
       
   362 
       
   363 /*! \fn void QAbstractEventDispatcher::flush()
       
   364 
       
   365     Flushes the event queue. This normally returns almost
       
   366     immediately. Does nothing on platforms other than X11.
       
   367 */
       
   368 
       
   369 // ### DOC: Are these called when the _application_ starts/stops or just
       
   370 // when the current _event loop_ starts/stops?
       
   371 /*! \internal */
       
   372 void QAbstractEventDispatcher::startingUp()
       
   373 { }
       
   374 
       
   375 /*! \internal */
       
   376 void QAbstractEventDispatcher::closingDown()
       
   377 { }
       
   378 
       
   379 /*!
       
   380     \typedef QAbstractEventDispatcher::TimerInfo
       
   381 
       
   382     Typedef for QPair<int, int>. The first component of
       
   383     the pair is the timer ID; the second component is
       
   384     the interval.
       
   385 
       
   386     \sa registeredTimers()
       
   387 */
       
   388 
       
   389 /*!
       
   390     \typedef QAbstractEventDispatcher::EventFilter
       
   391 
       
   392     Typedef for a function with the signature
       
   393 
       
   394     \snippet doc/src/snippets/code/src_corelib_kernel_qabstracteventdispatcher.cpp 0
       
   395 
       
   396     \sa setEventFilter(), filterEvent()
       
   397 */
       
   398 
       
   399 /*!
       
   400     Replaces the event filter function for this
       
   401     QAbstractEventDispatcher with \a filter and returns the replaced
       
   402     event filter function. Only the current event filter function is
       
   403     called. If you want to use both filter functions, save the
       
   404     replaced EventFilter in a place where yours can call it.
       
   405 
       
   406     The event filter function set here is called for all messages
       
   407     taken from the system event loop before the event is dispatched to
       
   408     the respective target, including the messages not meant for Qt
       
   409     objects.
       
   410 
       
   411     The event filter function should return true if the message should
       
   412     be filtered, (i.e. stopped). It should return false to allow
       
   413     processing the message to continue.
       
   414 
       
   415     By default, no event filter function is set (i.e., this function
       
   416     returns a null EventFilter the first time it is called).
       
   417 */
       
   418 QAbstractEventDispatcher::EventFilter QAbstractEventDispatcher::setEventFilter(EventFilter filter)
       
   419 {
       
   420     Q_D(QAbstractEventDispatcher);
       
   421     EventFilter oldFilter = d->event_filter;
       
   422     d->event_filter = filter;
       
   423     return oldFilter;
       
   424 }
       
   425 
       
   426 /*!
       
   427     Sends \a message through the event filter that was set by
       
   428     setEventFilter().  If no event filter has been set, this function
       
   429     returns false; otherwise, this function returns the result of the
       
   430     event filter function.
       
   431 
       
   432     Subclasses of QAbstractEventDispatcher \e must call this function
       
   433     for \e all messages received from the system to ensure
       
   434     compatibility with any extensions that may be used in the
       
   435     application.
       
   436 
       
   437     \sa setEventFilter()
       
   438 */
       
   439 bool QAbstractEventDispatcher::filterEvent(void *message)
       
   440 {
       
   441     Q_D(QAbstractEventDispatcher);
       
   442     if (d->event_filter)
       
   443         return d->event_filter(message);
       
   444     return false;
       
   445 }
       
   446 
       
   447 /*! \fn void QAbstractEventDispatcher::awake()
       
   448 
       
   449     This signal is emitted after the event loop returns from a
       
   450     function that could block.
       
   451 
       
   452     \sa wakeUp() aboutToBlock()
       
   453 */
       
   454 
       
   455 /*! \fn void QAbstractEventDispatcher::aboutToBlock()
       
   456 
       
   457     This signal is emitted before the event loop calls a function that
       
   458     could block.
       
   459 
       
   460     \sa awake()
       
   461 */
       
   462 
       
   463 QT_END_NAMESPACE