source: trunk/src/corelib/kernel/qabstracteventdispatcher.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 16.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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
49QT_BEGIN_NAMESPACE
50
51// we allow for 2^24 = 8^8 = 16777216 simultaneously running timers
52enum { NumberOfBuckets = 8, FirstBucketSize = 8 };
53
54static const int BucketSize[NumberOfBuckets] =
55 { 8, 64, 512, 4096, 32768, 262144, 2097152, 16777216 - 2396744 };
56static const int BucketOffset[NumberOfBuckets] =
57 { 0, 8, 72, 584, 4680, 37448, 299592, 2396744 };
58
59static int FirstBucket[FirstBucketSize] = { 1, 2, 3, 4, 5, 6, 7, 8 };
60static 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
70static 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}
76Q_DESTRUCTOR_FUNCTION(timerIdsDestructorFunction)
77
78static QBasicAtomicInt nextFreeTimerId = Q_BASIC_ATOMIC_INITIALIZER(1);
79
80static const int TimerIdMask = 0x00ffffff;
81static const int TimerSerialMask = ~TimerIdMask & ~0x80000000;
82static const int TimerSerialCounter = TimerIdMask + 1;
83
84// avoid the ABA-problem by using 7 of the top 8 bits of the timerId as a serial number
85static inline int prepareNewValueWithSerialNumber(int oldId, int newId)
86{
87 return (newId & TimerIdMask) | ((oldId + TimerSerialCounter) & TimerSerialMask);
88}
89
90static inline int bucketOffset(int timerId)
91{
92 for (int i = 0; i < NumberOfBuckets; ++i) {
93 if (timerId < BucketSize[i])
94 return i;
95 timerId -= BucketSize[i];
96 }
97 qFatal("QAbstractEventDispatcher: INTERNAL ERROR, timer ID %d is too large", timerId);
98 return -1;
99}
100
101static inline int bucketIndex(int bucket, int timerId)
102{
103 return timerId - BucketOffset[bucket];
104}
105
106static inline int *allocateBucket(int bucket)
107{
108 // allocate a new bucket
109 const int size = BucketSize[bucket];
110 const int offset = BucketOffset[bucket];
111 int *b = new int[size];
112 for (int i = 0; i != size; ++i)
113 b[i] = offset + i + 1;
114 return b;
115}
116
117void QAbstractEventDispatcherPrivate::init()
118{
119 Q_Q(QAbstractEventDispatcher);
120 if (threadData->eventDispatcher != 0) {
121 qWarning("QAbstractEventDispatcher: An event dispatcher has already been created for this thread");
122 } else {
123 threadData->eventDispatcher = q;
124 }
125}
126
127// Timer IDs are implemented using a free-list;
128// there's a vector initialized with:
129// X[i] = i + 1
130// and nextFreeTimerId starts with 1.
131//
132// Allocating a timer ID involves taking the ID from
133// X[nextFreeTimerId]
134// updating nextFreeTimerId to this value and returning the old value
135//
136// When the timer ID is allocated, its cell in the vector is unused (it's a
137// free list). As an added protection, we use the cell to store an invalid
138// (negative) value that we can later check for integrity.
139//
140// (continues below).
141int QAbstractEventDispatcherPrivate::allocateTimerId()
142{
143 int timerId, newTimerId;
144 int at, *b;
145 do {
146 timerId = nextFreeTimerId; //.loadAcquire(); // ### FIXME Proper memory ordering semantics
147
148 // which bucket are we looking in?
149 int which = timerId & TimerIdMask;
150 int bucket = bucketOffset(which);
151 at = bucketIndex(bucket, which);
152 b = timerIds[bucket];
153
154 if (!b) {
155 // allocate a new bucket
156 b = allocateBucket(bucket);
157 if (!timerIds[bucket].testAndSetRelease(0, b)) {
158 // another thread won the race to allocate the bucket
159 delete [] b;
160 b = timerIds[bucket];
161 }
162 }
163
164 newTimerId = prepareNewValueWithSerialNumber(timerId, b[at]);
165 } while (!nextFreeTimerId.testAndSetRelaxed(timerId, newTimerId));
166
167 b[at] = -timerId;
168
169 return timerId;
170}
171
172// Releasing a timer ID requires putting the current ID back in the vector;
173// we do it by setting:
174// X[timerId] = nextFreeTimerId;
175// then we update nextFreeTimerId to the timer we've just released
176//
177// The extra code in allocateTimerId and releaseTimerId are ABA prevention
178// and bucket memory. The buckets are simply to make sure we allocate only
179// the necessary number of timers. See above.
180//
181// ABA prevention simply adds a value to 7 of the top 8 bits when resetting
182// nextFreeTimerId.
183void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId)
184{
185 int which = timerId & TimerIdMask;
186 int bucket = bucketOffset(which);
187 int at = bucketIndex(bucket, which);
188 int *b = timerIds[bucket];
189
190 Q_ASSERT(b[at] == -timerId);
191
192 int freeId, newTimerId;
193 do {
194 freeId = nextFreeTimerId;//.loadAcquire(); // ### FIXME Proper memory ordering semantics
195 b[at] = freeId & TimerIdMask;
196
197 newTimerId = prepareNewValueWithSerialNumber(freeId, timerId);
198 } while (!nextFreeTimerId.testAndSetRelease(freeId, newTimerId));
199}
200
201/*!
202 \class QAbstractEventDispatcher
203 \brief The QAbstractEventDispatcher class provides an interface to manage Qt's event queue.
204
205 \ingroup events
206
207 An event dispatcher receives events from the window system and other
208 sources. It then sends them to the QCoreApplication or QApplication
209 instance for processing and delivery. QAbstractEventDispatcher provides
210 fine-grained control over event delivery.
211
212 For simple control of event processing use
213 QCoreApplication::processEvents().
214
215 For finer control of the application's event loop, call
216 instance() and call functions on the QAbstractEventDispatcher
217 object that is returned. If you want to use your own instance of
218 QAbstractEventDispatcher or of a QAbstractEventDispatcher
219 subclass, you must create your instance \e before you create the
220 QApplication object.
221
222 The main event loop is started by calling
223 QCoreApplication::exec(), and stopped by calling
224 QCoreApplication::exit(). Local event loops can be created using
225 QEventLoop.
226
227 Programs that perform long operations can call processEvents()
228 with a bitwise OR combination of various QEventLoop::ProcessEventsFlag
229 values to control which events should be delivered.
230
231 QAbstractEventDispatcher also allows the integration of an
232 external event loop with the Qt event loop. For example, the
233 \l{Qt Solutions}{Motif Extension Qt Solution} includes a
234 reimplementation of QAbstractEventDispatcher that merges Qt and
235 Motif events together.
236
237 \sa QEventLoop, QCoreApplication
238*/
239
240/*!
241 Constructs a new event dispatcher with the given \a parent.
242*/
243QAbstractEventDispatcher::QAbstractEventDispatcher(QObject *parent)
244 : QObject(*new QAbstractEventDispatcherPrivate, parent)
245{
246 Q_D(QAbstractEventDispatcher);
247 d->init();
248}
249
250/*!
251 \internal
252*/
253QAbstractEventDispatcher::QAbstractEventDispatcher(QAbstractEventDispatcherPrivate &dd,
254 QObject *parent)
255 : QObject(dd, parent)
256{
257 Q_D(QAbstractEventDispatcher);
258 d->init();
259}
260
261/*!
262 Destroys the event dispatcher.
263*/
264QAbstractEventDispatcher::~QAbstractEventDispatcher()
265{ }
266
267/*!
268 Returns a pointer to the event dispatcher object for the specified
269 \a thread. If \a thread is zero, the current thread is used. If no
270 event dispatcher exists for the specified thread, this function
271 returns 0.
272
273 \bold{Note:} If Qt is built without thread support, the \a thread
274 argument is ignored.
275 */
276QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
277{
278 QThreadData *data = thread ? QThreadData::get2(thread) : QThreadData::current();
279 return data->eventDispatcher;
280}
281
282/*!
283 \fn bool QAbstractEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
284
285 Processes pending events that match \a flags until there are no
286 more events to process. Returns true if an event was processed;
287 otherwise returns false.
288
289 This function is especially useful if you have a long running
290 operation and want to show its progress without allowing user
291 input; i.e. by using the QEventLoop::ExcludeUserInputEvents flag.
292
293 If the QEventLoop::WaitForMoreEvents flag is set in \a flags, the
294 behavior of this function is as follows:
295
296 \list
297
298 \i If events are available, this function returns after processing
299 them.
300
301 \i If no events are available, this function will wait until more
302 are available and return after processing newly available events.
303
304 \endlist
305
306 If the QEventLoop::WaitForMoreEvents flag is not set in \a flags,
307 and no events are available, this function will return
308 immediately.
309
310 \bold{Note:} This function does not process events continuously; it
311 returns after all available events are processed.
312
313 \sa hasPendingEvents()
314*/
315
316/*! \fn bool QAbstractEventDispatcher::hasPendingEvents()
317
318 Returns true if there is an event waiting; otherwise returns
319 false.
320*/
321
322/*!
323 \fn void QAbstractEventDispatcher::registerSocketNotifier(QSocketNotifier *notifier)
324
325 Registers \a notifier with the event loop. Subclasses must
326 implement this method to tie a socket notifier into another
327 event loop.
328*/
329
330/*! \fn void QAbstractEventDispatcher::unregisterSocketNotifier(QSocketNotifier *notifier)
331
332 Unregisters \a notifier from the event dispatcher. Subclasses must
333 reimplement this method to tie a socket notifier into another
334 event loop. Reimplementations must call the base
335 implementation.
336*/
337
338/*!
339 \fn int QAbstractEventDispatcher::registerTimer(int interval, QObject *object)
340
341 Registers a timer with the specified \a interval for the given \a object.
342*/
343int QAbstractEventDispatcher::registerTimer(int interval, QObject *object)
344{
345 int id = QAbstractEventDispatcherPrivate::allocateTimerId();
346 registerTimer(id, interval, object);
347 return id;
348}
349
350/*!
351 \fn void QAbstractEventDispatcher::registerTimer(int timerId, int interval, QObject *object)
352
353 Register a timer with the specified \a timerId and \a interval for
354 the given \a object.
355*/
356
357/*!
358 \fn bool QAbstractEventDispatcher::unregisterTimer(int timerId)
359
360 Unregisters the timer with the given \a timerId.
361 Returns true if successful; otherwise returns false.
362
363 \sa registerTimer(), unregisterTimers()
364*/
365
366/*!
367 \fn bool QAbstractEventDispatcher::unregisterTimers(QObject *object)
368
369 Unregisters all the timers associated with the given \a object.
370 Returns true if all timers were successful removed; otherwise returns false.
371
372 \sa unregisterTimer(), registeredTimers()
373*/
374
375/*!
376 \fn QList<TimerInfo> QAbstractEventDispatcher::registeredTimers(QObject *object) const
377
378 Returns a list of registered timers for \a object. The timer ID
379 is the first member in each pair; the interval is the second.
380*/
381
382/*! \fn void QAbstractEventDispatcher::wakeUp()
383 \threadsafe
384
385 Wakes up the event loop.
386
387 \sa awake()
388*/
389
390/*!
391 \fn void QAbstractEventDispatcher::interrupt()
392
393 Interrupts event dispatching; i.e. the event dispatcher will
394 return from processEvents() as soon as possible.
395*/
396
397/*! \fn void QAbstractEventDispatcher::flush()
398
399 Flushes the event queue. This normally returns almost
400 immediately. Does nothing on platforms other than X11.
401*/
402
403// ### DOC: Are these called when the _application_ starts/stops or just
404// when the current _event loop_ starts/stops?
405/*! \internal */
406void QAbstractEventDispatcher::startingUp()
407{ }
408
409/*! \internal */
410void QAbstractEventDispatcher::closingDown()
411{ }
412
413/*!
414 \typedef QAbstractEventDispatcher::TimerInfo
415
416 Typedef for QPair<int, int>. The first component of
417 the pair is the timer ID; the second component is
418 the interval.
419
420 \sa registeredTimers()
421*/
422
423/*!
424 \typedef QAbstractEventDispatcher::EventFilter
425
426 Typedef for a function with the signature
427
428 \snippet doc/src/snippets/code/src_corelib_kernel_qabstracteventdispatcher.cpp 0
429
430 Note that the type of the \a message is platform dependent. The
431 following table shows the \a {message}'s type on Windows, Mac, and
432 X11. You can do a static cast to these types.
433
434 \table
435 \header
436 \o Platform
437 \o type
438 \row
439 \o Windows
440 \o MSG
441 \row
442 \o X11
443 \o XEvent
444 \row
445 \o Mac
446 \o NSEvent
447 \endtable
448
449
450
451 \sa setEventFilter(), filterEvent()
452*/
453
454/*!
455 Replaces the event filter function for this
456 QAbstractEventDispatcher with \a filter and returns the replaced
457 event filter function. Only the current event filter function is
458 called. If you want to use both filter functions, save the
459 replaced EventFilter in a place where yours can call it.
460
461 The event filter function set here is called for all messages
462 taken from the system event loop before the event is dispatched to
463 the respective target, including the messages not meant for Qt
464 objects.
465
466 The event filter function should return true if the message should
467 be filtered, (i.e. stopped). It should return false to allow
468 processing the message to continue.
469
470 By default, no event filter function is set (i.e., this function
471 returns a null EventFilter the first time it is called).
472*/
473QAbstractEventDispatcher::EventFilter QAbstractEventDispatcher::setEventFilter(EventFilter filter)
474{
475 Q_D(QAbstractEventDispatcher);
476 EventFilter oldFilter = d->event_filter;
477 d->event_filter = filter;
478 return oldFilter;
479}
480
481/*!
482 Sends \a message through the event filter that was set by
483 setEventFilter(). If no event filter has been set, this function
484 returns false; otherwise, this function returns the result of the
485 event filter function.
486
487 Subclasses of QAbstractEventDispatcher \e must call this function
488 for \e all messages received from the system to ensure
489 compatibility with any extensions that may be used in the
490 application.
491
492 Note that the type of \a message is platform dependent. See
493 QAbstractEventDispatcher::EventFilter for details.
494
495 \sa setEventFilter()
496*/
497bool QAbstractEventDispatcher::filterEvent(void *message)
498{
499 Q_D(QAbstractEventDispatcher);
500 if (d->event_filter)
501 return d->event_filter(message);
502 return false;
503}
504
505/*! \fn void QAbstractEventDispatcher::awake()
506
507 This signal is emitted after the event loop returns from a
508 function that could block.
509
510 \sa wakeUp() aboutToBlock()
511*/
512
513/*! \fn void QAbstractEventDispatcher::aboutToBlock()
514
515 This signal is emitted before the event loop calls a function that
516 could block.
517
518 \sa awake()
519*/
520
521QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.