summaryrefslogtreecommitdiffstats
path: root/src/corelib/thread
Commit message (Collapse)AuthorAgeFilesLines
* QThread/Unix: intercept exceptions only with GlibcVladimir Belyavsky11 days1-9/+11
| | | | | | | | | | | | | | | | | See 5677b70eee2e923eea8e5150500ac745d8d54974 for details why we need such specific exception handling for Glibc. In short, on Glibc, pthread_cancel and pthread_exit are implemented by throwing a special kind of exception that can be caught, but must always be rethrown. That exception is then used to activate the cancellation clean-up handlers. But for libc++ on Apple platforms we can simply wrap it as noexcept to guarantee that std::terminate() will be called in case of any unhandled exception. Task-number: QTBUG-141803 Pick-to: 6.10 6.8 Change-Id: Iaa88d3a8091425206ee2735e835ae74fd087e9e0 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QThread: optimize currentThreadId() for WindowsThiago Macieira2025-11-041-20/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | We don't need to read the TIB's pointer from the TIB to access the TIB. We are already accessing the TIB. Drive-by fix the incorrect comment about an internal compiler error with intrisics for MinGW. It's not an ICE: it just doesn't have those MSVC- specific intrinsics in the first place. Confirmed by debugging tst_QThread::currentThreadId() (or any application, for that matter): Thread 1 hit Breakpoint 2.2, QThread::currentThreadId () at C:/Qt/qt6/qtbase/src/corelib/thread/qthread.h:164 164 Qt::HANDLE tid; // typedef to void* (gdb) fin Run till exit from #0 QThread::currentThreadId () at C:/Qt/qt6/qtbase/src/corelib/thread/qthread.h:164 0x00007fff3d4edc64 in QAdoptedThread::QAdoptedThread (this=0x70c090, data=0x70f1c0) at C:/Qt/qt6/qtbase/src/corelib/thread/qthread.cpp:105 105 Qt::HANDLE id = QThread::currentThreadId(); Value returned is $5 = (void *) 0x73f8 (gdb) p (void *)GetCurrentThreadId() $6 = (void *) 0x73f8 Pick-to: 6.10 6.8 Change-Id: I11c4401a495df9a43b7efffd270732847e431ae1 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* QBasicAtomicInteger: Add (internal) refRelaxedFabian Kosmale2025-10-273-0/+15
| | | | | | | | | | | | | | | | | | | | It is known that incrementing the refcount can use relaxed semantics, compare https://web.archive.org/web/20251016043603/https://devblogs.microsoft.com/oldnewthing/20251015-00/?p=111686 However, we can't modify QBasicAtomic::ref, because that is documented to use "ordered" semantics. So introduce a new (internal) refRelaxed method, which simply calls fetchAndAddRelaxed(1) instead. Compared to ref, we also do not return anything, as no expected user has a need for the return value (and it only causes more work for the compiler to get rid of it again). Our deref operation is still using acquire_release semantics, so everything is fine. Port QArrayData to use it as a first user so that the functionality is tested. Change-Id: I678870551fe85b83d9bb073ddb5947e649845264 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QSemaphore: stub out tryAcquire() for no-threadMorten Sørvig2025-10-211-1/+19
| | | | | | | | | Ammends 7075ac5bf6bf51a7538bf5c6592e2ff97f5c7cbe. Pick-to: 6.10 Fixes: QTBUG-141130 Change-Id: I699bb61832cded1b2f05d0138478e3d8c703f8f2 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Doc: Add more info to QThread::requestInterruptionMoss Heim2025-10-141-0/+3
| | | | | | | | Document its behavior on main thread & non-running threads. Pick-to: 6.8 6.9 6.10 Change-Id: I0857217effa727971fb532adf70e892d205036dd Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Thread: QResultStore - silence -Wunnecessary-virtual-specifierTim Blechmann2025-09-251-0/+7
| | | | | | | | | | clang-21 emits -Wunnecessary-virtual-specifier on final classes. Disabling the warning to silence warnings when compiling application code. Pick-to: 6.10 6.8 6.5 Change-Id: I382f38d20d67d0758f670bd880924982d525e5ab Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QFuture: allow implicit conversion from QFuture<T> to QFuture<void>Giuseppe D'Angelo2025-09-191-1/+1
| | | | | | | | | | | | | This is a form of type erasure and therefore should be implicit: a function `f(QFuture<void>)` should be callable as `f(future)` for any `QFuture<T> future`. Drop the `explicit`. This is also in line with the existing converting assignment operator. Pick-to: 6.10 6.9 6.8 Fixes: QTBUG-139790 Change-Id: Ib63edf197285cce2c95a28b0308ddc7256e4af2b Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
* Move all Q_DECL_(PURE|CONST)_FUNCTION markers to the frontMårten Nordheim2025-09-192-3/+3
| | | | | | | | | While testing defining Q_DECL_PURE_FUNCTION for MSVC I discovered it cannot handle having the marker trailing, while GCC/clang can cope with either. Change-Id: Ic9dd088996c191263e2f2a43c2f6a16533bdb9c5 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Doc: Update multi-threading doc titlePaul Wicking2025-09-161-1/+1
| | | | | | | | | | | | Change title from "Thread Support in Qt" to "Multi-threading in Qt" to use more modern and precise terminology. Add target directive to preserve possible existing links and update all cross-references across the codebase. Task-number: QTBUG-140178 Pick-to: 6.10 6.10.0 6.9 6.8 Change-Id: If3457a811d71fa17e29cf5d5886fda11951c2862 Reviewed-by: Andy Shaw <andy.shaw@qt.io>
* no-thread: include setStatusAndClearList() in buildMorten Sørvig2025-09-101-0/+4
| | | | | | | | | | | | Fix build error on single-threaded webassembly: undefined symbol: QtPrivate::BindingStatusOrList:: setStatusAndClearList(QBindingStatus*) Pick-to: 6.10 6.10.0 6.9 6.8 6.5 Fixes: QTBUG-139990 Change-Id: Iabeb4c0f94a9ec8374ceb9419f0acacd02711729 Reviewed-by: Jani Heikkinen <jani.heikkinen@qt.io>
* QBindingStatus/QThread: Add missing synchronizationFabian Kosmale2025-09-021-1/+4
| | | | | | | | | | | As the comment in qthread_p.h indicates, setStatusAndClearList requires external synchronization, otherwise we get data races. That was missinsg 2d92ea02501c058f55a8562f55804ccb105bf4bf, and gets fixed by this commit. Pick-to: 6.10 6.9 6.8 6.5 Change-Id: I63ca246964a85d5045b459cc17c8883dfa0ff914 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QProperty: Avoid referencing stale QBindingStatusFabian Kosmale2025-08-274-14/+33
| | | | | | | | | | | | | | | | | Because we cache the QBindingStatus in QObjects, and the QObjects might outlive the native thread, we can't bind the lifetime of the QBindingStatus solely to the native thread. Instead, keep it alive while the QThreadData associated with the QObject still exists. This is done by moving the BindingStatusOrList member for QThreadPrivate to QThreadData, and by letting QThreadData own the binding status. Pick-to: 6.10 6.9 6.8 6.5 Fixes: QTBUG-126134 Change-Id: I747ec1778f6b6f376c38d1c678dc5b2f62fcb7ef Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Don't assert if the QFuture is in pending stateBogDan Vatra2025-08-211-4/+2
| | | | | | | | | Same as result/results takeResult should just waitForResult Fixes: QTBUG-139119 Pick-to: 6.10 6.9 6.8 Change-Id: Ic578ee6c5853a5b1551f1d30ac9f5e302f79b4e6 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* QMutex: mark the uncontended paths as Q_LIKELYThiago Macieira2025-08-141-2/+2
| | | | | Change-Id: I72ae8d8975c26d1f2e81fffd5839a2500f5edcb6 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
* QFutureWatcher docs: Add a full stopJarek Kobus2025-08-061-1/+1
| | | | | | Pick-to: 6.10 6.9 6.8 Change-Id: I78ae2bd5985943abe28c012d551ffefcdfe298b7 Reviewed-by: Paul Wicking <paul.wicking@qt.io>
* QReadWriteLock: use the Counter static variableThiago Macieira2025-08-051-3/+3
| | | | | | | Instead of duplicating its value everywhere. Change-Id: If220ae2bc2def315431efffd5ac604f6c64a1735 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
* QReadWriteLock: inline the locking contentThiago Macieira2025-08-053-44/+149
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is similar to QMutex, which has an inline uncontended portion and leaves the handling of contention (or recursive QRWL) to the out-of-line content. Using tst_bench_qreadwritelock on an Intel i9-7940X with the CPUs fixed to 3.1 GHz and only using the first 4 cores, I noticed: * The cost for an uncontended lock of either type decreased by 26 instructions but only 1 cycle. * Compared to an uncontended QMutex, either type of uncontended lock only requires 2 more instructions (11 vs 9). * Contended read locks appear to improve by about 274 cycles and 35 instructions, or over 6.7% and 16.5% respectively (excluding the "nothing" base cost). * Contended write locks appear to be slower by about 118 cycles and 8 instructions, though the benchmark varies a lot. * Likewise, recursive QReadWriteLocks cost 5 instructions more. This means that for QReadWriteLocks used where reads are far more frequent than writes, this is a meaningful performance improvement, at the cost of some more code being emitted on use. This makes everyone have roughly the same benefit as QtCore in LTO mode. The extra cost for contended write locks and for recursion are probably caused by the checks upon entry to the contendedTryLock* functions, which duplicate what was inlined. Change-Id: Ia78b7edb86b31435b7b2fffd82cd5e27688355e8 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
* Mark all files in corelib/thread security significantMatthias Rauter2025-08-0459-0/+60
| | | | | | | | | | | | | | | None of the files in this folder handle untrusted inputs, implement a protocol or cryptographic logic or execute external code. While bugs in threading, atomics, and locks might lead to security issues, there is no elevated risk and exposure of these classes and methods. Therefore they are marked significant. Pick-to: 6.10 6.9 6.8 Fixes: QTBUG-135196 Change-Id: If336b6f8a920b3d41b4c4e57f1bff36e2b392739 Reviewed-by: Dimitrios Apostolou <jimis@qt.io> Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
* QFuture: simplify is_same<T, void> → is_void<T>Marc Mutz2025-08-011-4/+4
| | | | | | | | | | | | | | | | std::is_void is available since C++11, the same as std::is_same, so use it. Amends 1005c86c6101a9cdc5ce37de3fd5bc67505bf8bc, 44ceb56455c82df3e6b1c9a2fa373cac14a039f8 and 90d9a86c2e762c9426d0facbd54ed5dbff574ecd. Found while fixing CID-87769. Coverity-Id: 87769 Pick-to: 6.10 6.9 6.8 6.5 Change-Id: I7ae296b53e215ef33f923ac7aff2623de879f70e Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* QFuture: fix UB (uninit'ed member) in const_iterator default ctorMarc Mutz2025-08-011-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | Coverity complained that the default ctor didn't initialize the iterator's data members, and it's correct, of course. What makes matters worse: by implementing the default constructor like that, we break the C++ guarantee that value-initialized iterators must compare equal. Fix by = default'ing the constructor. That leaves default-construction to establish only the partially-formed state, as before, but value-initialization now creates a well-formed object, ready for equality comparison. Add a test. Amends the start of the public history. Coverity-Id: 87769 Pick-to: 6.10 6.9 6.8 6.5 Change-Id: I4d7af36937946dd58d52aaafae4dd48a60c00cf0 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QSemaphore: fix Coverity warning about uninit'ed fieldMarc Mutz2025-08-011-1/+1
| | | | | | | | | | | | | | | The m_n member is not read in normal operation when m_sem is nullptr, but since move-assignment to the default-constructed object (a valid operation even on partially-formed states) reads this value uninitialized as part of the move-and-swap, we need it initialized, because otherwise it's UB. Amends f0ee4ed0a28d274c7a8efeb9e6ac8642e020e2cc. Coverity-Id: 483737 Pick-to: 6.10 6.9 6.8 6.5 Change-Id: Ifd200877cef693110832675b6e172bc083372d4f Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Make files under thread and time prefix compilableOleksii Zbykovskyi2025-07-291-0/+5
| | | | | | | | Make these file compilable and add to the build system. Task-number: QTBUG-137566 Change-Id: I3edf8204428a1e619fe5049e5d46ae51c6900002 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* QAbstractEventDispatcher: don't recreate QThreadData if it is goneThiago Macieira2025-07-161-0/+1
| | | | | | | | | | | | | | | | | | | | | | Since QAbstractEventDispatcher is a QObject, the base class construction will necessarily have created a QThreadData, if one didn't exist yet. Normally, this means the QThreadData reference count shouldn't have gone down to zero if the dispatcher still exists. However, the thread-local pointer in qthread_{unix,cpp}.cpp may have already been reset, even if we haven't reached a zero count. This commit makes it so we don't recreate the QThreadData under those conditions. It's also a minor performance optimization, by suppressing the need to call QThreadData::createCurrentThreadData(). It may additionally fix some issues with calling pthread_setspecific() / TlsSetValue() in very late thread execution. Task-number: QTBUG-137130 Task-number: QTBUG-136629 Pick-to: 6.10 6.9 6.8 Change-Id: Ie88d88cfaa5330cdca79fffded47ecb2bb4113c1 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* QBasicTimer: avoid recreating the thread's QThreadData if it's goneThiago Macieira2025-07-161-0/+1
| | | | | | | | | | | | | | | | | | | | We know it existed at some point because this timer is active, meaning an event dispatcher did exist. So if it and the event dispatcher have already been destroyed, don't recreate the QThreadData: there will be no dispatcher there anyway. That helps fixing some problems with set_thread_data() → pthread_setspecific() / TlsSetValue() during very late thread execution. This complements c8d3d7a7af73d97e0415b99df8d8378edb3117f5, which ensured that we didn't attempt to call unregisterTimer() on a partially- or fully-destroyed event dispatcher. Task-number: QTBUG-137130 Task-number: QTBUG-136629 Pick-to: 6.10 6.9 6.8 Change-Id: Id24ac8b3452d2c459136fffd5b3ecf23cf87e7d1 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Doc: Remove deadlock warnings in most QMutex documentationKai Köhne2025-07-071-17/+2
| | | | | | | | | | | | | | | | | The origin of this sentence predates the Qt 5 history. Anyhow, as is, the sentence is too general, as locking the same mutex over time from the same thread is definitely supported, as long as it is also unlocked every time. Furthermore, for the tryLock() variants, the thread will only dead-lock if an infinite wait time is specified. Improve the sentence for QMutex::lock(), but just leave out this information for the other methods. The behavior is arguably as you would expect it from a mutex. Pick-to: 6.9 6.10 Change-Id: I0b658cc29c2f2d2cd6b59d49e2baa285508ec720 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* qatomicwait: disable the code for systems with permanent futex supportThiago Macieira2025-07-041-0/+14
| | | | | | | This saves some code emission and the 2kB of .bss space for the locks. Change-Id: Icf6a9c0091b86d6e223afffdb4acede2c2f930f5 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* QLatch: optimize to avoid a syscall when no one is waitingThiago Macieira2025-06-272-3/+37
| | | | | | | | | | | | | | | | | | | | | | | | We do it by using the sign bit of the atomic to indicate that there are no waiters waiting. That way, the counter only becomes a zero when all expected counters have counted down *and* there is at least one waiter. That means the countDown() code remains unchanged. On x86-64 and AArch64, there is no change in the number of instructions in the inline portion of wait() either. The non-inline portion uses a __atomic_and_fetch() instead of atomic_fetch_and() so compilers will generate LOCK AND for x86-64, LDCLR for AArch64 ARMv8.1, and AMOAND.W for RISC-V. This is more efficient than the Standard Libraries's current implementations, which use a separate, global atomic out of a pool, meaning that there could be a collision between two or more latches (or any other users std::atomic waiting, such as std::semaphore and std::barrier). Coupled with the fact that we futexWait() on the actual latch's address (something libc++ can't / won't do), this implementation should be overall much more efficient. Change-Id: Ib5ce7a497e034ebabb2cfffd1761b02a44d548d3 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* Long live QLatchThiago Macieira2025-06-273-0/+302
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Like std::latch[1][2]. Originally proposed by N3666, it only became a reality after the atomic wait functionality in C++20. We can't depend on that yet in Qt because a) we don't depend on C++20 yet, and b) the implementations of atomic waiting and std::latch are too recent in the Standard Library implementations (GCC 12, LLVM 12, MSVC 19.28). This implementation therefore builds the functionality from scratch, like the original proposal did[3]. We'll probably keep our implementation for the long run, because it's more efficient than the Standard Libraries' implementations. The MS STL implementation is the closest to ours and to bare OS functionality: uses WaitOnAddress / WakeByAddress as expected, but it generates a bit more code than is necessary. And it's Windows-specific, of course. Both cross-platform implementations (libstdc++ and libc++) do far more work than necessary for platforms that offer a OS futex-like support. Both of them busy-loop waiting for the atomic value to change and then exponentially back off using sched_yield(). Those aren't useful to us, as the majority of our uses are with threads that have just been created and have therefore likely made little progress. They can be actively harmful in some cases. The libc++ implementation is even worse by using std::high_resolution_clock to time this looping up to 64 µs in inline code before making a system call to sleep and wait (and it can't / won't use the latch's address for the futex itself). Both implementations also use an extra atomic out of a global pool (16 in libstdc++, 256 in libc++) to indicate whether there is any waiter on this address and therefore avoid the system call to wake them. See the next commit for an efficient implementation for QLatch. This implementation uses the limited atomic-wait functionality added by the previous commit for platforms that don't support futexes. [1] https://wg21.link/p1135 [2] https://en.cppreference.com/w/cpp/thread/latch/latch [3] https://github.com/ogiroux/atomic_wait/tree/master/include Change-Id: Ib5ce7a497e034ebabb2cfffd1761a3a6ff2598d3 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Short live q20::atomic_wait!Thiago Macieira2025-06-272-0/+248
| | | | | | | | | | | | | | | | | | | atomic_wait() and atomic_notify_{one,all}() are available in C++20, which we can't depend on right now. So we implement our own fallback implementation. This is a simple implementation for systems which don't have either futexes or the C++20 atomic wait API. That means it's not very efficient, just simple. The unit test tests the fallback implementation only: it is not Qt's business to test the Standard Library. The fallback implementation and the Standard Library's are not binary-compatible and cannot be mixed. Callers must ensure that all sides use the same implementation and the easiest way to do that is to only use this in non-inline code, or at worst inline code that isn't shared across libraries/modules/plugins. Change-Id: Ib5ce7a497e034ebabb2cfffd1761a0e497dd17d4 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* no-thread: enable using QFutureMorten Sørvig2025-06-245-6/+39
| | | | | | | | | | | | | | | | | | | | | | | | Enable using QFuture for handling async tasks, which is a use case which can work also for the no-thread configuration. Add implementation files and headers for the QFuture dependencies to the no-thread build. These files build, but as with no-thread QThread there is no guarantee that they will do anything useful. Stub out some more functions in QThread, and also add stubs for no-op QSemaphore. Enable the tst_qfuture test and skip tests which require threads. tst_qfuture now runs with: Totals: 70 passed, 0 failed, 13 skipped, 0 blacklisted, 6373ms Pick-to: 6.10 Change-Id: Icd82590915d6034ae7829ead3fb4ebaf1e9c2aad Reviewed-by: Tim Blechmann <tim.blechmann@qt.io> Reviewed-by: Artem Dyomin <artem.dyomin@qt.io>
* Doc: Fix self-linking "see also" linkDavid Boddie2025-06-181-1/+1
| | | | | | Pick-to: 6.9 6.10 Change-Id: I23647451fd26c4e9aa16f2287429af6f57f17bf1 Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
* Q*Mutex: unexport for Qt 7Thiago Macieira2025-06-121-3/+11
| | | | | | | | Those weren't caught for the Qt 6.0 release. Pick-to: 6.10 Change-Id: I5831d4ad80b7f60d8782fffd6c64ef552f82ad6e Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QBasicMutex: bring back fastTryUnlock for MSVCThiago Macieira2025-06-121-0/+5
| | | | | | | | | | | | | | | | | MSVC exports inline functions, so we're not allowed to remove them. This is an unlikely problem, though, since it was only called from other inline functions: if the compiler was inlining content into user code (as it should), then it would likely have inlined this one too; if instead the inliner was disabled, then it wouldn't have inlined the caller either. Amends commit 1957597aa6bc6ebd8bd1f903389800897411ac5d. Seen in API review. Pick-to: 6.10 Task-number: QTBUG-137478 Change-Id: Idd01170c3396c5b6fefefffd748f3335fc42fd79 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QAbstractEventDispatcher: prevent too late unregistering of timersThiago Macieira2025-05-251-1/+1
| | | | | | | | | | | | | | | | | | | | | Timers can't unregister when the dispatcher object is no longer of a dispatcher type. It's too late even at ~QAbstractEventDispatcher, because unregisterTimer() is a pure virtual. To prevent their attempting to unregister, we set the thread's dispatcher to nullptr if it is this object. This has been a latent bug, so it's worth fixing. This started happening for me with an un-pushed change that changed the order of how QCoreApplication and QGuiApplication destroy the main thread event dispatcher (namely, in their destructors, not waiting for ~QObject to deleteChildren()). Drive-by relax the store in QThread::setEventDispatcher(). Fixes: QTBUG-137130 Pick-to: 6.9 6.8 Change-Id: I8845736c38a931af62e3fffdfd3554874df89e8e Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* QThread/Unix: fix silly mistake: static was missing after refactoringThiago Macieira2025-05-251-1/+1
| | | | | | | | | | | | | | | | | | | | | | Amends commit 6763e25cbc16cf8c54ab9b1ef97030aab9bb0eec, which refactored static struct Cleanup { to move the body if said cleaning up closer to the rest of the clean up code in QThreadDataDestroyer::EarlyMainThread. But it accidentally forgot the static keyword. As a result, we attempted to clean up before ::currentThreadData was set yet, resulting in a no-op and no clean up. Task-number: QTBUG-135044 Task-number: QTBUG-134080 Task-number: QTBUG-133861 Task-number: QTBUG-132697 Task-number: QTBUG-102984 Task-number: QTBUG-132381 Pick-to: 6.9 6.8 Change-Id: Ibe40567bba8dea205401fffdb71f7e6a3be130e4 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> (cherry picked from commit b5e47fa433f218a47db98a370fbad97c70455e85) Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* QLibrary/Darwin: don't use RTLD_NODELETE, just don't dlclose()Thiago Macieira2025-05-251-6/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | As the comment says, the OS does support the flag and a perusal of the source code for dyld[1] shows it does handle the flag, setting an internal flag called "leaveMapped", which is different from the "neverUnload" flag. My guess is that it literally just leaves the memory for the plugin mapped, but removes all links to it in the dyld internal data structures. That results in the Objective C runtime crashing when running content from NODELETE plugins that has been dlclose()d. This probably explains why lldb stops seeing those symbols too: (lldb) f frame #0: 0x0000000103872eb4 QtCore`QLibraryPrivate::unload_sys(this=0x000060000179c210) at qlibrary_unix.cpp:258:21 -> 258 if (doTryUnload && dlclose(pHnd.loadAcquire())) { (lldb) target modules list libqcocoa.dylib [ 0] 81EB58D5-8D31-333A-9E8C-F2385F6EFCF4 0x00000001043de000 libqcocoa.dylib (lldb) image lookup -vn QCocoaEventDispatcher::QCocoaEventDispatcher 2 matches found in libqcocoa.dylib: Address: libqcocoa.dylib[0x0000000000036480] (libqcocoa.dylib.__TEXT.__text + 190368) Summary: libqcocoa.dylib`QCocoaEventDispatcher::QCocoaEventDispatcher(QObject*) at qcocoaeventdispatcher.mm:776 ... (lldb) n (lldb) target modules list libqcocoa.dylib [ 0] 81EB58D5-8D31-333A-9E8C-F2385F6EFCF4 libqcocoa.dylib[0x0000000000000000] libqcocoa.dylib (lldb) image lookup -vn QCocoaEventDispatcher::QCocoaEventDispatcher [1] https://github.com/apple-oss-distributions/dyld Task-number: QTBUG-135044 Task-number: QTBUG-134080 Task-number: QTBUG-133861 Task-number: QTBUG-132697 Task-number: QTBUG-102984 Task-number: QTBUG-132381 Pick-to: 6.9 6.9.0 6.8 Change-Id: I7da3b3615a6ace7c72d1fffd5cf560d8f8a4e1bb Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
* Remove VxWorks DKM check from QThreadsKarim Pinter2025-05-151-1/+1
| | | | | | | | | | Qt doesn't support VxWorks DKM since 4.8, removing DKM specific check, so it is the same as in Qt for VxWorks 5.15. Pick-to: 6.8 6.9 Task-number: QTBUG-136722 Change-Id: I86cf54e8eadbb78365b7c58cb72b0675714fb37a Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Clarify QFuture::isValid() docsIvan Solovev2025-05-141-2/+8
| | | | | | | | | | | | It was not clear that the function will return true even when the result is not yet ready, so mention it explicitly. Amends 44ceb56455c82df3e6b1c9a2fa373cac14a039f8. Fixes: QTBUG-136530 Pick-to: 6.9 6.8 6.5 Change-Id: I03b79f2b28c4bb755e6f56147cc7af1413ed4e57 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* Replace uses of std::is_trivial with its underlying definitionsThiago Macieira2025-05-081-1/+2
| | | | | | | | | | | | | C++26 deprecated it[1]. Like the paper, we don't need the trivial default constructibility for most uses. Even some of the QTypeInfo::isComplex checks don't need it. [1] https://wg21.link/p3247 Pick-to: 6.9 6.8 6.5 Fixes: QTBUG-136083 Change-Id: I0caafc5a15df732b9640fffd72fb1c598563a91b Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* QThreadStorage: make the internal finish() function really privateThiago Macieira2025-04-115-8/+5
| | | | | | | | | | | | | | | This class is very old and hasn't been modernized since C++98 became a thing we could rely on. We hadn't come up with the concept of private headers yet. This commit moves the exported QThreadStorageData::finish() function from the public header to QThreadStoragePrivate in a private header and no longer exports it. It also removes the need to pass the QList as a void **. Task-number: QTBUG-135044 Change-Id: I736cb12a7c29716effd7fffd87c7b086a8cb7e19 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* QThreadStorage: ensure global static exists when finish() is calledThiago Macieira2025-04-115-5/+45
| | | | | | | | | | | | | For the thread that calls ::exit() (usually, the main thread). Otherwise, depending on construction order, it is possible for the QThreadStorage's destructor list to have been destroyed by the time destroy_current_thread_data() → QThreadData::finish() calls our finish(). Fixes: QTBUG-135044 Pick-to: 6.9 6.8 Change-Id: Ic5a10367ff31e7faa039fffdc2067eba9642fbf9 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* QThread: explicitly clear posted events during destructionVolker Hilsheimer2025-04-112-4/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | So far, we have been destroying pending posted events during thread shutdown only as part of ~QThreadData. QThreadData is reference counted, and ~QThreadPrivate releases the reference count. However, any QObject living in a thread also holds a reference to the QThreadData. If any of those objects are only destroyed when a posted event is processed, then we have a cyclic reference problem. This might be a problem with DeferredDelete events that are posted after a QThread has exited its event loop. It does manifest as a problem with QSingleShotTimer, which is temporarily owned by a posted event object. As long as that event object is in the queue, the reference count of QThreadData never drops to zero as the QSST instance holds a reference. So the event never gets destroyed, and we end up leaking both. To fix this, explicitly clear all pending posted events during QThread destruction as well, not only during QThreadData destruction. Once the QThread is destroyed, nothing will process those events. We still clear the posted events during QThreadData destruction, as QThreadData might get destroyed when other objects release their reference count on it. This fixes a somewhat contrived problem in our test scenario, and the change is not without risk, so not cherry-picking this to any stable branch. Change-Id: I488c1d3137ce83f1c34596e1041c22759825be18 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QReadWriteLock: add qYieldCpu() calls to the contended loop acquisitionsThiago Macieira2025-04-091-0/+2
| | | | | | | | | We're looping on fastTryLock() (which does testAndSetAcquire()) and a few other testAndSet()s, so we should yield the CPU between calls. Change-Id: I6ba01efc9142f8be2bf1fffddf06c027dde18016 Reviewed-by: David Faure <david.faure@kdab.com>
* QReadWriteLock: extract method fastTryLockDavid Faure2025-04-101-10/+16
| | | | | | | | | This removes a little bit of duplication, and reduces the temptation to remove the first part of tryLockForX as duplicated (it should remain there for performance reasons). Change-Id: I7ce102ceeb03b5ab4fe026b56fbba245b4c2f310 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QReadWriteLock: fix data race on the d_ptr membersDavid Faure2025-04-081-2/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | Testcase: ./tst_qreadwritelock countingTest WARNING: ThreadSanitizer: data race (pid=356186) Read of size 1 at 0x7294000000f8 by thread T12: #0 contendedTryLockForRead qtbase/src/corelib/thread/qreadwritelock.cpp:230 (libQt6Core_tsan.so.6+0x6c3743) #1 QReadWriteLock::tryLockForRead(QDeadlineTimer) qtbase/src/corelib/thread/qreadwritelock.cpp:190 (libQt6Core_tsan.so.6+0x6c347b) #2 QReadWriteLock::lockForRead() qtbase/src/corelib/thread/qreadwritelock.h:68 (tst_qreadwritelock+0xb0f0) #3 ReadLockCountThread::run() qtbase/tests/auto/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp:597 (tst_qreadwritelock+0xc506) Previous write of size 8 at 0x7294000000f8 by thread T2: #0 operator new[](unsigned long, std::align_val_t) <null> (libtsan.so.2+0xa78eb) #1 allocate qtbase/src/corelib/tools/qfreelist_p.h:135 (libQt6Core_tsan.so.6+0x6c6079) #2 next qtbase/src/corelib/tools/qfreelist_p.h:212 (libQt6Core_tsan.so.6+0x6c5915) #3 QReadWriteLockPrivate::allocate() qtbase/src/corelib/thread/qreadwritelock.cpp:564 (libQt6Core_tsan.so.6+0x6c5354) #4 contendedTryLockForRead qtbase/src/corelib/thread/qreadwritelock.cpp:218 (libQt6Core_tsan.so.6+0x6c364f) The loadRelaxed() at the beginning of tryLockForRead/tryLockForWrite isn't enough to bring us the non-atomic write of the recursive bool. Same issue with the std::mutex itself. Pick-to: 6.9 6.8 6.5 Change-Id: I6f5e371cf94292b643cb36041d1406b19d22cdbe Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QThread/Doc: improve docs on running, finished, and the OS threadThiago Macieira2025-03-291-0/+21
| | | | | | | | | | | | | And take the opportunity to explain that the finished() signal does not indicate the end of the operating system thread. Indeed, on some OSes, not even wait() can be sure of that: for Unix systems, see the docs at the top of qthread_unix.cpp about timed pthread_joins. Pick-to: 6.9 6.8 Fixes: QTBUG-135163 Change-Id: Ie00a742f0707f57c767bfffd44bdaec40df05e4a Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Andreas Eliasson <andreas.eliasson@qt.io>
* Shuffle Q_(ALWAYS|NEVER)_INLINE around so they can be attributesMårten Nordheim2025-03-281-1/+2
| | | | | | | The attribute must appear before the modifiers like 'inline' and 'constexpr'. Change-Id: If3d143fc2f85a8eba6e3ac2ceca10720649f33cb Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Warn if QFuture::then() is called for a QFuture with multiple resultsIvan Solovev2025-03-242-0/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | QFuture is tricky in the sense that it can store multiple results. The users might write the code like: QList<int> values{1, 2, 3}; auto f = QtConcurrent::mapped(values, func) .then([](auto val) { otherFunc(val); }); with the expectation that the lambda will be called on each mapped value of the original input container. However, that is not true. QtConcurrent::mapped() returns a QFuture which has multiple results, and in this case only the first result will be passed to the then() continuation. We cannot detect this problem at compile-time, because we do not know how many results will the QFuture hold. So, add at least a runtime warning. The warning is added in a new logging category, so that the users who really need this behavior can disable it. The warning is implemented as an exported out-of-line method for two reasons: * To avoid code duplication for each template parameter of CompactContinuation. * To avoid exposing a Qt-specific logging category into a public header. Such design, however, prevents us from cherry-picking the change to older branches. Fixes: QTBUG-133522 Change-Id: I3344b5228b50e9c9d68d0c57961bbc969f566bb9 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* docs: Clarify adding a continuation to a QFuture with multiple resultsIvan Solovev2025-03-241-0/+5
| | | | | | | | | | | | | Explain that the continuation should take QFuture<T> as a parameter in order to be able to access all results. Add notes with examples to the QtConcurrent::mapped and QtConcurrent::filtered overviews. Task-number: QTBUG-133522 Pick-to: 6.9 6.8 6.5 Change-Id: I65655aadc8d4623b147d22a9bf9b2189c80b14c5 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* Fix usage of API functions on Windows 1607 (Build 14393)Lars Schmertmann2025-03-151-0/+14
| | | | | | | | | | | | | | | | * Windows Server 2016, Windows 10 LTSB 2016 and Windows 10 version 1607: SetThreadDescription is only available by Run Time Dynamic Linking in KernelBase.dll. See [1]. * According to [2] UiaRaiseNotificationEvent should be available on Windows Server 2016 but in fact it is not. [1] https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription [2] https://learn.microsoft.com/de-de/windows/win32/api/uiautomationcoreapi/nf-uiautomationcoreapi-uiaraisenotificationevent Fixes: QTBUG-134075 Pick-to: 6.8 6.8.3 6.9 6.9.0 Change-Id: I3c4c733a4112a72b75f91f017a278dff2454e100 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>