summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2021-01-20 10:26:24 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2021-01-21 17:00:29 +0100
commit3861ec735e669aa43c2a0177f948b84d8cac0797 (patch)
treee3e59b7dc9c043fda925c7b10692e9b825b9d2d1
parent150660887f9cb402e16e351252a6ccdbee235ad9 (diff)
QProperty: Add private isAnyBindingEvaluating function
To optimize certain operations, it can be useful to know whether we are currently evaluating a binding. For instance, we have properties whose storage is only alloctaed on-demand when they are set. However, we would also allocate them if they are used in a binding context, as we would otherwise not properly track the dependency. Using isAnyBindingEvaluating in the getter, we can detect this situation, and avoid the allocation if it returns false. This API is private for now, as it exposes some internals of the property system and should be used with care. As it needs to access the TLS variable, it also has a non-negligible cost. Change-Id: I373aabee644fe7020b2ffba7d6a0ad9a1e1b4ec0 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
-rw-r--r--src/corelib/kernel/qproperty.cpp15
-rw-r--r--src/corelib/kernel/qproperty_p.h4
-rw-r--r--tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp9
3 files changed, 28 insertions, 0 deletions
diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp
index 0534749afa..686ec484ca 100644
--- a/src/corelib/kernel/qproperty.cpp
+++ b/src/corelib/kernel/qproperty.cpp
@@ -1667,4 +1667,19 @@ void restoreBindingStatus(BindingEvaluationState *status)
bindingStatus.currentlyEvaluatingBinding = status;
}
+namespace QtPrivate {
+/*!
+ \internal
+ This function can be used to detect whether we are currently
+ evaluating a binding. This can e.g. be used to defer the allocation
+ of extra data for a QPropertyBindingStorage in a getter.
+ Note that this function accesses TLS storage, and is therefore soemwhat
+ costly to call.
+ */
+bool isAnyBindingEvaluating()
+{
+ return bindingStatus.currentlyEvaluatingBinding != nullptr;
+}
+} // namespace QtPrivate end
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qproperty_p.h b/src/corelib/kernel/qproperty_p.h
index 6ff1e8e71e..27cb8c907f 100644
--- a/src/corelib/kernel/qproperty_p.h
+++ b/src/corelib/kernel/qproperty_p.h
@@ -59,6 +59,10 @@
QT_BEGIN_NAMESPACE
+namespace QtPrivate {
+ Q_CORE_EXPORT bool isAnyBindingEvaluating();
+}
+
// Keep all classes related to QProperty in one compilation unit. Performance of this code is crucial and
// we need to allow the compiler to inline where it makes sense.
diff --git a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
index 7de6458406..3b656dae25 100644
--- a/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
+++ b/tests/auto/corelib/kernel/qproperty/tst_qproperty.cpp
@@ -1140,6 +1140,15 @@ void tst_QProperty::testNewStuff()
QCOMPARE(object.bindableFoo().value(), 111);
object.bindableFoo().setValue(24);
QCOMPARE(object.foo(), 24);
+
+ auto isCurrentlyEvaluatingBinding = []() {
+ return QtPrivate::isAnyBindingEvaluating();
+ };
+ QVERIFY(!isCurrentlyEvaluatingBinding());
+ QProperty<bool> evaluationDetector {false};
+ evaluationDetector.setBinding(isCurrentlyEvaluatingBinding);
+ QVERIFY(evaluationDetector.value());
+ QVERIFY(!isCurrentlyEvaluatingBinding());
}
void tst_QProperty::qobjectObservers()