Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Nils Jeisecke
Hi,

On Wed, Apr 15, 2015 at 11:49 AM, André Somers an...@familiesomers.nl wrote:
 That's why I have been working with a RAII implementation to monitor
 property changes for a while now.

This looks like an interesting idea.

Another issue I often have with properties is performance related.
Imagine a model that has more than one filter property. In case that
two properties should be set, it does not make sense to update the
model twice. Adding a special setFilters method with multiple
arguments is no option if you want to use property binding in QML.

So I usually have a private update slot and a timer that's restarted
on each property invocation so that the model update will take place
on the next event loop iteration.

That guard could have a second parameter specifying a property
evaluation slot that is guaranteed to be invoked *once* on the next
event loop iteration. It might be tricky to manage the timer though,
maybe setting a special custom object property
__SLOT_NAME_invoke_timer storing the timer pointer could help? Or
- to get rid of the expensive timer - a flag could be stored as a
property controlling whether QMetaObject::invoke(this, SLOT_NAME,
Qt::QueuedConnection) should be called - the slot (or a c++11 lambda?)
would have to reset that flag then.

Thinking about this, maybe this functionality should be implemented in
a separate class.

Nils
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Matthew Woehlke
On 2015-04-15 10:43, Marc Mutz wrote:
 On Wednesday 15 April 2015 11:49:56 André Somers wrote:
 void MyClass::setFoo(QString value)
 {
PropertyGuard guard(this, foo);  //foo is the name of the Q_PROPERTY
Q_UNUSED(guard);

m_foo = value;
 }
 
 This is an interesting idea, though I don't think I have encountered the 
 problems with which you motivate PropertyGuard.
 
 For use in a library, though, I fear the string-based mechanism is too 
 inefficient. For use within QtWidgets, say, I'd suggest a mechanism that 
 works 
 on the member data directly.

FWIW I had the same thought; also, I'm not a fan of needing the
Q_UNUSED, or using a macro to 'hide' it.

What about something like this?

  QPropertyGuard g{this};
  g.addProperty(a); // use QObject::property
  g.addProperty(b, m_b); // take value member by reference
  g.addProperty(m_c, cChanged); // ...and also slot address

It's slightly redundant because declaring the guard and adding a
property are separate, but there is no unused object, and you can use
the same guard for multiple properties.

The implementation is trickier (probably you need a dynamically
allocated templated helper class with a virtual base to store the value
and check for changes), but avoids multiple string-based look-ups.

The slot could be a functor, like QObject::connect accepts, that could
be any of the actual slot, std::function, lambda, etc.

-- 
Matthew

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread André Somers
Hi Marc,

Thank you for responding.

Marc Mutz schreef op 15-4-2015 om 16:43:
 Hi André,

 On Wednesday 15 April 2015 11:49:56 André Somers wrote:
 void MyClass::setFoo(QString value)
 {
 PropertyGuard guard(this, foo);  //foo is the name of the Q_PROPERTY
 Q_UNUSED(guard);

 m_foo = value;
 }
 This is an interesting idea, though I don't think I have encountered the
 problems with which you motivate PropertyGuard.
Are you sure, or is your code just not secure? ;-)

Basically, if you have this code (or something like it) somewhere, you 
already have a problem:

void MyClass::setFooAndBar(QString foo, int bar)
{
   if (m_foo != foo) {
 m_foo = foo;
 emit fooChanged(foo);  //this is where things may start to go wrong 
already
   }

   if (m_bar != bar) {
 m_bar = bar;
 emit barChanged(bar);
   }
}

Calling separate setters instead from inside setFooAndBar doesn't help.

What happens if a slot connected to fooChanged uses the instance of 
MyClass? What property values does it see? foo is changed, but bar has 
not changed yet. What if that slot triggers something that ends up 
deleting the instance?

You'd have to write something like this instead:

void MyClass::setFooAndBar(QString foo, int bar)
{
   bool fooHasChanged(false);
   bool barHasChanged(false);

   if (m_foo != foo) {
 m_foo = foo;
 fooHasChanged = true;
   }

   if (m_bar != bar) {
 m_bar = bar;
 barHasChanged = true;
   }

   if (fooHasChanged) emit fooHasChanged(foo);
   if (barHasChanged) emit barHasChanged(bar); // we should check if 
we're still alive before we do this
}

I find my version easier to write and maintain:

