Re: [Development] On QML, ownership, QObject-trees and QSharedPointer

2012-06-01 Thread Rene Jensen

 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

2012-05-30 Thread Stephen Kelly
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

2012-05-29 Thread Rene Jensen

 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

2012-05-24 Thread Alberto Mardegan
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
QSharedPointerQObject 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 QSharedPointerQObject 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

2012-05-24 Thread Olivier Goffart
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
 QSharedPointerQObject 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

2012-05-24 Thread Thiago Macieira
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

2012-05-24 Thread Olivier Goffart
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 
QListQSharedPointerQObject  ?

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

2012-05-24 Thread Thiago Macieira
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
 QListQSharedPointerQObject  ?

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

2012-05-24 Thread Stephen Kelly
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 stephen.ke...@kdab.com | 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

2012-05-24 Thread christopher.adams
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

2012-05-24 Thread Kent Hansen
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

2012-05-23 Thread Alberto Mardegan
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


Re: [Development] On QML, ownership, QObject-trees and QSharedPointer

2012-05-23 Thread Thiago Macieira
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 QSharedPointerQObject 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

2012-05-23 Thread marius.storm-olsen
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 QSharedPointerQObject 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

2012-05-23 Thread Atlant Schmidt
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 QSharedPointerQObject 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

2012-05-23 Thread christopher.adams
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 property) depending on factors
 not quite clear to me.
 
 Question: