Qt 4.8
qfutureinterface.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
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.
16 **
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.
24 **
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.
28 **
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.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 // qfutureinterface.h included from qfuture.h
43 #include "qfuture.h"
44 
45 #ifndef QT_NO_QFUTURE
46 
47 #include <QtCore/qatomic.h>
48 #include <QtCore/qthread.h>
49 #include <QtCore/qthreadpool.h>
50 #include <private/qthreadpool_p.h>
51 
52 #include "qfutureinterface_p.h"
53 
55 
56 enum {
58 };
59 
61  : d(new QFutureInterfaceBasePrivate(initialState))
62 { }
63 
65  : d(other.d)
66 {
67  d->refCount.ref();
68 }
69 
71 {
72  if (!d->refCount.deref())
73  delete d;
74 }
75 
77 {
78  QMutexLocker locker(&d->m_mutex);
79  if (d->state & Canceled)
80  return;
81 
82  d->state = State((d->state & ~Paused) | Canceled);
86 }
87 
89 {
90  QMutexLocker locker(&d->m_mutex);
91  if (paused) {
92  d->state = State(d->state | Paused);
94  } else {
95  d->state = State(d->state & ~Paused);
98  }
99 }
100 
102 {
103  QMutexLocker locker(&d->m_mutex);
104  if (d->state & Paused) {
105  d->state = State(d->state & ~Paused);
108  } else {
109  d->state = State(d->state | Paused);
111  }
112 }
113 
115 {
116  // bail out if we are not changing the state
117  if ((enable && (d->state & Throttled)) || (!enable && !(d->state & Throttled)))
118  return;
119 
120  // lock and change the state
122  if (enable) {
123  d->state = State(d->state | Throttled);
124  } else {
125  d->state = State(d->state & ~Throttled);
126  if (!(d->state & Paused))
128  }
129 }
130 
131 
133 {
134  return queryState(Running);
135 }
136 
138 {
139  return queryState(Started);
140 }
141 
143 {
144  return queryState(Canceled);
145 }
146 
148 {
149  return queryState(Finished);
150 }
151 
153 {
154  return queryState(Paused);
155 }
156 
158 {
159  return queryState(Throttled);
160 }
161 
163 {
165  return d->internal_isResultReadyAt(index);
166 }
167 
169 {
171  return d->internal_waitForNextResult();
172 }
173 
175 {
176  // return early if possible to avoid taking the mutex lock.
177  if ((d->state & Paused) == false || (d->state & Canceled))
178  return;
179 
181  if ((d->state & Paused) == false || (d->state & Canceled))
182  return;
183 
184  // decrease active thread count since this thread will wait.
186 
188 
190 }
191 
193 {
194  return d->m_progressValue;
195 }
196 
198 {
199  return d->m_progressMinimum;
200 }
201 
203 {
204  return d->m_progressMaximum;
205 }
206 
208 {
210  return d->internal_resultCount();
211 }
212 
214 {
215  QMutexLocker locker(&d->m_mutex);
216  return d->m_progressText;
217 }
218 
220 {
221  QMutexLocker locker(&d->m_mutex);
222  return !d->progressTime.isValid() || (d->progressTime.elapsed() > (1000 / MaxProgressEmitsPerSecond));
223 }
224 
226 {
227  QMutexLocker locker(&d->m_mutex);
228  if ((d->state & Started) || (d->state & Canceled) || (d->state & Finished))
229  return;
230 
233 }
234 
236 {
237  cancel();
238 }
239 
240 #ifndef QT_NO_EXCEPTIONS
242 {
243  QMutexLocker locker(&d->m_mutex);
244  if ((d->state & Canceled) || (d->state & Finished))
245  return;
246 
247  d->m_exceptionStore.setException(exception);
248  d->state = State(d->state | Canceled);
252 }
253 #endif
254 
256 {
257  QMutexLocker locker(&d->m_mutex);
258  if (!(d->state & Finished)) {
259  d->state = State((d->state & ~Running) | Finished);
262  }
263 }
264 
266 {
267  if (d->manualProgress == false)
268  setProgressRange(0, resultCount);
270 }
271 
273 {
274  return d->m_expectedResultCount;
275 }
276 
278 {
279  return (d->state & state);
280 }
281 
283 {
285 
286  if (!(d->state & Running))
287  return;
288 
289  // To avoid deadlocks and reduce the number of threads used, try to
290  // run the runnable in the current thread.
291  QThreadPool::globalInstance()->d_func()->stealRunnable(d->runnable);
292 
294 
295  if (!(d->state & Running))
296  return;
297 
298  const int waitIndex = (resultIndex == -1) ? INT_MAX : resultIndex;
299  while ((d->state & Running) && d->internal_isResultReadyAt(waitIndex) == false)
301 
303 }
304 
306 {
307  if (d->state & Running) {
308  QThreadPool::globalInstance()->d_func()->stealRunnable(d->runnable);
309 
311 
312  while (d->state & Running)
314  }
315 
317 }
318 
319 void QFutureInterfaceBase::reportResultsReady(int beginIndex, int endIndex)
320 {
321  if ((d->state & Canceled) || (d->state & Finished) || beginIndex == endIndex)
322  return;
323 
325 
326  if (d->manualProgress == false) {
327  if (d->internal_updateProgress(d->m_progressValue + endIndex - beginIndex) == false) {
329  beginIndex,
330  endIndex));
331  return;
332  }
333 
336  d->m_progressText),
338  beginIndex,
339  endIndex));
340  return;
341  }
343 }
344 
346 {
347  d->runnable = runnable;
348 }
349 
351 {
352  QMutexLocker locker(&d->m_mutex);
353  resultStoreBase().setFilterMode(enable);
354 }
355 
356 void QFutureInterfaceBase::setProgressRange(int minimum, int maximum)
357 {
358  QMutexLocker locker(&d->m_mutex);
359  d->m_progressMinimum = minimum;
360  d->m_progressMaximum = maximum;
362 }
363 
365 {
366  setProgressValueAndText(progressValue, QString());
367 }
368 
370  const QString &progressText)
371 {
372  QMutexLocker locker(&d->m_mutex);
373  if (d->manualProgress == false)
374  d->manualProgress = true;
375  if (d->m_progressValue >= progressValue)
376  return;
377 
378  if ((d->state & Canceled) || (d->state & Finished))
379  return;
380 
381  if (d->internal_updateProgress(progressValue, progressText)) {
384  d->m_progressText));
385  }
386 }
387 
389 {
390  return &d->m_mutex;
391 }
392 
394 {
395  return d->m_exceptionStore;
396 }
397 
398 QtConcurrent::ResultStoreBase &QFutureInterfaceBase::resultStoreBase()
399 {
400  return d->m_results;
401 }
402 
403 const QtConcurrent::ResultStoreBase &QFutureInterfaceBase::resultStoreBase() const
404 {
405  return d->m_results;
406 }
407 
409 {
410  other.d->refCount.ref();
411  if (!d->refCount.deref())
412  delete d;
413  d = other.d;
414  return *this;
415 }
416 
418 {
419  return d->refCount == 1;
420 }
421 
423  : refCount(1), m_progressValue(0), m_progressMinimum(0), m_progressMaximum(0),
424  state(initialState), pendingResults(0),
425  manualProgress(false), m_expectedResultCount(0), runnable(0)
426 {
428 }
429 
431 {
432  return m_results.count(); // ### subtract canceled results.
433 }
434 
436 {
437  return (m_results.contains(index));
438 }
439 
441 {
442  if (m_results.hasNextResult())
443  return true;
444 
445  while ((state & QFutureInterfaceBase::Running) && m_results.hasNextResult() == false)
447 
448  return (!(state & QFutureInterfaceBase::Canceled) && m_results.hasNextResult());
449 }
450 
452  const QString &progressText)
453 {
454  if (m_progressValue >= progress)
455  return false;
456 
457  m_progressValue = progress;
459 
460  if (progressTime.isValid() && m_progressValue != m_progressMaximum) // make sure the first and last steps are emitted.
462  return false;
463 
465  return true;
466 }
467 
469 {
470  // bail out if we are not changing the state
471  if ((enable && (state & QFutureInterfaceBase::Throttled))
472  || (!enable && !(state & QFutureInterfaceBase::Throttled)))
473  return;
474 
475  // change the state
476  if (enable) {
477  state = QFutureInterfaceBase::State(state | QFutureInterfaceBase::Throttled);
478  } else {
479  state = QFutureInterfaceBase::State(state & ~QFutureInterfaceBase::Throttled);
482  }
483 }
484 
486 {
488  return;
489 
490  for (int i = 0; i < outputConnections.count(); ++i)
491  outputConnections.at(i)->postCallOutEvent(callOutEvent);
492 }
493 
495  const QFutureCallOutEvent &callOutEvent2)
496 {
498  return;
499 
500  for (int i = 0; i < outputConnections.count(); ++i) {
501  QFutureCallOutInterface *interface = outputConnections.at(i);
502  interface->postCallOutEvent(callOutEvent1);
503  interface->postCallOutEvent(callOutEvent2);
504  }
505 }
506 
507 // This function connects an output interface (for example a QFutureWatcher)
508 // to this future. While holding the lock we check the state and ready results
509 // and add the appropriate callouts to the queue. In order to avoid deadlocks,
510 // the actual callouts are made at the end while not holding the lock.
512 {
513  QMutexLocker locker(&m_mutex);
514 
522  m_progressText));
523  }
524 
525  QtConcurrent::ResultIteratorBase it = m_results.begin();
526  while (it != m_results.end()) {
527  const int begin = it.resultIndex();
528  const int end = begin + it.batchSize();
530  begin,
531  end));
532  it.batchedAdvance();
533  }
534 
537 
540 
543 
544  outputConnections.append(interface);
545 }
546 
548 {
550  const int index = outputConnections.indexOf(interface);
551  if (index == -1)
552  return;
554 
555  interface->callOutInterfaceDisconnected();
556 }
557 
559 {
560  state = newState;
561 }
562 
564 
565 #endif // QT_NO_CONCURRENT
double d
Definition: qnumeric_p.h:62
void releaseThread()
Releases a thread previously reserved by a call to reserveThread().
bool internal_isResultReadyAt(int index) const
void setProgressValueAndText(int progressValue, const QString &progressText)
QString progressText() const
Returns the (optional) textual representation of the progress as reported by the asynchronous computa...
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
The QMutex class provides access serialization between threads.
Definition: qmutex.h:60
void setProgressValue(int progressValue)
bool isResultReadyAt(int index) const
void sendCallOuts(const QFutureCallOutEvent &callOut1, const QFutureCallOutEvent &callOut2)
#define it(className, varName)
QFutureInterfaceBase(State initialState=NoState)
void setFilterMode(bool enable)
QtConcurrent::ResultStoreBase m_results
virtual void postCallOutEvent(const QFutureCallOutEvent &)=0
bool queryState(State state) const
bool isValid() const
Returns false if this object was invalidated by a call to invalidate() and has not been restarted sin...
QString progressText() const
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
QFutureInterfaceBase::State state
bool ref()
Atomically increments the value of this QAtomicInt.
void setProgressRange(int minimum, int maximum)
QFutureInterfaceBasePrivate * d
The QString class provides a Unicode character string.
Definition: qstring.h:83
void sendCallOut(const QFutureCallOutEvent &callOut)
The QRunnable class is the base class for all runnable objects.
Definition: qrunnable.h:52
QtConcurrent::internal::ExceptionStore & exceptionStore()
qint64 elapsed() const
Returns the number of milliseconds since this QElapsedTimer was last started.
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
bool referenceCountIsOne() const
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
QtConcurrent::internal::ExceptionStore m_exceptionStore
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
void disconnectOutputInterface(QFutureCallOutInterface *iface)
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
bool deref()
Atomically decrements the value of this QAtomicInt.
void reportException(const QtConcurrent::Exception &e)
void setRunnable(QRunnable *runnable)
void setPaused(bool paused)
void internal_setThrottled(bool enable)
void invalidate()
Marks this QElapsedTimer object as invalid.
void setExpectedResultCount(int resultCount)
The State element defines configurations of objects and properties.
QList< QFutureCallOutInterface * > outputConnections
QMutex * mutex() const
bool wait(QMutex *mutex, unsigned long time=ULONG_MAX)
QFutureInterfaceBasePrivate(QFutureInterfaceBase::State initialState)
void connectOutputInterface(QFutureCallOutInterface *iface)
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
int indexOf(const T &t, int from=0) const
Returns the index position of the first occurrence of value in the list, searching forward from index...
Definition: qlist.h:847
virtual void callOutInterfaceDisconnected()=0
The Exception class provides a base class for exceptions that can transferred across threads...
static QReadWriteLock lock
Definition: proxyconf.cpp:399
QFutureInterfaceBase & operator=(const QFutureInterfaceBase &other)
void waitForResult(int resultIndex)
static QThreadPool * globalInstance()
Returns the global QThreadPool instance.
void setState(QFutureInterfaceBase::State state)
quint16 index
void setException(const Exception &e)
bool isProgressUpdateNeeded() const
void paused()
This signal is emitted when the watched future is paused.
void reportResultsReady(int beginIndex, int endIndex)
bool internal_updateProgress(int progress, const QString &progressText=QString())
static const KeyPair *const end
void setThrottled(bool enable)
QtConcurrent::ResultStoreBase & resultStoreBase()
void start()
Starts this timer.
#define INT_MAX
void reserveThread()
Reserves one thread, disregarding activeThreadCount() and maxThreadCount().
void removeAt(int i)
Removes the item at index position i.
Definition: qlist.h:480