void MyClass::setFooAndBar(QString foo, int bar)
{
   guardProperty(foo);
   guardProperty(bar);

   m_foo = foo;
   m_bar = bar;
}



 For use in a library, though, I fear the string-based mechanism is too
 inefficient. For use within QtWidgets, say, I'd suggest a mechanism that works
 on the member data directly.
I developed this still working on Qt4, and there its's all we have. Do 
you have a suggestion how to get access to the metaproperty without 
using the string lookup in Qt5? AFAIK, that is still string-based API. 
Perhaps it could be a constexpr though, as the value really wouldn't 
change at runtime (for normal C++ objects, not talking about dynamic 
generated stuff here)? I doubt that will actually work, but I have not 
played around with that enough yet.

Thanks for your comments though; speed is a real concern of course.

André

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Christian Kandeler
On 04/15/2015 05:12 PM, Matthew Woehlke wrote:
 [Valid points about the inconsistent state of the object elided.]

 On 2015-04-15 10:58, André Somers wrote:
 What if that slot [connected to the instance property changed
 signal] triggers something that ends up deleting the instance?

 Then the slot is broken. What if the sender needs to do something after
 it delivers the signal? What if other slots are connected? Deleting a
 signal sender from a slot connected to the signal is inherently
 dangerous. Don't do it.

While delete is probably the most extreme case, all other operations on 
the sender have the same conceptual problem. I'd even argue that the 
delete case is relatively benign, because it very likely fails loudly, 
rather than in some subtle way.


Christian

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Matthew Woehlke
[Valid points about the inconsistent state of the object elided.]

On 2015-04-15 10:58, André Somers wrote:
 What if that slot [connected to the instance property changed
 signal] triggers something that ends up deleting the instance?

Then the slot is broken. What if the sender needs to do something after
it delivers the signal? What if other slots are connected? Deleting a
signal sender from a slot connected to the signal is inherently
dangerous. Don't do it.

This is why we have deleteLater()...

IMO it's perfectly valid for an object to assume that emitting a signal
will not cause it to be deleted.

-- 
Matthew

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Keith Gardner
On Wed, Apr 15, 2015 at 9:38 AM Marc Mutz marc.m...@kdab.com wrote:

 Hi André,

 On Wednesday 15 April 2015 11:49:56 André Somers wrote:
  void MyClass::setFoo(QString value)
  {
 PropertyGuard guard(this, foo);  //foo is the name of the Q_PROPERTY
 Q_UNUSED(guard);
 
 m_foo = value;
  }

 This is an interesting idea, though I don't think I have encountered the
 problems with which you motivate PropertyGuard.

 For use in a library, though, I fear the string-based mechanism is too
 inefficient. For use within QtWidgets, say, I'd suggest a mechanism that
 works
 on the member data directly.

 Thanks,
 Marc


I have actually run into the same situation and made a template class that
owns the variable.  Its constructor takes an initial value and a
std::functionvoid (const T) as a callback for when the value changes.
The callback can be a lambda or a std::bind to the expected signal.  I also
added overloads to allow for the templated class to behave just like the
contained type so that it can be swapped in easily.  I figured the Qt
project wouldn't like the submission of the class due to its template
nature and its use of std::function but i am willing to share it if anyone
is interested.
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Marc Mutz
Hi André,

On Wednesday 15 April 2015 11:49:56 André Somers wrote:
 void MyClass::setFoo(QString value)
 {
PropertyGuard guard(this, foo);  //foo is the name of the Q_PROPERTY
Q_UNUSED(guard);
 
m_foo = value;
 }

This is an interesting idea, though I don't think I have encountered the 
problems with which you motivate PropertyGuard.

For use in a library, though, I fear the string-based mechanism is too 
inefficient. For use within QtWidgets, say, I'd suggest a mechanism that works 
on the member data directly.

Thanks,
Marc

-- 
Marc Mutz marc.m...@kdab.com | Senior Software Engineer
KDAB (Deutschland) GmbH  Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Keith Gardner

 I'd certainly be interested to seeing how you solved this, yes. Thanks!


I have made a repository for the class with an example.  Sorry that there
is no documentation for it.  It requires C++11 support for r-value
references, std::functional, and some type traits features.  In addition to
having a notify callback, it also provides an optional pre-notify callback
to let you know the current value and the value it will change to.

