Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
> > Step 1: mySharedPtr.data() ==> MyShared* P; >> Step 2: make sure the QML engine doesn't assume ownership: >> QDeclarativeEngine::**setObjectOwnership >> Step 3: hand over P to QML: setProperty or setContextProperty >> > > Yep, those steps seem to be the current requirement. If my patches get in > (not guaranteed), it will be reduced to just: > > Step 1: setContextProperty("myname", mySharedPtr); > > or > > Step 1: setContextProperty("myname", mySharedPtr.toWeakRef()); > > depending on your needs. > > > >> When I said the database layer should preferably remain QML agnostic, >> I merely wanted to keep "patchup code" like "setObjectOwnership" out >> of a clean set of data classes for purist reasons. (Really it is an >> exaggeration imho.. I have no problem using stuff from QtDeclarative >> in code. Will need it for QList properties anyway. It's just a design >> reflex). >> > > Yes, I agree. > > > Leaving out step 2 is bad, right? >> > > Yes, and worse it might not obvious to consumers of the API that it's > needed. > Hi again. I have modified the wiki page that Sivan started (my name in qt-project.orgis "Centipede"). In my view your advice above is serious enough to warrant a user comment in the footnote section of at least the documentation pages of 4.8. But I cannot for the life of me figure out where to add such comments. Is qt-project.org's user comment system up and running? Best regards, Rene Jensen ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
On 29.05.2012 10:55, Rene Jensen wrote: >>> Question: How can we expose objects governed by QSharedPointer to >>> QML >>> safely? I *can* guarantee the lifecycle beyond the life of my >>> QDeclarativeEngine. >> If you can guarantee that, then use mySharedPtr.data() as others >> have >> said. > > Just a quick thought, would that suggesion be leading into trouble? > In > only see one way to do that right: > > Step 1: mySharedPtr.data() ==> MyShared* P; > Step 2: make sure the QML engine doesn't assume ownership: > QDeclarativeEngine::setObjectOwnership > Step 3: hand over P to QML: setProperty or setContextProperty Yep, those steps seem to be the current requirement. If my patches get in (not guaranteed), it will be reduced to just: Step 1: setContextProperty("myname", mySharedPtr); or Step 1: setContextProperty("myname", mySharedPtr.toWeakRef()); depending on your needs. > > When I said the database layer should preferably remain QML agnostic, > I merely wanted to keep "patchup code" like "setObjectOwnership" out > of a clean set of data classes for purist reasons. (Really it is an > exaggeration imho.. I have no problem using stuff from QtDeclarative > in code. Will need it for QList properties anyway. It's just a design > reflex). Yes, I agree. > Leaving out step 2 is bad, right? Yes, and worse it might not obvious to consumers of the API that it's needed. Thanks, -- Stephen Kelly | Software Engineer KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company www.kdab.com || Germany +49-30-521325470 || Sweden (HQ) +46-563-540090 KDAB - Qt Experts - Platform-Independent Software Solutions ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
>> >> Question: How can we expose objects governed by QSharedPointer to QML >> safely? I *can* guarantee the lifecycle beyond the life of my >> QDeclarativeEngine. > > If you can guarantee that, then use mySharedPtr.data() as others have said. Just a quick thought, would that suggesion be leading into trouble? In only see one way to do that right: Step 1: mySharedPtr.data() ==> MyShared* P; Step 2: make sure the QML engine doesn't assume ownership: QDeclarativeEngine::setObjectOwnership Step 3: hand over P to QML: setProperty or setContextProperty When I said the database layer should preferably remain QML agnostic, I merely wanted to keep "patchup code" like "setObjectOwnership" out of a clean set of data classes for purist reasons. (Really it is an exaggeration imho.. I have no problem using stuff from QtDeclarative in code. Will need it for QList properties anyway. It's just a design reflex). Leaving out step 2 is bad, right? Best regards, Rene Jensen ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
First of all, I just want to say thanks for the quite unexpected amount of replies to my mail. They will take a little time to absorb, but I still feel I have relevant comments on some of the issues - once the "heatwave" in Denmark has passed (apparently my brain fries at temperatures above 22 C) >> >> Hoping for an enriching debate, > ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
Den 25. mai 2012 02:35, skrev ext christopher.ad...@nokia.com: > Hi, > >>> In QtQuick 2.0 (ie, Qt 5.0), we are thinking about using property var >>> more often in the implementation (eg, of qobject-derived-type >>> properties) to avoid some of those edge-cases, and providing more >>> consistent (and useful) referencing semantics. >> Can you say what 'var' is and why it would help? > In QtQuick 1.x, you could not define a "JavaScript var-type property" in a > QML item. The closest thing provided was "property variant" which, > internally, is a QVariant. Assigning a JavaScript object to that property > would result in it being converted to a QVariantMap. Accessing that property > from JS would result in that QVariantMap being converted back into a JS > object. You could not store a JS function reference, or any other "special" > JS value in a "property variant" property (eg, null, undefined). > > In QtQuick 2.0, we deprecated "property variant" and added "property var". > Internally, "property var" properties are JS values. Thus, you can store > anything created in JS, including JS function references. This allows > greater dynamicity and flexibility. Only when you access that property from > C++ (via QObject::property() or QQmlProperty::read()) will it be converted to > a QVariant (following the same conversion rules as for any other JS value to > QVariant conversion). > Also note that when you implement types on the C++ side, you can use the QJSValue class as a property or method parameter to transfer values between C++ and QML/JS without type/data loss. This also includes JS functions; for example, you can assign a function to a property from QML and call it later from C++ using QJSValue::call(). There's also QJson{Value,Object,Array} integration. Best regards, Kent ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
Hi, > > In QtQuick 2.0 (ie, Qt 5.0), we are thinking about using property var > > more often in the implementation (eg, of qobject-derived-type > > properties) to avoid some of those edge-cases, and providing more > > consistent (and useful) referencing semantics. > > Can you say what 'var' is and why it would help? In QtQuick 1.x, you could not define a "JavaScript var-type property" in a QML item. The closest thing provided was "property variant" which, internally, is a QVariant. Assigning a JavaScript object to that property would result in it being converted to a QVariantMap. Accessing that property from JS would result in that QVariantMap being converted back into a JS object. You could not store a JS function reference, or any other "special" JS value in a "property variant" property (eg, null, undefined). In QtQuick 2.0, we deprecated "property variant" and added "property var". Internally, "property var" properties are JS values. Thus, you can store anything created in JS, including JS function references. This allows greater dynamicity and flexibility. Only when you access that property from C++ (via QObject::property() or QQmlProperty::read()) will it be converted to a QVariant (following the same conversion rules as for any other JS value to QVariant conversion). If we were to implement "property variant" as a synonym for "property var" in QtQuick 2.0, the code base would be simplified, and the referencing semantics made more consistent (more on this later). I haven't benchmarked the performance impact of such a change, yet, however. > > Does what you say about handling qobject-derived-type properties have > anything to do with this: > > https://codereview.qt-project.org/#change,13006 > > https://codereview.qt-project.org/#change,13007 > > or do you have something else in mind? When I said "qobject-derived-type" I should have said "User-defined (via custom components) QML types". Eg, if you have a file named MyButton.qml, you can use MyButton as a type. It is a QQuickItem-derived type (and thus a QObject-derived type). The problem is that currently, the ownership semantics are (in my opinion) quite strange. In particular: import QtQuick 2.0 Item { id: root property MyButton buttonOne: MyButton { ... } property MyButton buttonTwo property variant buttonThree: MyButton { ... } property variant buttonFour property var buttonFive: MyButton { ... } property var buttonSix function generateButton() { var c = Qt.createComponent("MyButton.qml"); var o = c.createObject(null); // no explicit parent return o; } function generateButtons() { buttonTwo = generateButton(); buttonFour = generateButton(); buttonSix = generateButton(); } Component.onCompleted: { generateButtons(); gc(); gc(); gc(); gc(); } } That example will cause button two and four to be collected / destroyed via garbage collection. Because the generated buttons had no explicit parent given, they have JS ownership and will be collected if no JS references to them exist. QVariant-backed property types (like MyButton and variant) don't store JS values (and thus don't cause JS references to exist) and thus buttons two and four will be collected. The only reason why buttonOne and buttonThree aren't collected is that we explicitly set the parent of the RHS item, during instantiation (in the VME, during CreateSimpleObject). To me, it seems strange that root is the parent of buttonOne and buttonThree, but not the parent of buttonTwo or buttonFour (given that the only real difference is declaration vs assignment), and it is certainly strange that even though buttonTwo and buttonFour "reference" their associated values, the gc will still collect them. Note that buttons five and six are not collected, because they are JS values (which will prevent the gc from collecting what they reference). See QTBUG-24767 for more information. There is a change which fixes the referencing strangeness, but it may have a performance impact during gc cycles, which we are currently evaluating. Cheers, Chris. ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
Hi Rene, Thanks for the email. I think you raise some valid points. Some work on addressing them is already underway. On Wednesday, May 23, 2012 12:25:42 Rene Jensen wrote: > Disclaimer 3: Discussing QML seems very poisonous these days, but I > still feel the need for a thread that focus on the good and bad with > the current design and/or the current documentation specifically > regarding exposing C++ to QML. Hopefully you agree and can accept that > I bring it up on the developer list. Yes, I think this email has the right tone and content, as others have said too. >From the forum: > Can QML gracefully handle pointers wrapped in QSharedPointer? The answer is not yet - maybe in Qt 5.1. > > So rewording the concerns to open up for (hopefully) useful comments - > I can perhaps try to make a wiki article which adds any missing > information: > > OWNERSHIP... > > These are the ownership "universes" (unless I'm mistaken): > > 1) Objects created in C++ owned via the QObject parent/child tree > e.g.: new MyGizmo. > 2) Objects created in C++ owned via the QSharedPointer system, e.g.: > QSharedPointer (new MyGizmo). > 3) Objects created by QDeclarativeEngine or Javascript owned by the > engine, e.g.: MyGizmo { ... properties ... } Looks right to me. > > Question: How can we expose objects governed by QSharedPointer to QML > safely? I *can* guarantee the lifecycle beyond the life of my > QDeclarativeEngine. If you can guarantee that, then use mySharedPtr.data() as others have said. > > These are the ways to transfer values/references from C++ to QML > (let's ignore the other way around for now): > > A) By calling QDeclarative::setRootContext (ownership not transferred: > http://qt-project.org/doc/qt-4.8/qdeclarativecontext.html#setContextProperty I think it's more common to use QDeclarativeEngine::rootContext()->setContextProperty() as Alberto said. > D) By QML accessing a Q_PROPERTY on a C++ object (ownership?). I guess you mean a binding? > I assume that each time a value crosses a boundary between from C++ => > QML => Javascript an automatic conversion takes place. This conversion > is probably the root of all evils, since a lot can happen with pointer > references being smashed to either some form of null (as in > unsuccessful C++ to QML assignment via (A) or (B) above) or > "undefined" (like when a javascript expression tries to access a QML > Component property) depending on factors not quite clear to me. > > Question: What are the exact mechanisms that governs value conversion > from one space to another? Beyond what Christopher said, there's some more automation possible. We can add QSharedPointer awareness to QML, as long as doing: if (we_know_variant_contains_a_QSharedPointer_To_QObjectDerived) { QSharedPointer sp; sp = *reinterpret_cast*>(variant.data()); } ...is ok, which I think it is. However, we'll more likely want to make that possible with QWeakPointer based instances (otherwise declarative might store our QSharedPointer and not drop its refcount - it's a tricky issue), which should also be possible. After this patch: https://codereview.qt-project.org/#change,27070 we_know_variant_contains_a_QSharedPointer_To_QObjectDerived will be: QMetaType::typeFlags(variant.userType()) & QMetaType::SharedPointerToQObject or similar. We would be able to handle Q_PROPERTY(QSharedPointer ...) too. After this stuff: https://codereview.qt-project.org/#change,27071 ... and a few more tricks adding function pointers to the QVariant::Handler, we would be able to handle Q_PROPERTY(QSharedPointer ...) too. This is the kind of integration that I wish had been thought of for declarative use-cases long ago and designed into QVariant in Qt 5 with the hybrid QML application use-cases in mind. The needs QtDeclarative has needs for non-type-safety and conversions are mostly separate and internal, so it's not as easy as it could be to use user- defined types and containers and QVariants with QML, like automatic handling of QList, QVector and generally Container. Maybe we can make this stuff better in 5.1 though... We'll have to see if it works and the API can be extended for it in a maintainable way. Handling QObject derived types might be easily handled too (currently it introduces several inconveniences for hybrid apps): https://codereview.qt-project.org/#change,13006 https://codereview.qt-project.org/#change,13007 https://codereview.qt-project.org/#change,19113 > > COLLECTIONS... > > Collections (QList, QMap, QHash, QSet) of object references > constitutes a special scenario which in my view is less that ideally > solved. I would love a much simpler and more intuitive way to expose > those to QML. But given that this topic is way too large, I don't want > to bring it up here, although it does belong. I have a working patch , but again, it was already pushed back to 5.1: https://bugreports.qt-project.org/browse/QTBUG-23566 I'm still not 100% certain if th
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
On Thursday, May 24, 2012 02:41:31 christopher.ad...@nokia.com wrote: > In QtQuick 2.0 (ie, Qt 5.0), we are thinking about using property var more > often in the implementation (eg, of qobject-derived-type properties) to > avoid some of those edge-cases, and providing more consistent (and useful) > referencing semantics. Can you say what 'var' is and why it would help? Does what you say about handling qobject-derived-type properties have anything to do with this: https://codereview.qt-project.org/#change,13006 https://codereview.qt-project.org/#change,13007 or do you have something else in mind? Thanks, -- Stephen Kelly | Software Engineer KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company www.kdab.com || Germany +49-30-521325470 || Sweden (HQ) +46-563-540090 KDAB - Qt Experts - Platform-Independent Software Solutions signature.asc Description: This is a digitally signed message part. ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
On quinta-feira, 24 de maio de 2012 16.33.53, Olivier Goffart wrote: > > I've long wanted to make QSharedPointer on QObject-derivatives participate > > in the whole-tree ownership, somehow. I introduced QSharedPointer in 4.4 > > and I did some work in 4.5 to make that work. > > > > My original solution was to have a parent only deref its children's shared > > pointer counter, deleting it only if it became zero. That means that if > > you > > had a QSharedPointer to an object in the middle of the hierarchy, that > > object would be orphaned instead of deleted when the parent died. The > > converse was that when the last QSharedPointer reference to a QObject went > > away, the object might survive if it still had a parent. > > So that would be like having "children" be in implemented as a > QList > ? Yes, like that, but not actually implemented with that. > But I personaly think it shoud not be the case. QSharedPointer is > orthogonal with object tree as much as it is orthogonal with > std::shared_ptr or QScopedPointer or manually delete. > > You have to pick how you do thememory management for a given pointer and > stick to it. It is orthogonal and right now it's working orthogonally. This was just something I experimented with, but didn't work as intended. It crashed QWidget left and right. -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center Intel Sweden AB - Registration Number: 556189-6027 Knarrarnäsgatan 15, 164 40 Kista, Stockholm, Sweden signature.asc Description: This is a digitally signed message part. ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
Hi Rene, On Wed, May 23, 2012 at 1:25 PM, Rene Jensen wrote: > > DOCUMENTATION... > > The truth is that initially in ten out of ten cases I resorted to > guessing about the type and ownership of a value when I cross a > boundary. Since I have thoroughly cross examined the docs, it must > mean that (subjectively) I find it hard to extract the proper > information from them. I miss clear best practices, and often feel > more confused by reading the docs than I feel enlightened. In fact, > let me upgrade that statement: > When I started with Qt , eager to get developing and contributing to Qt itself , I also hit similar walls. Now days I resort to use the source (tm) more and more as I need more advanced stuff, especially when trying to extend QML. The question of ownership/linkage/transport of objects from QML to C++ and vice verse is indeed involved, and is a challenge to document to all tastes. I think task based docs might be a partial solution to start with. > *you* the burden of reading messy prose text). We need quick reference > cards containing COMPLETE information about all possibilities in one > place. You are only asking for trouble if you make it mandatory to > read every article under > http://doc-snapshot.qt-project.org/4.8/qtquick.html to be able to > write bug free code. > Sorry. But I'm learning a new technology just about every week - most > in vain. I get my dose of documentation, thank you. Thanks to your post and Christopher's reply (and ofcourse Kai who discussed some of this a while ago on interest@), I personally feel *much* more enlightened about it, and not just with regards to my project's use case. The docs are far from being in ideal shape- hopefully we this will change. I listed task based docs as suggested discussion point for the docs session[0] next month in Berlin qt summit. Realizing that improving Qt is now a community wide effort, I'd appreciate if you could add your own feedback there if you see fit (I know that it is all time consuming and apologize for that in advance, but there's simply no other way to improve). And on a related note, your email has been very informative and specific in describing the issues we face. I would suggest that next time don't hesitate to post even if it is a long post. Following the Qt mailing lists for a while now, I learned that the large posts are usually (1) gold mines for knowledge and expertise of Qt, (2) highly interesting. Your post scored both (1) and (2). I also think that now, when Qt is trying to out reach new communities, platforms and problem domains- this sort of constructive communication is of grave importance. This is the sort of discussion I enjoy following. -Sivan [0]: http://qt-project.org/groups/qt-contributors-summit-2012/wiki/Documentation ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
On Wednesday 23 May 2012 13:43:22 Thiago Macieira wrote: > On quarta-feira, 23 de maio de 2012 14.16.12, Alberto Mardegan wrote: > > On 05/23/2012 01:25 PM, Rene Jensen wrote: > > > Question: How can we expose objects governed by QSharedPointer to QML > > > safely? I can guarantee the lifecycle beyond the life of my > > > QDeclarativeEngine. > > > > As neither of us knows exactly how QML handles QSharedPointer (my guess > > is that it simply doesn't; QSharedPointer is a template class which can > > be used with many other types than QObject, so I don't think that > > exposing it in QML is trivial), I would simply recommend you not to use > > it. > > I actually mentioned QSharedPointer in a recent blog post of mine [0], > > which you might find interesting especially if your use of > > QSharedPointer is suggested by your previous experience with other > > toolkits. If you really think that QSharedPointer is absolutely necessary > > in your case (I still doubt), then just expose its QObject data to QML, > > since you also claim that you can make sure its lifetime will survive the > > engine. > Just a tidbit... > > I've long wanted to make QSharedPointer on QObject-derivatives participate > in the whole-tree ownership, somehow. I introduced QSharedPointer in 4.4 > and I did some work in 4.5 to make that work. > > My original solution was to have a parent only deref its children's shared > pointer counter, deleting it only if it became zero. That means that if you > had a QSharedPointer to an object in the middle of the hierarchy, that > object would be orphaned instead of deleted when the parent died. The > converse was that when the last QSharedPointer reference to a QObject went > away, the object might survive if it still had a parent. So that would be like having "children" be in implemented as a QList > ? But I personaly think it shoud not be the case. QSharedPointer is orthogonal with object tree as much as it is orthogonal with std::shared_ptr or QScopedPointer or manually delete. You have to pick how you do thememory management for a given pointer and stick to it. -- Olivier Woboq - Qt services and support - http://woboq.com ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
On quinta-feira, 24 de maio de 2012 16.26.19, Olivier Goffart wrote: > > Then you would also be able to make the "delete" operator work > > consistently with reference-counted QObjects, by overriding it and make > > it just decrement the count (and delete the object if the count is 0). > > No. That's not how the delete operator works. > The operator delete is called after the destructors has already been run, > and its purpose is just to release the memory. the operator delete cannot > decide not to delete. No, but a QSharedPointer custom deleter can decide not to call delete in the first place. -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center Intel Sweden AB - Registration Number: 556189-6027 Knarrarnäsgatan 15, 164 40 Kista, Stockholm, Sweden signature.asc Description: This is a digitally signed message part. ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
On Thursday 24 May 2012 11:46:05 Alberto Mardegan wrote: > On 05/23/2012 02:43 PM, Thiago Macieira wrote: > > My original solution was to have a parent only deref its children's shared > > pointer counter, deleting it only if it became zero. That means that if > > you > > had a QSharedPointer to an object in the middle of the hierarchy, that > > object would be orphaned instead of deleted when the parent died. The > > converse was that when the last QSharedPointer reference to a QObject > > went away, the object might survive if it still had a parent. > > Nice! However, a very hard thing to do as an aftertought. IMHO, it would > be easier if the reference count was built in QObject itself, and > QSharedPointer would just play with that reference count. Then it would be like a QExplicitlySharedDataPointer<> (Not a really good name, but already does what you want) And you can have that for any object if you have multiple inheritence with some QObject and QSharedData for example. > Then you would also be able to make the "delete" operator work > consistently with reference-counted QObjects, by overriding it and make > it just decrement the count (and delete the object if the count is 0). No. That's not how the delete operator works. The operator delete is called after the destructors has already been run, and its purpose is just to release the memory. the operator delete cannot decide not to delete. -- Olivier Woboq - Qt services and support - http://woboq.com ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
On 05/23/2012 02:43 PM, Thiago Macieira wrote: > My original solution was to have a parent only deref its children's shared > pointer counter, deleting it only if it became zero. That means that if you > had a QSharedPointer to an object in the middle of the hierarchy, that object > would be orphaned instead of deleted when the parent died. The converse was > that when the last QSharedPointer reference to a QObject went away, the > object > might survive if it still had a parent. Nice! However, a very hard thing to do as an aftertought. IMHO, it would be easier if the reference count was built in QObject itself, and QSharedPointer would just play with that reference count. Then you would also be able to make the "delete" operator work consistently with reference-counted QObjects, by overriding it and make it just decrement the count (and delete the object if the count is 0). However, I didn't think it thoroughly through, and I'm sure there would be issues with this approach as well. But indeed I'm convinced that using QSharedPointer and the unmodified really-deleting delete operator in the same code is also a recipe for disaster. > There were a few problems with that solution. I can remember now: > > 1) it didn't play very well with QWidgets after the Alien project. QWidgets > often reference the top-level window, which is the ultimate parent widget > (the > one with no parents). Orphaning a QWidget from QWidget's destructor was a > recipe for disaster, since the original TLW data might have been gone already. > > 2) it didn't play very well with QObject siblings talking to each other > during > destruction or, worse, deleting each other. This is a huge pain and source of > complexity during QObject infanticide. Indeed, all code which assumes that the parent object is always there should be fixed to gracefully handle being orphaned. > 3) what happens if you had a QSharedPointer with a parent, dropped > the last QSharedPointer reference (it survives because of the parent) and > later orphaned that object via setParent(0)? Should it be deleted? Unless the code calling object->setParent(0) still has a reference to the object, yes. Ciao, Alberto -- http://blog.mardy.it <- geek in un lingua international! ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
Hi Rene, I certainly agree that constructive discussion about the QML language and ways that it could be improved are important. You raise a lot of important points, some of which will be addressed in Qt5.0, some of which we still need to consider how to fix, and what priority they should be, for future minor releases of Qt. More comments inline (some sections removed for brevity). > OWNERSHIP... > > These are the ownership "universes" (unless I'm mistaken): > > 1) Objects created in C++ owned via the QObject parent/child tree > e.g.: new MyGizmo. > 2) Objects created in C++ owned via the QSharedPointer system, e.g.: > QSharedPointer (new MyGizmo). > 3) Objects created by QDeclarativeEngine or Javascript owned by the engine, > e.g.: MyGizmo { ... properties ... } > > Question: How can we expose objects governed by QSharedPointer to QML > safely? I *can* guarantee the lifecycle beyond the life of my > QDeclarativeEngine. Currently, QML isn't aware of QSharedPointer and friends, but internally uses its own guard-types to react to QObject deletion. If you want to ensure that the engine won't delete the QObject you pass in, you need to explicitly set the ownership of the QObject to CppOwnership (there's a QQmlEngine function to do so). Alternatively, if the QObject has a parent (ownership parent) set, the engine won't delete it. > > These are the ways to transfer values/references from C++ to QML (let's > ignore the other way around for now): > > A) By calling QDeclarative::setRootContext (ownership not transferred: > http://qt-project.org/doc/qt- > 4.8/qdeclarativecontext.html#setContextProperty). > B) By calling QObject::setProperty on the instantiated component > (ownership?) > C) By QML calling a method on a C++ object and getting a response > (ownership IS transferred to QML. In the docs somewhere.) > D) By QML accessing a Q_PROPERTY on a C++ object (ownership?). > > Now, A+B lend themselves badly as mechanisms to expose subobjects, but > makes it easy to specify ownership via > QDeclarativeEngine::setObjectOwnership. > Conversely C+D are better at exposing subobjects or related collections (in > QML... myProperty: myGizmo.findAllTimelineEvents() ), but I don't see how I > can specify ownership in a QML-agnostic way (C++ models should not know > about QML!) I don't understand your last point. What do you mean "in a QML-agnostic way"? The QML engine respects normal QObject parenting. You are correct about (c) by the way: if the QObject returned from a Q_INVOKABLE function to JS does not have CppOwnership explicitly set, it will become JavaScriptOwnership owned. To avoid that, you can explicitly set the ownership semantic prior to returning it. With (b) ownership is not transferred. However, it should be noted that if you define a QObject-derived-type property in QML with its value declared (ie, via "property Item propName: Item { id: child }") that property's QObject value will be owned by the object with the propName property. But this isn't directly related to interacting with QML from C++, and so is probably unrelated to what you are talking about. > > Question: What happens to ownership in each of these transfers? > To summarise: a) no ownership change b) no ownership change c) ownership change if ownership semantics were not previously explicitly set d) no ownership change > TYPESYSTEM... > > Then there is the issue of what type is associated with the object. > This is relevant when specifying properties in QML. I believe that a major > source of confusion comes from the notion that there are three type > systems involved: > > 1) The traditional Qt/C++ moc/compiler types (perhaps QObjects, perhaps > declared Q_DECLARE_METATYPE to make QVariant understand them) > 2) The types that the Javascript engine knows (Object, Function, Number, > String etc.) > 3) The types that the QML engine understands (http://doc-snapshot.qt- > project.org/4.8/qdeclarativebasictypes.html > plus those registered with qmlRegisterType). QVariants can be used too. > > Question: Are there 2 or 3 typesystems? I guess it depends on how you define the term. There are only two property types that the QML engine understands: JavaScript vars, and QVariant properties. It just happens that it builds type information from the loaded component set, and enforces type safety when assigning to properties of those types (which is why you cannot assign an Item {} to a property of type Rectangle). But internally, all properties are stored as either QVariants or JavaScript vars. > > I assume that each time a value crosses a boundary between from C++ => > QML => Javascript an automatic conversion takes place. This conversion is > probably the root of all evils, since a lot can happen with pointer references > being smashed to either some form of null (as in unsuccessful C++ to QML > assignment via (A) or (B) above) or "undefined" (like when a javascript > expression tries to access a QML Component p
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
All: > W00t should have a backlog which covers the conversation, > if it was done on our public channels :-) If only Pierre de Fermat had had that feature! Atlant -Original Message- From: development-bounces+aschmidt=dekaresearch@qt-project.org [mailto:development-bounces+aschmidt=dekaresearch@qt-project.org] On Behalf Of marius.storm-ol...@nokia.com Sent: Wednesday, May 23, 2012 09:52 To: development@qt-project.org; thiago.macie...@intel.com Subject: Re: [Development] On QML, ownership, QObject-trees and QSharedPointer W00t should have a backlog which covers the conversation, if it was done on our public channels :-) -- Sent from my Nokia N9On 5/23/12 13:44 ext Thiago Macieira wrote: On quarta-feira, 23 de maio de 2012 14.16.12, Alberto Mardegan wrote: > On 05/23/2012 01:25 PM, Rene Jensen wrote: > > Question: How can we expose objects governed by QSharedPointer to QML > > safely? I can guarantee the lifecycle beyond the life of my > > QDeclarativeEngine. > > As neither of us knows exactly how QML handles QSharedPointer (my guess > is that it simply doesn't; QSharedPointer is a template class which can > be used with many other types than QObject, so I don't think that > exposing it in QML is trivial), I would simply recommend you not to use it. > I actually mentioned QSharedPointer in a recent blog post of mine [0], > which you might find interesting especially if your use of > QSharedPointer is suggested by your previous experience with other toolkits. > If you really think that QSharedPointer is absolutely necessary in your > case (I still doubt), then just expose its QObject data to QML, since you > also claim that you can make sure its lifetime will survive the engine. Just a tidbit... I've long wanted to make QSharedPointer on QObject-derivatives participate in the whole-tree ownership, somehow. I introduced QSharedPointer in 4.4 and I did some work in 4.5 to make that work. My original solution was to have a parent only deref its children's shared pointer counter, deleting it only if it became zero. That means that if you had a QSharedPointer to an object in the middle of the hierarchy, that object would be orphaned instead of deleted when the parent died. The converse was that when the last QSharedPointer reference to a QObject went away, the object might survive if it still had a parent. There were a few problems with that solution. I can remember now: 1) it didn't play very well with QWidgets after the Alien project. QWidgets often reference the top-level window, which is the ultimate parent widget (the one with no parents). Orphaning a QWidget from QWidget's destructor was a recipe for disaster, since the original TLW data might have been gone already. 2) it didn't play very well with QObject siblings talking to each other during destruction or, worse, deleting each other. This is a huge pain and source of complexity during QObject infanticide. 3) what happens if you had a QSharedPointer with a parent, dropped the last QSharedPointer reference (it survives because of the parent) and later orphaned that object via setParent(0)? Should it be deleted? The worst of it all is that I remember having a discussion during 4.6 times with someone on IRC and coming up with a brilliant and simple solution. Something like "don't orphan, but keep a refcount on the entire tree". The problem is that I didn't write it down, because I thought it was so simple and evident that I'd be able to remember or work it out again. I haven't been able to. Fermat would be proud. Anyway, that reminds me I have some pending QSharedPointer work to do. I'll get on with it. -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center Intel Sweden AB - Registration Number: 556189-6027 Knarrarnäsgatan 15, 164 40 Kista, Stockholm, Sweden ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development Click https://www.mailcontrol.com/sr/Bj8gU1boyQLTndxI!oX7UjaeDmea67kX7SqObTicsrBLI7iRALOOZRgXDSSm+ebxNAjdtRoTpmRPbv5+FCDqIw== to report this email as spam. This e-mail and the information, including any attachments, it contains are intended to be a confidential communication only to the person or entity to whom it is addressed and may contain information that is privileged. If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution or copying of this communication is strictly prohibited. If you have received this communication in error, please immediately notify the sender and destroy the original message. Thank you. Please consider the environment before printing this email. ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
W00t should have a backlog which covers the conversation, if it was done on our public channels :-) -- Sent from my Nokia N9On 5/23/12 13:44 ext Thiago Macieira wrote: On quarta-feira, 23 de maio de 2012 14.16.12, Alberto Mardegan wrote: > On 05/23/2012 01:25 PM, Rene Jensen wrote: > > Question: How can we expose objects governed by QSharedPointer to QML > > safely? I can guarantee the lifecycle beyond the life of my > > QDeclarativeEngine. > > As neither of us knows exactly how QML handles QSharedPointer (my guess > is that it simply doesn't; QSharedPointer is a template class which can > be used with many other types than QObject, so I don't think that > exposing it in QML is trivial), I would simply recommend you not to use it. > I actually mentioned QSharedPointer in a recent blog post of mine [0], > which you might find interesting especially if your use of > QSharedPointer is suggested by your previous experience with other toolkits. > If you really think that QSharedPointer is absolutely necessary in your > case (I still doubt), then just expose its QObject data to QML, since you > also claim that you can make sure its lifetime will survive the engine. Just a tidbit... I've long wanted to make QSharedPointer on QObject-derivatives participate in the whole-tree ownership, somehow. I introduced QSharedPointer in 4.4 and I did some work in 4.5 to make that work. My original solution was to have a parent only deref its children's shared pointer counter, deleting it only if it became zero. That means that if you had a QSharedPointer to an object in the middle of the hierarchy, that object would be orphaned instead of deleted when the parent died. The converse was that when the last QSharedPointer reference to a QObject went away, the object might survive if it still had a parent. There were a few problems with that solution. I can remember now: 1) it didn't play very well with QWidgets after the Alien project. QWidgets often reference the top-level window, which is the ultimate parent widget (the one with no parents). Orphaning a QWidget from QWidget's destructor was a recipe for disaster, since the original TLW data might have been gone already. 2) it didn't play very well with QObject siblings talking to each other during destruction or, worse, deleting each other. This is a huge pain and source of complexity during QObject infanticide. 3) what happens if you had a QSharedPointer with a parent, dropped the last QSharedPointer reference (it survives because of the parent) and later orphaned that object via setParent(0)? Should it be deleted? The worst of it all is that I remember having a discussion during 4.6 times with someone on IRC and coming up with a brilliant and simple solution. Something like "don't orphan, but keep a refcount on the entire tree". The problem is that I didn't write it down, because I thought it was so simple and evident that I'd be able to remember or work it out again. I haven't been able to. Fermat would be proud. Anyway, that reminds me I have some pending QSharedPointer work to do. I'll get on with it. -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center Intel Sweden AB - Registration Number: 556189-6027 Knarrarnäsgatan 15, 164 40 Kista, Stockholm, Sweden ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
On quarta-feira, 23 de maio de 2012 14.16.12, Alberto Mardegan wrote: > On 05/23/2012 01:25 PM, Rene Jensen wrote: > > Question: How can we expose objects governed by QSharedPointer to QML > > safely? I can guarantee the lifecycle beyond the life of my > > QDeclarativeEngine. > > As neither of us knows exactly how QML handles QSharedPointer (my guess > is that it simply doesn't; QSharedPointer is a template class which can > be used with many other types than QObject, so I don't think that > exposing it in QML is trivial), I would simply recommend you not to use it. > I actually mentioned QSharedPointer in a recent blog post of mine [0], > which you might find interesting especially if your use of > QSharedPointer is suggested by your previous experience with other toolkits. > If you really think that QSharedPointer is absolutely necessary in your > case (I still doubt), then just expose its QObject data to QML, since you > also claim that you can make sure its lifetime will survive the engine. Just a tidbit... I've long wanted to make QSharedPointer on QObject-derivatives participate in the whole-tree ownership, somehow. I introduced QSharedPointer in 4.4 and I did some work in 4.5 to make that work. My original solution was to have a parent only deref its children's shared pointer counter, deleting it only if it became zero. That means that if you had a QSharedPointer to an object in the middle of the hierarchy, that object would be orphaned instead of deleted when the parent died. The converse was that when the last QSharedPointer reference to a QObject went away, the object might survive if it still had a parent. There were a few problems with that solution. I can remember now: 1) it didn't play very well with QWidgets after the Alien project. QWidgets often reference the top-level window, which is the ultimate parent widget (the one with no parents). Orphaning a QWidget from QWidget's destructor was a recipe for disaster, since the original TLW data might have been gone already. 2) it didn't play very well with QObject siblings talking to each other during destruction or, worse, deleting each other. This is a huge pain and source of complexity during QObject infanticide. 3) what happens if you had a QSharedPointer with a parent, dropped the last QSharedPointer reference (it survives because of the parent) and later orphaned that object via setParent(0)? Should it be deleted? The worst of it all is that I remember having a discussion during 4.6 times with someone on IRC and coming up with a brilliant and simple solution. Something like "don't orphan, but keep a refcount on the entire tree". The problem is that I didn't write it down, because I thought it was so simple and evident that I'd be able to remember or work it out again. I haven't been able to. Fermat would be proud. Anyway, that reminds me I have some pending QSharedPointer work to do. I'll get on with it. -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center Intel Sweden AB - Registration Number: 556189-6027 Knarrarnäsgatan 15, 164 40 Kista, Stockholm, Sweden signature.asc Description: This is a digitally signed message part. ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] On QML, ownership, QObject-trees and QSharedPointer
Hi Rene, I don't have real answers for your questions, but just a piece of advice: KISS. On 05/23/2012 01:25 PM, Rene Jensen wrote: > Question: How can we expose objects governed by QSharedPointer to QML > safely? I *can* guarantee the lifecycle beyond the life of my > QDeclarativeEngine. As neither of us knows exactly how QML handles QSharedPointer (my guess is that it simply doesn't; QSharedPointer is a template class which can be used with many other types than QObject, so I don't think that exposing it in QML is trivial), I would simply recommend you not to use it. I actually mentioned QSharedPointer in a recent blog post of mine [0], which you might find interesting especially if your use of QSharedPointer is suggested by your previous experience with other toolkits. If you really think that QSharedPointer is absolutely necessary in your case (I still doubt), then just expose its QObject data to QML, since you also claim that you can make sure its lifetime will survive the engine. > These are the ways to transfer values/references from C++ to QML > (let's ignore the other way around for now): > > A) By calling QDeclarative::setRootContext (ownership not transferred: > http://qt-project.org/doc/qt-4.8/qdeclarativecontext.html#setContextProperty). Note that you don't need to call setRootContext(); you can just get the existing context (with QDeclarative::rootContext()) and call setContextProperty() on it (maybe that's exactly the same you meant?). > B) By calling QObject::setProperty on the instantiated component (ownership?) > C) By QML calling a method on a C++ object and getting a response > (ownership IS transferred to QML. In the docs somewhere.) Sure? That would seem a bit weird to me: how can QML know whether the object you return is a newly created one, or some object owned by some other object (and what if the object is "const"?)? > D) By QML accessing a Q_PROPERTY on a C++ object (ownership?). E) Implement your own QDeclarative component in C++, which could wrap your hard-to-expose-to-QML object, and let it implement properties and methods which expose only data types that are safe and easy to use in QML. [...] As I said, I don't have the knowledge to reply to your other questions; but my gut feeling is that if you need to know the answers, you have already lost. :-) The key, IMHO, is to find a way to design your software so that you use the toolkit to the extent that you rely only on its well-documented properties. Refactoring your code and making it simple will not only help you to make it work with QML, but also make it easier for you to maintain it. IMHO, whatever the answers to your questions, you should try to forget them immediately or at least not rely on them. It will make your life easier on the long run. :-) Ciao, Alberto [0]: http://blog.mardy.it/2012/05/from-g-to-q.html -- http://blog.mardy.it <- geek in un lingua international! ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development