Hi all,

As you all know, we’ve been doing a lot of work for Qt 6.0 to bring the concept 
of property bindings into Qt Core and make it accessible from C++ 
(https://www.qt.io/blog/property-bindings-in-qt-6). Unfortunately, we lacked 
the time to do extensive porting of existing properties to the new system 
before we released 6.0.

A lot of that porting effort has now happened or is ongoing for both 6.1 and 
6.2. In general, the new property system does its job very well, but we did 
find a couple of items that required changing. Fortunately all of those changes 
can be done in a way that is binary compatible with 6.0.

The binding system in Qt 6.0 tries to evaluate bindings lazily, ie. when the 
property is being read. The advantage of such a system is that bindings would 
not get re-evaluated multiple times if several of the properties the binding 
depended upon got changed, leading in theory to less computations.

What we already found out before 6.0 times was that some of our existing 
properties could not easily be ported to a lazy binding system, as the property 
setters were executing code that triggered certain side effects. Thus we did 
include a private class called QObjectCompatProperty in 6.0 already that did 
evaluate bindings immediately, leading to a hybrid between immediate (eager) 
and lazy binding evaluations for the system.

During porting, we now found that

* A lot of existing properties (probably as much as 50%) require immediate 
binding evaluation for a straightforward port
* Changing those properties to be compatible with lazy binding evaluation 
requires in many cases a complete rewrite of the class in question, amounting 
to huge amounts of work and lots of potential regressions
* As many properties can not be lazy, there is a lot less benefit of lazy 
binding evaluation than we hoped for
* The Qt Quick architecture uses a rendering thread to decouple QML item 
changes and rendering. There is a sync point between both threads where the 
rendering thread reads out properties from the main thread to update itself. 
That sync point needs to be kept minimal to allow both threads to run as 
independent as possible. Lazy binding evaluation would cause the bindings to 
get evaluated during that sync period and from the wrong thread.

All of this lead us to revisit parts of the internal architecture of the new 
C++ binding system over the last two months. The conclusion we came up with was 
to remove the lazy binding evaluation and instead add a feature that would 
allow us to dynamically group property updates together and only update 
bindings once all property updates inside the group are done.

This system will allow us to avoid repeated binding evaluations for most cases 
where they appear today (e.g. when instantiating new components or when doing 
timed updates through animations). The advantage is that this will work for all 
properties, not only for part of them as with the mixed lazy/eager system that 
we have in Qt 6.0.

You can find those changes in 
https://codereview.qt-project.org/c/qt/qtbase/+/332557/34 and related patches. 
We’re currently working on merging those for Qt 6.2. 

They should have little direct impact on anybody using C++ based property 
bindings and keep the main benefits we are getting from the new property 
system: A C++ API for bindings, faster binding execution compared to what we 
had in the QML engine in Qt 5.15 and the ability to use bindings without a QML 
engine in place.

Cheers,
Lars
_______________________________________________
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development

Reply via email to