https://github.com/kreios4004/Property_Class
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Giuseppe D'Angelo
On 15 April 2015 at 17:12, Matthew Woehlke
mw_tr...@users.sourceforge.net wrote:

 Then the slot is broken. What if the sender needs to do something after
 it delivers the signal? What if other slots are connected? Deleting a
 signal sender from a slot connected to the signal is inherently
 dangerous. Don't do it.

For the record, there's some code in Qt to protect against this. I
believe the entire signal emission mechanism is designed to work
nonetheless (and tested), and you can probably grep for QPointer.*this
(f.i. in widgets code) to see other interesting cases. But I agree
it's damn difficult to design robust code this way.

-- 
Giuseppe D'Angelo
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Andre Somers

On 15-4-2015 16:54, Keith Gardner wrote:



On Wed, Apr 15, 2015 at 9:38 AM Marc Mutz marc.m...@kdab.com 
mailto:marc.m...@kdab.com wrote:


Hi André,

On Wednesday 15 April 2015 11:49:56 André Somers wrote:
 void MyClass::setFoo(QString value)
 {
PropertyGuard guard(this, foo);  //foo is the name of the
Q_PROPERTY
Q_UNUSED(guard);

m_foo = value;
 }

This is an interesting idea, though I don't think I have
encountered the
problems with which you motivate PropertyGuard.

For use in a library, though, I fear the string-based mechanism is too
inefficient. For use within QtWidgets, say, I'd suggest a
mechanism that works
on the member data directly.

Thanks,
Marc


I have actually run into the same situation and made a template class 
that owns the variable.  Its constructor takes an initial value and a 
std::functionvoid (const T) as a callback for when the value 
changes.  The callback can be a lambda or a std::bind to the expected 
signal.  I also added overloads to allow for the templated class to 
behave just like the contained type so that it can be swapped in 
easily.  I figured the Qt project wouldn't like the submission of the 
class due to its template nature and its use of std::function but i am 
willing to share it if anyone is interested.


I'd certainly be interested to seeing how you solved this, yes. Thanks!

André




___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Andre Somers
On 15-4-2015 17:08, Matthew Woehlke wrote:
 On 2015-04-15 10:43, Marc Mutz wrote:
 On Wednesday 15 April 2015 11:49:56 André Somers wrote:
 void MyClass::setFoo(QString value)
 {
 PropertyGuard guard(this, foo);  //foo is the name of the Q_PROPERTY
 Q_UNUSED(guard);

 m_foo = value;
 }
 This is an interesting idea, though I don't think I have encountered the
 problems with which you motivate PropertyGuard.

 For use in a library, though, I fear the string-based mechanism is too
 inefficient. For use within QtWidgets, say, I'd suggest a mechanism that 
 works
 on the member data directly.
 FWIW I had the same thought; also, I'm not a fan of needing the
 Q_UNUSED, or using a macro to 'hide' it.

 What about something like this?

QPropertyGuard g{this};
g.addProperty(a); // use QObject::property
g.addProperty(b, m_b); // take value member by reference
g.addProperty(m_c, cChanged); // ...and also slot address

 It's slightly redundant because declaring the guard and adding a
 property are separate, but there is no unused object, and you can use
 the same guard for multiple properties.

 The implementation is trickier (probably you need a dynamically
 allocated templated helper class with a virtual base to store the value
 and check for changes), but avoids multiple string-based look-ups.

 The slot could be a functor, like QObject::connect accepts, that could
 be any of the actual slot, std::function, lambda, etc.

I'm not sure I understand your solution, or what it yields over what I 
am using now. Of course what I do is not using multiple string lookups. 
The property is looked up once on construction of the guard object. Then 
the current value is copied as a QVariant, as it is made available 
through the property system. The signal meta-method is also stored from 
the constructor, so the destructor can use it. So, only one 
string-lookup needed per property. The elegance is that it uses the 
property system to get the value *and* the notification signal to 
trigger, so it is really easy to use.

The need for a Q_UNUSED is inherent in any RAII class that you don't 
explicitly use any more. It works without, but you get a warning about 
an unused variable which is annoying. QMutexLocker suffers from the same 
problem.

I also don't like using a macro much, but it does yield quite an elegant 
way to say what you want I think. It also hides the explicit reference 
to this. You can still use the explicit way too of course, especially if 
you want to access the guard object afterwards (you can cancel it and 
access the original value for instance).

I am currently not seeing a need to trigger anything else than the 
notification signal, but I guess that could be added if there is a need 
for that.

