We so far refetched the first observer after evaluating bindings, as
binding evaluating might change the list of observers.
However, that approach did not take into account that the 'this' pointer
might no longer be valid after binding evaluation: In case of a
QObjectBindableProperty (or a QObjectCompatProperty), binding evaluation
might cause a reallocation of the binding storage, and consequently the
invalidation of the QPropertyBindingData.
Fix this by refetching the QPropertyBindingData from the storage (if a
storage has been provided, which is always the case for the affected
classes).
Fixes: QTBUG-111268
Pick-to: 6.5 6.4 6.2
Change-Id: Ie7e143a0bbb18f1c3f88a81dd9b31e6af463584f
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
A RAII wrapper around Qt::{begin,end}PropertyUpdateGroup().
[ChangeLog][QtCore][QScopedPropertyUpdateGroup] New RAII class
wrapping Qt::beginPropertyUpdateGroup() and
Qt::endPropertyUpdateGroup().
Fixes: QTBUG-110710
Change-Id: If2619e9584dd9d57985d63e3babca75421499ab9
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Grouped property updates have been ported to make use of the
non-recursive variant, and thus the last remaining user of recursive
notify() is gone.
Change-Id: I617db0dedc66555152a9b43514d9d8658d528f2c
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This fixes a use-after-free in QPropertyDelayedNotifications::notify.
Before this patch, evaluateBindings or a notify from a property index
might have caused the originalBindingData to become reallocated.
However, at that point, we've already restored the original bindingData
in evaluateBindings, so we won't track updates, and thus won't adjust
originalBindingStatus, which will then point to already freed data.
To remedy this, we no longer do the notification with data fetched from
originalBindingData, but instead use the information we have in the
proxyData.
We also need to enure that referenced bindings do not get deleted; for
that we keep the PendingBindingObserverList alive for the whole duration
of the endPropertyUpdateGroup.
As we now have the PendingBindingObserverList, we use it for the
notification logic, and only notify change handlers in
QPropertyDelayedNotifications::notify. That will allow a follow-up
cleanup of QPropertyObserverPointer::notify, and aligns the logic for
grouped updates with the logic for "nornal", non-grouped updates.
Amends f1b1773d0a.
Task-number: QTBUG-110899
Pick-to: 6.5 6.4 6.2
Change-Id: Iae826e620d9614b7df39d86d8a28c48c8a5c4881
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
That use case for the class never materialized, and it was actually
meant for internal use. However, we put it into the public header, so
we cannot remove it (and while undocumented, someone actually used it at
some point, compare e4d62651c2).
Mark it as deprecated instead so that it can be finally be removed in Qt
7.
Change-Id: I058c5831a44610121fbec6eaddebd8b33d4a16c9
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This addresses two different issues:
- Firstly, we were casting the resolved binding data pointer to
QPropertyProxyBindingData, instead of the d_ptr of
QPropertyBindingData. Fix this by introducing a helper function,
and consistently using it to access the proxy data.
- Secondly, we were not resetting the originalBindingData when the
pointed to object was destoyed. Fix that, too.
Pick-to: 6.5 6.4 6.2
Task-number: QTBUG-110899
Change-Id: I7691c9df5cc26e761f6b0e5f16d152f7f2183208
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Easier to read, saying in one line that for which the old code needed
three.
Task-number: QTBUG-110710
Change-Id: Ie2a1d11aefe0bdf5f4db0694832fce669de564fc
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
decltype(QPropertyDelayedNotifications::used) is qsizetype, not int,
so don't use int to count from 0...used. The notify() and
evaluateBinding() functions use their int argument only for pointer
arithmetic, so this is completely self-contained.
Amends fdedcb6ec6.
Pick-to: 6.5 6.4 6.2
Task-number: QTBUG-103532
Task-number: QTBUG-110710
Change-Id: I765a06628d330fbb57a2fbecc96d66690bb62f13
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
"src/corelib/kernel/qproperty.cpp" documents assignment operators over
`QPropertyBinding` for `QProperty` and `QPropertyAlias`.
Those operators were removed in 638df6138e
and are thus stale.
Similarly, an assignment operator for `QPropertyAlias<T>` over a `T&&`
is documented albeit it was removed in
927647cd03.
Due an incorrect implementation of QDoc, which has now been removed,
with regards to identifying copy/move assignment operators, and the more
superficial and incorrect way in which QDoc binds those kind of elements
to the clang AST, QDoc was unable to report the lack of a binding
declaration for those elements that were removed, producing incorrect
documentation instead.
As of the latest changes to QDoc this will correctly generate a warning.
To avoid the addition of new warnings and remove stale and incorrect
documentation, the document blocks were removed from the file.
Change-Id: I30e20f26d4c44e4589abf40546d8ebaa4e869638
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Implements an adaptor from the notification signal of a Q_PROPERTY to
QBindable. The Q_PROPERTY does not need to be BINDABLE, but can still
be bound or used in a binding.
[ChangeLog][Core][Q_PROPERTY] Q_PROPERTYs without BINDABLE can be wrapped in QBindable to make them usable in bindings
Change-Id: Id0ca5444b93a371ba8720a38f3607925d393d98a
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Amends cf42a0fe5e.
As a drive-by, reflow the documentation, and mark some code segments
with \c
Change-Id: Id644e841f9990dd7aec2d7ce74efad8b4472b93a
Reviewed-by: Paul Wicking <paul.wicking@qt.io>
qExchange is one of the few remaining functionalities that have not been
moved out of qglobal. Given that std::exchange exists in the standard, we
can simply move to it everywhere...
...if it weren't for the fact that std::exchange is only constexpr in
C++20, and only has its noexceptness specified in (most likely) C++23.
Still, we want to move to the existing std functionality where
possible, to allow the removal of qglobal includes in lieu of something
more fine-grained in the future.
So leave any constexpr calls[1] alone for now (and observe that none of
our current usages cares about the conditional noexceptness), but
replace everything else.
[1] QScopedValueRollback' ctor and QExplicitlySharedDataPointerV2::take
Task-number: QTBUG-99313
Change-Id: I599cb9846cf319c7ffd3457130938347a75aad25
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
https://developercommunity.visualstudio.com/t/C:-constinit-for-an-optional-fails-if-/1406069
does not only affect constinit thread_local but also constinit in
general on MSVC compilers when C++20 is being used. So disable the
feature for these compilers in general for now.
This commit amends d9531593a2
Fixes: QTBUG-105234
Pick-to: 6.4
Change-Id: I1855f0857d85487895460fc7c56675fb864bfa73
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Previously, we were storing all binding-observers in a list, so that we
can later revisit them during the notification loop.
However, there is no point in doing that when the binding did not
actually change.
Pick-to: 6.4
Change-Id: I0b3343cc442eca2586c7c6a10c31d780f04730e6
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Problem description:
--------------------
Assume we have two properties, P1 and P2. Assume further that we assign
a binding to P2, so that it depends on P1. Let the binding additionally
capture some (non-QProperty) boolean, and only create the dependency to
P1 if the boolean is true.
The state afterwards is
P1:[p1vaue|firstObserver]
|
|
v
---[p2binding]
/
P2:[p2value|binding]
If the boolean is set to false, and P1 changes its value, we still
correctly re-evaluate the binding and update P2's value. However, during
binding evaluation we will notice that there is no further dependency
from P2 on P1, and remove its observer.
The state afterwards is
P1:[p1vaue|firstObserver=nullptr]
---[p2binding]
/
P2:[p2value|binding]
Then, during the notify phase, we traverse the observer's again,
starting from P1's firstObserver. Given that it is nullptr now, we never
reach P2's binding, and thus won't send a notification from it.
Fix:
----
We store a list of all visited binding-observers (in a QVarLengthArray,
to avoid allocations as long as possible). After the binding evaluation
phase, we then use that list to send notifications from every binding
that we visited. As we already have a list of all bindings, we no longer
need to recurse on binding-observes during the notification process;
instead, we only need to deal with static callbacks and ChangeHandlers.
The pre-existing notification logic is still kept for the grouped update
case, where we already have a list of all delayed properties, and should
therefore not encounter the same issue. Unifying its codepath with the
existing logic is left as an exercise for a later patch.
Fixes: QTBUG-105204
Task-number: QTBUG-104982
Pick-to: 6.4 6.3 6.2
Change-Id: I2951f7d9597f4da0b8560a64dfb834f7ad86e757
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Sami Shalayel <sami.shalayel@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Details: Added a note on how QProperty works in QML using BINDABLE keyword
Task-number: QTBUG-89166
Change-Id: Ib48dd26b0724f906efa65d14fbb75a8b97255b05
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Set it to nullptr on clear, and deal with possibly null bindingStatus.
Task-number: QTBUG-101177
Task-number: QTBUG-102403
Pick-to: 6.4
Change-Id: I66cb4d505a4f7b377dc90b45ac13834fca19d399
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Manipulating owning containers is costly at runtime, but also at
compile-time, so don't do it in inline functions, do it
out-of-line.
Removes the top-2 entries[1] in a Clang -ftime-trace QtWidget build.
[1] at the time of writing of this patch
Change-Id: I5da5030788b0d976a0ab7875f87ba3b51dbb1231
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Replace the current license disclaimer in files by
a SPDX-License-Identifier.
Files that have to be modified by hand are modified.
License files are organized under LICENSES directory.
Task-number: QTBUG-67283
Change-Id: Id880c92784c40f3bbde861c0d93f58151c18b9f1
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
MSVC 19 does not allow using constinit on thread_local objects of
non-trivial type:
https://developercommunity.visualstudio.com/t/C:-constinit-for-an-optional-fails-if-/1406069
Instead of revoking Q_CONSTINIT for that compiler or removing
Q_CONSTINIT from such variables, add a new macro for this situation,
so the constinit static assertion will still be checked on other
platforms.
Amends 32692667a6.
Change-Id: Ic2247768b0d64e0c01648cffc9532fe5bd4bbd5d
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Still not complete. Just grepping for static and thread_local.
Task-number: QTBUG-100486
Change-Id: I90ca14e8db3a95590ecde5f89924cf6fcc9755a3
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
QObject's cache the binding status pointer to avoid TLS lookups.
However, when an object is moved to a different thread, we need to
update the cached pointer (as the original thread might stop and thus no
longer exist, and to correctly allow setting up bindings in the object's
thread).
Fix this by also storing the binding status in QThreadPrivate and
updating the object's binding status when moved. This does only work
when the thread is already running, though. If it is not running, we
instead treat the QThreadPrivate's status pointer as a pointer to a
vector of pending objects. Once the QThread has been started, we check
if there are pending objects, and update them at this point.
Pick-to: 6.2 6.3
Fixes: QTBUG-101177
Change-Id: I0490bbbdc1a17cb5f85044ad6eb2e1a8c759d4b7
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
One of them has managed to percolate up to the top of the Clang
-ftime-trace list of expensive template instantiations when building
libQt6Gui.so with -pch:
**** Templates that took longest to instantiate:
7882 ms: std::is_trivially_destructible<QPropertyBindingSourceLocation> (135 times, avg 58 ms)
The checks aren't really necessary, because the compiler would
complain about the union's deleted dtor if any of the members were not
trivially destructible. Keep it around, though, but in the .cpp file.
Task-number: QTBUG-97601
Pick-to: 6.3 6.2
Change-Id: I74a513a907735bde298e0bd9557d10abbcee5c91
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
`Q_OBJECT_COMPUTED_PROPERTY` is a macro that is used to declare a
`QObjectComputedProperty`.
The documentation for the macro was related to the
`QObjectCompatProperty` documentation, which is internal.
A link to `Q_OBJECT_COMPUTED_PROPERTY` appears in
`QObjectComputedProperty`'s page, but fails to resolve as the required
documentation page is internal.
Furthermore, `QObjectCompatProperty` has a macro that is equivalent to
`Q_OBJECT_COMPUTED_PROPERTY`, `Q_OBJECT_COMPAT_PROPERTY`, whose
documentation is declared related to `QObjectCompatProperty`.
It is hence assumed that relating the documentation for
`Q_OBJECT_COMPUTED_PROPERTY` to `QObjectCompatProperty` was a typo, such
that the documentation for the macro is now moved to be related to
`QObjectComputedProperty`, resolving the linking issue in the process.
Task-number: QTBUG-96127
Pick-to: 6.2
Change-Id: I2c1bfd6ba64f13e186c65701593047b64bf0c199
Reviewed-by: Paul Wicking <paul.wicking@qt.io>
Reviewed-by: Andreas Buhr <andreas.buhr@qt.io>
The only non-inline function of that class was observerCount() which
would use two of the inline functions defined in the header file, so
we can safely inline observerCount() and make the whole class contain
only inline methods
Consequently, inline class doesn't have to be exported in Windows
Change-Id: I41d144d9a50420bbc0091992b36cc36ac2567704
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Extend the general property system page with a section on how
to use bindable properties.
Add some cross-references to improve the user experience.
Task-number: QTBUG-97656
Pick-to: 6.2
Change-Id: I2520cdc168e3a8a66ea387e4ab717f4e0f969424
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
This patch amends 89a4c8d40d.
It moves the code sample into a separate snippet file, which allows us
to use Q_OBJECT macro in it without complaints from moc.
Task-number: QTBUG-97656
Pick-to: 6.2
Change-Id: I368d8dd8c00dbbebd8a6bf3788be796c8ca4bce8
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
QObjectComputedProperty belongs to public API. It's even referred in
other documentation (for example, QBindable).
It does not make sense to have its documentation marked as \internal.
Task-number: QTBUG-97656
Pick-to: 6.2
Change-Id: I6ca81292cfafea873dd3577fb0e5ddb583969dc3
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Most compilers are clever enough to optimize this out. Yet, even with
optimizations disabled, we don't want to do two TLS lookups here.
Change-Id: I822954c7cec591084d6c27c916818dab7e000ea9
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Do the check for inBindingWrapper() last.
Change-Id: I3d589c9fba524f465e35cd4cc0e65e3af376b419
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This is necessary to optimize QObjectCompatProperty::notify in a second
step.
Change-Id: I89aaf51d39e04f17285f7db27f9b40d145fd846d
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
\relates takes a class name as argument, but doesn't deal nicely
with a templates full definition.
Pick-to: 6.2
Task-number: QTBUG-97028
Change-Id: I7c608717c5d552bc553073534104dece01b8ff96
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Topi Reiniö <topi.reinio@qt.io>
* Tag deprecated Q(Multi)Map operators in the header to correctly
match them with documentation \fn commands.
* Add documentation for QByteArrayView comparison operators.
* Add a dummy typedef 'jfieldID' for generating docs correctly
on non-Android platforms
* Fix other minor issues
Pick-to: 6.2
Task-number: QTBUG-95860
Change-Id: I141d2f75d6aa10557aa374201f09ad74b4cd6e81
Reviewed-by: Paul Wicking <paul.wicking@qt.io>
As QPropertyAlias was public by accident in 6.0, we have to ensure that
it still works in 6.2.
This re-adds some tests for it, and reimplements the unlinking
functionality. To avoid performance regressions in hot-paths,
a new unlink_fast function is added, which behaves like the old unlink:
It ignores the special handling for QPropertyAlias, so that we can skip
the tag check. It is only used in QPropertyObserverNodeProtector and
clearDependencyObservers, where we already know the type of the
observer.
Fixes: QTBUG-95846
Pick-to: 6.2
Change-Id: Ifb405b8327c4d61c673b1a912ed6e169d27c2d8f
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
We will not gain anything if we have to do multiple function calls to
obtain the thread id. Therefore we introduce a macro to signal that we
have a fast implementation of currentThreadId, and only use the function
if it is defined.
Pick-to: 6.2
Change-Id: I3347489ea91992896bb753b796ae26e391c2c99c
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
If we already have the bindingStatus, we can just pass it along.
Pick-to: 6.2
Change-Id: Iaaea4f4c34e6a786899561293016ece163c26d25
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
- Provide an inline version of evaluateRecursive which does not fetch the
status.
- Provide an unsafe variant of setBindingToNotify which does not set the
tag. This can be used in allocateDependencyObserver, as newly
allocated observers already have the correct tag (this is checked via
an assert).
Pick-to: 6.2
Change-Id: I31aec6af4aef244efc6d0777e5bfaaa8f82f2046
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This avoids another round of TLS lookups in evaluateRecursive when we
construct the BindingEvaluationState.
Pick-to: 6.2
Change-Id: Icfa9fd81fc6f54623d384c4d3fce33f4d4d549b9
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
- Ensure that the allocateDependencyObserver fast path is inlined.
- Use addObserver instead of observerProperty; we know that a freshly
allocated observer does not have its prev pointer set. If prev weren't
a private member, we could simply use Q_ASSUME(ptr->prev == nullptr),
but making it public or befriending the class seems like a bad idea,
as it grants too much access to the internals.
Pick-to: 6.2
Change-Id: Ia845f2807c70512563f7b9e1ecb85fe82b66208c
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
If we have no currentBinding, then registerWithCurrentlyEvaluatingBinding
will not do anything. Thus we can completely avoid fetching the storage.
Pick-to: 6.2
Change-Id: Ic20142e4c4e09752b5c41b959f66080e6885e6c3
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
By putting the groupUpdateData pointer into the same thread local as the
binding status, we avoid having to fetch two thread_local variables.
Moreover, we can reuse the caching mechanism which we have in place for
QBindingStatus to avoid costly TLS lookups.
Pick-to: 6.2
Change-Id: Iaea515763510daab83f89b8e74f35a80965d6965
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
If the QBindingStatus we receive from the QObject is from the thread
which is currently running, we do not need to refetch the thread local;
the reason we refetched the thread_local was after all only to guard
against the case where a QObject's property gets read in a different
thread.
To determine whether we are in the same thread, we can store the thread
id in the thread_local structure. Currently, it only gets initialized
for the main thread in QCoreApplication (as bindings are mostly used
there).
At a later point, we could either expose initBindingStatusThreadId, or
call the function when a QThread gets started.
Pick-to: 6.2
Change-Id: Id8eb803973bb083abfab83a62bfccc9e88a4e542
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
We call evaluateRecursive_inline in setBinding, which in turns runs the
noSelfDependecies check. However, creating a binding resuting in a
binding loop must not crash, but instead result in the binding entering
an error state. To prevent a crash caused by the assert in debug builds
of Qt, we replace the assert with a warning for now.
A better approach in the future would be to ensure that we only run the
check in cases where we are sure that a self-dependency is really a
fatal error.
Pick-to: 6.2
Change-Id: I58158864ed81fa907132a4e7d6667c9b529e7e64
Reviewed-by: Maximilian Goldstein <max.goldstein@qt.io>
We create the callable object at sizeof(QPBP) offset from
the beginning of the memory block. However, evaluateRecursive()
uses sizeof() + alignment when fetching that same callable from
the memory
While on 64-bit platforms this is fine due to
sizeof(QPBP) == QPBP::getSizeEnsuringAlignment(), this is broken for
32-bit systems where there's actually alignment bits that follow the
QPBP struct in memory (and thus we cast a random memory location to
an object)
(Note: QPBP is short for QPropertyBindingPrivate)
To fix this, change the offset for creation and destruction of the
callable to the one that uses alignment. This way, evaluateRecursive()
code becomes correct
Fixes: QTBUG-93890
Pick-to: 6.1 6.2
Change-Id: Ief57051846632fa61df4b79b3f054c25062a9498
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Update the bindable property docs to explain how to deal with virtual
getters and setters.
Task-number: QTBUG-92994
Pick-to: 6.2
Change-Id: I6c29011817e83623414b39afee0f39ad4cc5c1c9
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* Omit 'Bluetooth' enum value in QPermission::PermisionType (sic)
as that seems to be unimplemented.
* Comment out \sa links to internal/undocumented functions.
* Fix incomplete template parameters in \fn commands for
QProperty methods.
Task-number: QTBUG-93995
Change-Id: Ic8e63fca22c9c72325c76f90f537b221f56ebace
Reviewed-by: Paul Wicking <paul.wicking@qt.io>