1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtCore module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include "qtconcurrentiteratekernel.h"
45 #include <mach/mach.h>
46 #include <mach/mach_time.h>
48 #elif defined(Q_OS_UNIX)
49 #if defined(Q_OS_HURD)
54 #elif defined(Q_OS_WIN)
55 #include <qt_windows.h>
58 #include "private/qfunctions_p.h"
61 #ifndef QT_NO_CONCURRENT
72 static qint64 getticks()
74 return mach_absolute_time();
77 #elif defined(Q_OS_UNIX)
80 static qint64 getticks()
82 #if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
85 #ifndef _POSIX_THREAD_CPUTIME
86 clockId = CLOCK_REALTIME;
87 #elif (_POSIX_THREAD_CPUTIME-0 <= 0)
88 // if we don't have CLOCK_THREAD_CPUTIME_ID, we have to just use elapsed realtime instead
89 clockId = CLOCK_REALTIME;
91 # if (_POSIX_THREAD_CPUTIME-0 == 0)
92 // detect availablility of CLOCK_THREAD_CPUTIME_ID
93 static long useThreadCpuTime = -2;
94 if (useThreadCpuTime == -2) {
95 // sysconf() will return either -1 or _POSIX_VERSION (don't care about thread races here)
96 useThreadCpuTime = sysconf(_SC_THREAD_CPUTIME);
98 if (useThreadCpuTime != -1)
99 clockId = CLOCK_THREAD_CPUTIME_ID;
102 clockId = CLOCK_THREAD_CPUTIME_ID;
106 if (clock_gettime(clockId, &ts) == -1)
108 return (ts.tv_sec * 1000000000) + ts.tv_nsec;
111 // no clock_gettime(), fall back to wall time
113 gettimeofday(&tv, 0);
114 return (tv.tv_sec * 1000000) + tv.tv_usec;
118 #elif defined(Q_OS_WIN)
120 static qint64 getticks()
123 if (!QueryPerformanceCounter(&x))
130 static double elapsed(qint64 after, qint64 before)
132 return double(after - before);
135 namespace QtConcurrent {
140 BlockSizeManager::BlockSizeManager(int iterationCount)
141 : maxBlockSize(iterationCount / (QThreadPool::globalInstance()->maxThreadCount() * 2)),
142 beforeUser(0), afterUser(0),
143 controlPartElapsed(MedianSize), userPartElapsed(MedianSize),
147 // Records the time before user code.
148 void BlockSizeManager::timeBeforeUser()
150 if (blockSizeMaxed())
153 beforeUser = getticks();
154 controlPartElapsed.addValue(elapsed(beforeUser, afterUser));
157 // Records the time after user code and adjust the block size if we are spending
158 // to much time in the for control code compared with the user code.
159 void BlockSizeManager::timeAfterUser()
161 if (blockSizeMaxed())
164 afterUser = getticks();
165 userPartElapsed.addValue(elapsed(afterUser, beforeUser));
167 if (controlPartElapsed.isMedianValid() == false)
170 if (controlPartElapsed.median() * TargetRatio < userPartElapsed.median())
173 m_blockSize = qMin(m_blockSize * 2, maxBlockSize);
175 #ifdef QTCONCURRENT_FOR_DEBUG
176 qDebug() << QThread::currentThread() << "adjusting block size" << controlPartElapsed.median() << userPartElapsed.median() << m_blockSize;
179 // Reset the medians after adjusting the block size so we get
180 // new measurements with the new block size.
181 controlPartElapsed.reset();
182 userPartElapsed.reset();
185 int BlockSizeManager::blockSize()
190 } // namespace QtConcurrent
194 #endif // QT_NO_CONCURRENT