André



___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Matthew Woehlke
On 2015-04-15 12:29, Andre Somers wrote:
 On 15-4-2015 17:08, Matthew Woehlke wrote:
 What about something like this?

QPropertyGuard g{this};
g.addProperty(a); // use QObject::property
g.addProperty(b, m_b); // take value member by reference
g.addProperty(m_c, cChanged); // ...and also slot address

 It's slightly redundant because declaring the guard and adding a
 property are separate, but there is no unused object, and you can use
 the same guard for multiple properties.

 The implementation is trickier (probably you need a dynamically
 allocated templated helper class with a virtual base to store the value
 and check for changes), but avoids multiple string-based look-ups.

 The slot could be a functor, like QObject::connect accepts, that could
 be any of the actual slot, std::function, lambda, etc.

 I'm not sure I understand your solution, or what it yields over what I 
 am using now. Of course what I do is not using multiple string lookups. 
 The property is looked up once on construction of the guard object. Then 
 the current value is copied as a QVariant, as it is made available 
 through the property system. The signal meta-method is also stored from 
 the constructor, so the destructor can use it. So, only one 
 string-lookup needed per property. The elegance is that it uses the 
 property system to get the value *and* the notification signal to 
 trigger, so it is really easy to use.

The second form would thus save the value - QVariant comparison and
not much else. The third form however eliminates the string look-up
entirely by having the user provide both the backing member variable
*and* what to do when a change should be emitted. (I'd expect this to be
the change signal most of the time, but taking a functor adds the
flexibility of allowing users to do other things if needed.)

 The need for a Q_UNUSED is inherent in any RAII class that you don't 
 explicitly use any more. It works without, but you get a warning about 
 an unused variable which is annoying. QMutexLocker suffers from the same 
 problem.

Yes, but separating the construction and property binding eliminates
that (because you used the guard after all) and allows one guard to
track multiple properties, with a potential saving in memory complexity.
The down side is that it's a little more typing, so it's a trade-off.

-- 
Matthew

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Andre Somers
On 15-4-2015 18:44, Matthew Woehlke wrote:
 The second form would thus save the value - QVariant comparison and 
 not much else. The third form however eliminates the string look-up 
 entirely by having the user provide both the backing member variable 
 *and* what to do when a change should be emitted. (I'd expect this to 
 be the change signal most of the time, but taking a functor adds the 
 flexibility of allowing users to do other things if needed.)
Right, of course. That may be useful indeed. Thank you for your 
feedback, it is apreciated!

André

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Alan Alpert
On Wed, Apr 15, 2015 at 8:08 AM, Matthew Woehlke
mw_tr...@users.sourceforge.net wrote:
 On 2015-04-15 10:43, Marc Mutz wrote:
 On Wednesday 15 April 2015 11:49:56 André Somers wrote:
 void MyClass::setFoo(QString value)
 {
PropertyGuard guard(this, foo);  //foo is the name of the Q_PROPERTY
Q_UNUSED(guard);

m_foo = value;
 }

 This is an interesting idea, though I don't think I have encountered the
 problems with which you motivate PropertyGuard.

I have, it comes up a lot in objects used as an interface to QML
(where every fooChanged signal will probably trigger binding
re-evaluation or JS blocks). I don't think it's that hard to manage,
but PropertyGuard does look easier and saves some boilerplate code.

 For use in a library, though, I fear the string-based mechanism is too
 inefficient. For use within QtWidgets, say, I'd suggest a mechanism that 
 works
 on the member data directly.

I think it's fine to tie it to the property system, since conceptually
it needs a both a read and a notify on the datum.

For performance, allow passing in a metaproperty index instead of a
property name string. It will still invoke the getter, but they're
rarely that complicated (and when they are, you need to go off the
getter value*).

 FWIW I had the same thought; also, I'm not a fan of needing the
 Q_UNUSED, or using a macro to 'hide' it.

 What about something like this?

   QPropertyGuard g{this};
   g.addProperty(a); // use QObject::property
   g.addProperty(b, m_b); // take value member by reference
   g.addProperty(m_c, cChanged); // ...and also slot address

 It's slightly redundant because declaring the guard and adding a
 property are separate, but there is no unused object, and you can use
 the same guard for multiple properties.

The common case is one property I think, so keep that case to one
line. I'd envision using it in all my basic setters to save code at
the start of a project, and then when the features start to creep in
it's easier to add complexity into the setters.

