| qatomic.cpp |
!
\class QAtomicInt
\inmodule QtCore
\brief The QAtomicInt class provides platform-independent atomic operations on int.
\since 4.4
This class is a equivalent to \c{QAtomicInteger<int>}. All other
functionality is equivalent. Please see that class for more information.
\sa QAtomicInteger, QAtomicPointer
|
63183 |
- |
| qatomic.h |
|
6429 |
- |
| qatomic_cxx11.h |
Attempt to detect whether the atomic operations exist in hardware
or whether they are emulated by way of a lock.
C++11 29.4 [atomics.lockfree] p1 says
The ATOMIC_..._LOCK_FREE macros indicate the lock-free property of the
corresponding atomic types, with the signed and unsigned variants grouped
together. The properties also apply to the corresponding (partial)
specializations of the atomic template. A value of 0 indicates that the
types are never lock-free. A value of 1 indicates that the types are
sometimes lock-free. A value of 2 indicates that the types are always
lock-free.
We have a problem when the value is 1: we'd need to check at runtime, but
QAtomicInteger requires a constexpr answer (defect introduced in Qt 5.0). So
we'll err in the side of caution and say it isn't.
|
18000 |
- |
| qatomicwait.cpp |
Implementation details:
Normally, a call from atomic_notify_one() or atomic_notify_all() corresponds
to a call to cond.notify_one() or cond.notify_all(). This simple
implementation would require that we keep a distinct wait condition variable
per atomic variable, of which there could be an arbitrary number.
Instead, we have a limited set of std::condition_variable, which are
selected based on the address of the variable being waited/notified on.
Because multiple, distinct variables could be sharing the same condition
variable, we need to perform a cond.notify_all() call in case the lock is
contended by waiters to more than one address, as we can't be sure which one
would be woken up by the cond.notify_one() call.
We recover some of the performance of notifying a single waker by also
storing the address of the variable that was being waited on. If it matches
the address of the variable being notified, we can perform a notify_one()
call. This also allows us to avoid any system call in case no waiter has yet
joined the queue. In case of contention, we store a sentinel address
instead, indicating there are waiters to multiple variables. The last waiter
to leave a wait queue is responsible for resetting the watched address back
to nullptr.
Performance details:
This implementation is designed for systems where neither the Standard
Library's own std::atomic_wait nor operating system futexes are available
(read: usually, not the systems Qt is used most frequently on). Therefore,
it's designed for simplicity, not performance. Simplifications applied
include:
- the total number of possible condition variables
- the hashing algorithm to select a condition variable (simple XOR)
- no attempt to wait for a variable change before calling cond.wait()
(no spinning, no HW-assisted wait)
Other limitations:
We only support 8-, 16-, 32- and 64-bit variables and we require bit-exact
comparisons for all bits. This means we do not support objects with padding
bits or without unique representations.
|
6353 |
- |
| qatomicwait_p.h |
being linked into the unit test |
2728 |
- |
| qbasicatomic.h |
|
12843 |
- |
| qexception.cpp |
!
\class QException
\inmodule QtCore
\brief The QException class provides a base class for exceptions that can be transferred across threads.
\since 5.0
Qt Concurrent supports throwing and catching exceptions across thread
boundaries, provided that the exception inherits from QException
and implements two helper functions:
\snippet code/src_corelib_thread_qexception.cpp 0
QException subclasses must be thrown by value and
caught by reference:
\snippet code/src_corelib_thread_qexception.cpp 1
If you throw an exception that is not a subclass of QException,
the \l{Qt Concurrent} functions will throw a QUnhandledException
in the receiver thread.
When using QFuture, transferred exceptions will be thrown when calling the following functions:
\list
\li QFuture::waitForFinished()
\li QFuture::result()
\li QFuture::resultAt()
\li QFuture::results()
\endlist
|
6049 |
- |
| qexception.h |
|
2220 |
- |
| qfutex_freebsd_p.h |
|
2376 |
- |
| qfutex_linux_p.h |
|
2808 |
- |
| qfutex_mac_p.h |
|
2413 |
- |
| qfutex_p.h |
|
1400 |
- |
| qfutex_win_p.h |
|
1611 |
- |
| qfuture.h |
|
19403 |
- |
| qfuture.qdoc |
|
66182 |
- |
| qfuture_impl.h |
|
42591 |
- |
| qfutureinterface.cpp |
|
35176 |
- |
| qfutureinterface.h |
|
15970 |
- |
| qfutureinterface_p.h |
|
6648 |
- |
| qfuturesynchronizer.h |
|
1705 |
- |
| qfuturesynchronizer.qdoc |
|
3825 |
- |
| qfuturewatcher.cpp |
! \class QFutureWatcher
\reentrant
\since 4.4
\inmodule QtCore
\ingroup thread
\brief The QFutureWatcher class allows monitoring a QFuture using signals
and slots.
QFutureWatcher is a template class where the template parameter \a T
specifies the result type of the QFuture being watched. QFutureWatcher
provides information and notifications about a QFuture. Use the setFuture()
function to start watching a particular QFuture. The future() function
returns the future set with setFuture().
For convenience, several of QFuture's functions are also available in
QFutureWatcher: progressValue(), progressMinimum(), progressMaximum(),
progressText(), isStarted(), isFinished(), isRunning(), isCanceled(),
isSuspending(), isSuspended(), waitForFinished(), result(), and resultAt().
The cancel(), setSuspended(), suspend(), resume(), and toggleSuspended() functions
are slots in QFutureWatcher.
Status changes are reported via the started(), finished(), canceled(),
suspending(), suspended(), resumed(), resultReadyAt(), and resultsReadyAt()
signals. Progress information is provided from the progressRangeChanged(),
void progressValueChanged(), and progressTextChanged() signals.
Throttling control is provided by the setPendingResultsLimit() function.
When the number of pending resultReadyAt() or resultsReadyAt() signals
exceeds the limit, the computation represented by the future will be
throttled automatically. The computation will resume once the number of
pending signals drops below the limit.
Example: Starting a computation and getting a slot callback when it's
finished:
\snippet code/src_corelib_thread_qfuturewatcher.cpp 0
Be aware that not all running asynchronous computations can be canceled or
suspended. For example, the future returned by QtConcurrent::run() cannot be
canceled; but the future returned by QtConcurrent::mappedReduced() can.
QFutureWatcher<void> is specialized to not contain any of the result
fetching functions. Any QFuture<T> can be watched by a
QFutureWatcher<void> as well. This is useful if only status or progress
information is needed; not the actual result data.
\sa QFuture, {Qt Concurrent}
|
24133 |
- |
| qfuturewatcher.h |
|
4947 |
- |
| qfuturewatcher_p.h |
|
1190 |
- |
| qgenericatomic.h |
|
965 |
- |
| qlatch.cpp |
!
\class QLatch
\internal
Implements the same API as \c std::latch (C++20), allowing a single
synchronization between threads.
\section2 Typical uses
\section3 Waiting for threaded work to finish
For this use-case, one or more threads perform some work, which needs to
finish before the caller thread can proceed. For this, each worker thread
calls countDown() once they have finished their work, while the caller
thread suspends execution by calling wait().
The operation is best seen in:
\code
QLatch latch(segments);
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (data->height - y) / (segments - i);
threadPool->start([&, y, yn]() {
convertSegment(y, y + yn);
latch.countDown();
});
y += yn;
}
latch.wait();
\endcode
Or, for a single thread:
\code
QLatch latch(1);
QMetaObject::invokeMethod(object, [&]() {
doSomething();
latch.countDown();
}, Qt::QueuedConnection);
latch.wait();
\endcode
In fact, the above is exactly what Qt::BlockingQueued connection does.
\section3 Synchronizing execution
For this use-case, multiple threads must reach a particular state before
any of them may proceed. In this case, all of them call arriveAndWait(),
causing all but the last one of them to suspend execution until that last
one also arrives.
\code
QLatch latch(n);
for (int i = 0; i < n; ++i) {
threadPool->start([] {
latch.arriveAndWait();
doStressfulWork();
});
}
\endcode
\section2 Differences from \c std::latch
\list
\li Uses \c{int} in the API instead of \c{ptrdiff_t} (note that the max()
is the same as libstdc++'s on Linux).
\li count_down() is not \c{const} (libstdc++ implementation is).
\endlist
\omit
\section2 Implementation details
countDown() must call wakeUp() if the latch counter reaches zero and there
are threads waiting to be woken up. Or, conversely, countDown() needs to do
nothing after decrementing if the latch counter is still non-zero or there
are no waiters. Therefore, we choose the bits so that a non-zero
\c{counter} member implies no action required.
\endomit
|
6910 |
- |
| qlatch_p.h |
being linked into the unit test |
2339 |
- |
| qlocking_p.h |
|
2441 |
- |
| qmutex.cpp |
\class QBasicMutex
\inmodule QtCore
\brief QMutex POD
\internal
\ingroup thread
- Can be used as global static object.
- Always non-recursive
- Do not use tryLock with timeout > 0, else you can have a leak (see the ~QMutex destructor)
|
32000 |
- |
| qmutex.h |
|
9393 |
- |
| qmutex_p.h |
Boolean indicating that a timed wait timed out.
When it is true, a reference is held.
It is there to avoid a race that happens if unlock happens right
when the mutex is unlocked.
|
2609 |
- |
| qmutex_unix.cpp |
|
1761 |
- |
| qorderedmutexlocker_p.h |
Locks 2 mutexes in a defined order, avoiding a recursive lock if
we're trying to lock the same mutex twice.
|
3565 |
- |
| qpromise.h |
|
3531 |
- |
| qpromise.qdoc |
|
10869 |
- |
| qreadwritelock.cpp |
Implementation details of QReadWriteLock:
Depending on the valued of d_ptr, the lock is in the following state:
- when d_ptr == 0x0: Unlocked (no readers, no writers) and non-recursive.
- when d_ptr & 0x1: If the least significant bit is set, we are locked for read.
In that case, d_ptr>>4 represents the number of reading threads minus 1. No writers
are waiting, and the lock is not recursive.
- when d_ptr == 0x2: We are locked for write and nobody is waiting. (no contention)
- In any other case, d_ptr points to an actual QReadWriteLockPrivate.
|
23559 |
- |
| qreadwritelock.h |
|
11501 |
- |
| qreadwritelock_p.h |
!
\internal
Describes the state of the QReadWriteLock whose private is \a dd.
Returns one of:
\list
\li 0 (unlocked)
\li \c IsRecursiveLock (still unlocked)
\li \c StateLockedForRead
\li \c{StateLockedForRead | IsRecursiveLock}
\li \c StateLockedForWrite
\li \c{StateLockedForWrite | IsRecursiveLock}
\li \c{StateLockedForWrite | IsRecursiveLock | MultiplyLocked} = \c RecursivelyLockedForWrite
\endlist
|
5083 |
- |
| qresultstore.cpp |
!
\internal
Finds result in \a store by \a index
|
6609 |
- |
| qresultstore.h |
ResultStore stores indexed results. Results can be added and retrieved
either individually batched in a QList. Retriveing results and checking
which indexes are in the store can be done either by iterating or by random
access. In addition results can be removed from the front of the store,
either individually or in batches.
|
7692 |
- |
| qrunnable.cpp |
!
\internal
Prints a warning and returns nullptr.
|
3287 |
- |
| qrunnable.h |
|
4197 |
- |
| qsemaphore.cpp |
!
\class QSemaphore
\inmodule QtCore
\brief The QSemaphore class provides a general counting semaphore.
\threadsafe
\ingroup thread
A semaphore is a generalization of a mutex. While a mutex can
only be locked once, it's possible to acquire a semaphore
multiple times. Semaphores are typically used to protect a
certain number of identical resources.
Semaphores support two fundamental operations, acquire() and
release():
\list
\li acquire(\e{n}) tries to acquire \e n resources. If there aren't
that many resources available, the call will block until this
is the case.
\li release(\e{n}) releases \e n resources.
\endlist
There's also a tryAcquire() function that returns immediately if
it cannot acquire the resources, and an available() function that
returns the number of available resources at any time.
Example:
\snippet code/src_corelib_thread_qsemaphore.cpp 0
A typical application of semaphores is for controlling access to
a circular buffer shared by a producer thread and a consumer
thread. The \l{Producer and Consumer using Semaphores} example shows how
to use QSemaphore to solve that problem.
A non-computing example of a semaphore would be dining at a
restaurant. A semaphore is initialized with the number of chairs
in the restaurant. As people arrive, they want a seat. As seats
are filled, available() is decremented. As people leave, the
available() is incremented, allowing more people to enter. If a
party of 10 people want to be seated, but there are only 9 seats,
those 10 people will wait, but a party of 4 people would be
seated (taking the available seats to 5, making the party of 10
people wait longer).
\sa QSemaphoreReleaser, QMutex, QWaitCondition, QThread,
{Producer and Consumer using Semaphores}
|
22595 |
- |
| qsemaphore.h |
|
2787 |
- |
| qthread.cpp |
QPostEventList
|
43624 |
- |
| qthread.h |
On architectures and platforms we know, interpret the thread control
block (TCB) as a unique identifier for a thread within a process. Otherwise,
fall back to a slower but safe implementation.
As per the documentation of currentThreadId, we return an opaque handle
as a thread identifier, and application code is not supposed to use that
value for anything. In Qt we use the handle to check if threads are identical,
for which the TCB is sufficient.
So we use the fastest possible way, rather than spend time on returning
some pseudo-interoperable value.
|
6374 |
- |
| qthread_p.h |
BindingStatusOrList is basically a QBiPointer (as found in declarative)
with some helper methods to manipulate the list. BindingStatusOrList starts
its life in a null state and supports the following transitions
0 state (initial)
/ \
/ \
v v
pending object list----------->binding status
Note that binding status is the final state, and we never transition away
from it
|
11823 |
- |
| qthread_unix.cpp |
|
38353 |
- |
| qthread_win.cpp |
QThreadData
|
17218 |
- |
| qthreadpool.cpp |
QThread wrapper, provides synchronization against a ThreadPool
|
27145 |
- |
| qthreadpool.h |
|
3559 |
- |
| qthreadpool_p.h |
|
4333 |
- |
| qthreadstorage.cpp |
the destructors vector has already been destroyed, yet a new
QThreadStorage is being allocated. this can only happen during global
destruction, at which point we assume that there is only one thread.
in order to keep QThreadStorage working, we need somewhere to store
the data, best place we have in this situation is at the tail of the
current thread's tls vector. the destructor is ignored, since we have
no where to store it, and no way to actually call it.
|
10323 |
- |
| qthreadstorage.h |
|
4670 |
- |
| qthreadstorage_p.h |
|
760 |
- |
| qtsan_impl.h |
|
2642 |
- |
| qwaitcondition.h |
|
1724 |
- |
| qwaitcondition.qdoc |
|
6265 |
- |
| qwaitcondition_p.h |
QWAITCONDITION_P_H |
1296 |
- |
| qwaitcondition_unix.cpp |
|
5283 |
- |
| qwaitcondition_win.cpp |
|
5210 |
- |
| qyieldcpu.h |
|
1902 |
- |
| qyieldcpu.qdoc |
|
2169 |
- |