QThreadPool: optimize enqueueTask() for common case
authorKonstantin Ritt <ritt.ks@gmail.com>
Mon, 16 Apr 2012 11:43:27 +0000 (14:43 +0300)
committerQt by Nokia <qt-info@nokia.com>
Tue, 17 Apr 2012 16:44:13 +0000 (18:44 +0200)
the most-common case is: queue is empty or filled with tasks of
the same priority; so the runnable would be put at the end of queue.
both checks are cheap for us.

also avoid detach()'ing by using const iterators

Change-Id: Iab2255f852211f9accc8d717f778671661210ef3
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
src/corelib/thread/qthreadpool.cpp

index b702181..870f943 100644 (file)
 
 QT_BEGIN_NAMESPACE
 
-inline bool operator<(int priority, const QPair<QRunnable *, int> &p)
-{
-    return p.second < priority;
-}
-inline bool operator<(const QPair<QRunnable *, int> &p, int priority)
-{
-    return priority < p.second;
-}
-
 Q_GLOBAL_STATIC(QThreadPool, theInstance)
 
 /*
@@ -209,15 +200,22 @@ bool QThreadPoolPrivate::tryStart(QRunnable *task)
     return true;
 }
 
+inline bool operator<(int priority, const QPair<QRunnable *, int> &p)
+{ return p.second < priority; }
+inline bool operator<(const QPair<QRunnable *, int> &p, int priority)
+{ return priority < p.second; }
+
 void QThreadPoolPrivate::enqueueTask(QRunnable *runnable, int priority)
 {
     if (runnable->autoDelete())
         ++runnable->ref;
 
     // put it on the queue
-    QList<QPair<QRunnable *, int> >::iterator at =
-        qUpperBound(queue.begin(), queue.end(), priority);
-    queue.insert(at, qMakePair(runnable, priority));
+    QList<QPair<QRunnable *, int> >::const_iterator begin = queue.constBegin();
+    QList<QPair<QRunnable *, int> >::const_iterator it = queue.constEnd();
+    if (it != begin && priority < (*(it - 1)).second)
+        it = qUpperBound(begin, --it, priority);
+    queue.insert(it - begin, qMakePair(runnable, priority));
     runnableReady.wakeOne();
 }