Still, you could always leave in a convenience constructor or just
wrap it in a macro as before.

* Example of when you need to go off getter value instead of member is
usually sometime like implicit width, where the getter looks like
getWidth() {
if (m_width == -1)
return m_implicitWidth;
return m_width;
}
In this case, if you have m_width = 80, m_implicitWidth = 80, and call
setWidth(-1), then you actually don't want to emit widthChanged even
though m_width is updated.

That was just an example, not how implicit width actually is
implemented in QtQuick.

--
Alan Alpert
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Matthew Woehlke
On 2015-04-15 13:55, Alan Alpert wrote:
 The common case is one property I think, so keep that case to one
 line. I'd envision using it in all my basic setters to save code at
 the start of a project, and then when the features start to creep in
 it's easier to add complexity into the setters.

If you use the helper class always, sure. I was thinking I probably
would not use it for the easy cases, i.e. where only one value
changes, and instead use it only where it becomes more important to have
the helper, in which case it's more likely you have two or more values.
Anyway...

 Still, you could always leave in a convenience constructor or just
 wrap it in a macro as before.

...there's always this :-). The case with one property (or, for that
matter, if you don't care about having multiple instances of the helper)
can still use a macro to collapse the two lines of code that either
version needs.

For that matter, the addProperty flavor doesn't preclude having
convenience ctors that also call addProperty :-).

-- 
Matthew

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Keith Gardner
On Wed, Apr 15, 2015 at 2:20 PM Andre Somers an...@familiesomers.nl wrote:

 On 15-4-2015 21:05, Keith Gardner wrote:

 QPropertyGuard g{this};
g.addProperty(a); // use QObject::property
g.addProperty(b, m_b); // take value member by reference
g.addProperty(m_c, cChanged); // ...and also slot address

 There's type erasure going on, so it will allocate memory. Allocating
 memory
 in a setter that might just change an int is what I call inefficient.


  Would something like this be better?

  // constructor
 // Provide an initial value and a std::function to notify about the change
 Propertybool m_example = Propertybool(false, [](bool value){
 emit exampleChanged(value);
 });

  // getter
 bool *::example() const {
 return m_example;
 }

  // setter
 void *::setExample(bool value) {
 m_example = value;
 }

  The working code for this example can be found
 https://github.com/kreios4004/Property_Class.

  Thank you for posting that.

 I took a look at it, but I am not sure it actually solves much. It moves
 the check if something changed to the wrapped variable, but it makes using
 that value then more complicated. Instead of using the variable directly,
 one now has to go through m_example.getValue() everywhere.


This is partially true.  If it is containing a class or a struct, then you
are correct.  If it is an int or float and you want to perform some math
operation with it, it has the operator const T() to perform the get
automatically.


 Not pretty, I think. The case of modifying more than one property in one
 go is also not solved. On the one hand, dependent properties (such a
 isValid property) are not updated unless you manually write that code
 again, and on the other hand if you use this to set more than one property
 in a method, you still are sending signals at the point the class is in an
 inconsistent state.


True.  My goal was to perform a type safe way of change detection so I
wouldn't have to write the boilerplate code over and over.  It also
provides a way customize the way the signal is called in the callback.  It
does suffer in the more complex scenarios when more than one operation is
happening to the object.


 One nice side effect of my implementation is that the notification is
 actually only send once. Even if the property value is changed multiple
 times in the meantime, you still get only one notification. That can be
 very convenient, even if you don't use it much.


This is very appealing.
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Marc Mutz
On Wednesday 15 April 2015 16:58:24 André Somers wrote:
 Basically, if you have this code (or something like it) somewhere, you 
 already have a problem:
 
 void MyClass::setFooAndBar(QString foo, int bar)
 {
if (m_foo != foo) {
  m_foo = foo;
  emit fooChanged(foo);  //this is where things may start to go wrong 
 already
}
 
if (m_bar != bar) {
  m_bar = bar;
  emit barChanged(bar);
}
 }

1. This function has more than one responsibility. Functions with more than
   one responsibility are hard to get right, to maintain, and in general
   hard to make exception-safe.
2. This function doesn't have all-or-nothing / transactional semantics.

That's basically both different way of saying that functions should be 
structured such that they:

1st perform anything that can fail _without_ modifying the state of the 
program
2nd commit the new state with never-fail operations
3rd clean up (this includes notification)

 void MyClass::setFooAndBar(QString foo, int bar)
 {
 
bool fooHasChanged(false);
bool barHasChanged(false);

if (m_foo != foo) {

  m_foo = foo;
  fooHasChanged = true;

}

if (m_bar != bar) {

  m_bar = bar;
  barHasChanged = true;

}

if (fooHasChanged) emit fooHasChanged(foo);
if (barHasChanged) emit barHasChanged(bar); // [...]
 }

This code still doesn't meet that goal. It first modifies m_foo. If the 
assignment to m_bar throws, then m_foo has been changed, but m_bar hasn't.

void MyClass::setFooAndBar(QString foo, int bar)
{
   const bool fooHasChanged = m_foo != foo;
   const bool barHasChanged = m_bar != bar;

   m_foo.swap(foo);
   m_bar = bar;  // int can't throw

   if (fooHasChanged) emit fooHasChanged(m_foo);
   if (barHasChanged) emit barHasChanged(m_bar);
}

Untested code:

#define EMIT_AT_SCOPE_EXIT_WHEN_CHANGED(value, signal) \
  struct Guard##value {
  decltype(value) oldValue;
  decltype(value) ref;
  ~Guard##value() { if (ref != oldValue) emit signal(ref); }
  } guard##value = { value, value };

For C++98, the type would have to be passed instead of using decltype.
It's still less efficient than it could be, due to oldValue (imagine it being 
a std::vector), but that can be fixed at the cost of more arguments. Maybe a 
lot of this stuff can also be templatised, to effectively get something like:

const GuardBase valueGuard = guard(value, signal);

But if the call to signal in this local scope is still indirect, as it is with 
most function pointers, this is still a no-no, imo.

Thanks,
Marc

-- 
Marc Mutz marc.m...@kdab.com | Senior Software Engineer
KDAB (Deutschland) GmbH  Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Marc Mutz
On Wednesday 15 April 2015 17:08:11 Matthew Woehlke wrote:
 FWIW I had the same thought; also, I'm not a fan of needing the
 Q_UNUSED, or using a macro to 'hide' it.

I haven't had to use Q_UNUSED on a RAII object since iirc GCC 3 times. What 
broken compilers are you guys using?

 What about something like this?
 
   QPropertyGuard g{this};
   g.addProperty(a); // use QObject::property
   g.addProperty(b, m_b); // take value member by reference
   g.addProperty(m_c, cChanged); // ...and also slot address

There's type erasure going on, so it will allocate memory. Allocating memory 
in a setter that might just change an int is what I call inefficient.

Thanks,
Marc

-- 
Marc Mutz marc.m...@kdab.com | Senior Software Engineer
KDAB (Deutschland) GmbH  Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Keith Gardner

QPropertyGuard g{this};
g.addProperty(a); // use QObject::property
g.addProperty(b, m_b); // take value member by reference
g.addProperty(m_c, cChanged); // ...and also slot address

 There's type erasure going on, so it will allocate memory. Allocating
 memory
 in a setter that might just change an int is what I call inefficient.


Would something like this be better?

// constructor
// Provide an initial value and a std::function to notify about the change
Propertybool m_example = Propertybool(false, [](bool value){
emit exampleChanged(value);
});

// getter
bool *::example() const {
return m_example;
}

// setter
void *::setExample(bool value) {
m_example = value;
}

The working code for this example can be found
https://github.com/kreios4004/Property_Class.
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Andre Somers

On 15-4-2015 21:05, Keith Gardner wrote:


  QPropertyGuard g{this};
   g.addProperty(a); // use QObject::property
   g.addProperty(b, m_b); // take value member by reference
   g.addProperty(m_c, cChanged); // ...and also slot address

There's type erasure going on, so it will allocate memory.
Allocating memory
in a setter that might just change an int is what I call inefficient.


Would something like this be better?

// constructor
// Provide an initial value and a std::function to notify about the change
Propertybool m_example = Propertybool(false, [](bool value){
emit exampleChanged(value);
});

// getter
bool *::example() const {
return m_example;
}

// setter
void *::setExample(bool value) {
m_example = value;
}

The working code for this example can be found 
https://github.com/kreios4004/Property_Class.



Thank you for posting that.

I took a look at it, but I am not sure it actually solves much. It moves 
the check if something changed to the wrapped variable, but it makes 
using that value then more complicated. Instead of using the variable 
directly, one now has to go through m_example.getValue() everywhere. Not 
pretty, I think. The case of modifying more than one property in one go 
is also not solved. On the one hand, dependent properties (such a 
isValid property) are not updated unless you manually write that code 
again, and on the other hand if you use this to set more than one 
property in a method, you still are sending signals at the point the 
class is in an inconsistent state.


One nice side effect of my implementation is that the notification is 
actually only send once. Even if the property value is changed multiple 
times in the meantime, you still get only one notification. That can be 
very convenient, even if you don't use it much.


André

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


Re: [Development] RFC: RAII for property changes

2015-04-15 Thread Marc Mutz
On Wednesday 15 April 2015 21:05:39 Keith Gardner wrote:
 Would something like this be better?
 
 std::function

No, a std::function in general allocates memory and even if it uses the small 
object optimisation, the call to the lambda will still be indirect.

Thanks,
Marc

-- 
Marc Mutz marc.m...@kdab.com | Senior Software Engineer
KDAB (Deutschland) GmbH  Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts
___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development


[Development] RFC: RAII for property changes

2015-04-15 Thread André Somers
Hi,

When writing QObject-derived classes with properties, I often found 
myself writing code like this:

void MyClass::setFoo(QString value)
{
   if (m_foo != value) {
 m_foo = value;
 emit fooChanged(m_foo);
   }
}

Trivial enough, in the simple case. However, when more than one property 
is involved at the same time, or properties depend on each other, things 
can get way less simple and more error-phrone quickly, I found. If the 
order of signals matters (and I found it does some times!), it gets even 
more tricky to get things right. This is especially tricky because you 
really would like to emit the signal at the moment the class is in a 
consistent state. That is, if you have a method that sets both width and 
height of an object at the same time, you really don't want to emit the 
signal about the change of one property before the change of another 
property is also set. In this case, the change may be harmless (but 
potentially expensive, as perhaps two relayouts are triggered when only 
one was needed), but there are cases where you'd really expose the class 
in an inconsistent state if you emit too soon. Considder that at the 
moment you emit, you give other code the change to do whatever its wants 
again, including calling methods on your class, even the very same 
method they just called, or worse, delete it... Your class better be in 
a consistent state when they do such things.

That's why I have been working with a RAII implementation to monitor 
property changes for a while now. The idea is that you instantiate a 
RAII class to monitor a property at the beginning of a method that _may_ 
change the property value, and then do all you want. Upon destruction of 
the RAII class, it checks if the property value changed and if it did, 
emit the associated signal.

The code I now write looks like this:

void MyClass::setFoo(QString value)
{
   PropertyGuard guard(this, foo);  //foo is the name of the Q_PROPERTY
   Q_UNUSED(guard);

   m_foo = value;
}

which then is further simplified by creating a small macro called 
guardProperty to this:

void MyClass::setFoo(QString value)
{
   guardProperty(foo);  //foo is the name of the Q_PROPERTY
   m_foo = value;
}

Note that you can guard as many properties as you need:

void MyClass::setFoo(QString value)
{
   guardProperty(foo);  //foo is the name of the Q_PROPERTY
   guardProperty(isValid); //the isValid property depends on m_foo as well

   m_foo = value;
}


The PropertyGuard class itself is quite simple in its basic form. It 
uses QMetaObject to read the current value and find the notify signal 
for the property. Upon desctruction, it compares the current value to 
the initial value stored at creation, and if the two don't match, the 
signal is emitted. The code deals with signals with zero or one 
arguments, assuming that in the latter case the one argument is the new 
property value.

I found this little device to be very useful in practice. Not so much in 
trivial setters like the ones on top (but still useful there, as the 
intent is clearer and there is less typing), but very much so in 
non-trivial cases where more than one property may change at a time or 
other complex interactions take place. In cases where a method changing 
should trigger other property changes as well, while not exposing 
inconsistent states of the class I found the device to be extremely 
valuable, as I can be sure that the emits are done at a moment where the 
state of class is fully consistent. I find myself writing emit less and 
less.


So, what are your opinions on using a mechanism like this? I have not 
found it in Qt itself, but perhaps others here are already using similar 
methods or perhaps very different methods to tackle the issues I described?

Looking forward to your comments,


André Somers

___
Development mailing list
Development@qt-project.org
http://lists.qt-project.org/mailman/listinfo/development