Boost logo

Boost Users :

Subject: Re: [Boost-users] [signals2][review] The review of the signals2 library (formerly thread_safe_signals) begins today, Nov 1st
From: Frank Mori Hess (frank.hess_at_[hidden])
Date: 2009-02-11 16:17:55


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Wednesday 11 February 2009 15:08 pm, Nat Goodspeed wrote:
> Frank Mori Hess wrote:
> > I have added a thread-UNsafe boost::signals2::trackable to svn to ease
> > porting of single-threaded Boost.Signals code that doesn't need to be
> > made thread-safe.
>
> That will be useful transitionally if we can count on a thread-safe
> boost::signals2::trackable arriving later. If signals2::trackable would
> only ever be thread-unsafe, it's not useful to us.

It's intended for people who don't want to bother rewriting a lot of
Boost.Signals code that doesn't need thread-safety.

> With an instance 'smartptr' of ListenerClass derived from
> boost::trackable, I'd like to write something like:
>
> holler.listen(boost::bind(&ListenerClass::method, smartptr, _1));
>
> If my listen() method were able to tease apart the object returned from
> bind(), it could detect the case of a shared_ptr<boost::trackable
> subclass>.

It could, by using boost::visit_each. boost::bind supports visit_each to let
you apply a visitor to all the objects bound inside the returned functor.
The signals libraries use visit_each to discover trackable objects that have
been bound into slots.

> Since I don't know how to do that, I've introduced a number of
> alternative ways to get disconnect-on-destruction. I don't yet know
> which, if any of them, will become the prevalent idiom. None is as
> easy/foolproof as boost::trackable, since each requires the caller to
> explicitly request connection management.
>
> Maybe I'm overlooking something that would make my life much easier --
> suggestions welcome!

I would spend some time learning how to use visit_each with bind. You could
implement a wrapper function that inspects slots for your own Trackable base
class objects, and then takes whatever step is needed to extract a shared_ptr
and pass it to slot::track before connecting.

> 2. For transient objects not managed by shared_ptr, I've also introduced
> a Trackable base class containing
> boost::ptr_vector<boost::signals2::scoped_connection> mConnections;
>
> The Trackable::track(const connection& c) method does this:
> mConnections.push_back(new scoped_connection(c));
>
> So destroying a Trackable subclass object disconnects any connections
> passed to track().

Just a note: you need to be careful about connecting these transient objects,
since the signal can't employ shared_ptr to prevent them from destructing in
mid-signal invocation.

> 3. One of my colleagues has a class that (with my changes) now also
> wraps a boost::signals2::signal. He strongly dislikes the variation
> between my listen(const slot_type&) and listen(method ptr, shared_ptr)
> methods, so he's changed his own connectFor() method as follows:
>
> template <typename POINTER>
> connection connectFor(const slot_type& slot, const POINTER& ptr)
> {
> connection c(mSignal.connect(slot));
> Trackable* isTrackable(dynamic_cast<Trackable*>(ptr));
> if (isTrackable)
> {
> isTrackable->track(c);
> }
> return c;
> }

Again, with this usage the signal can't prevent destruction in mid-signal
invocation.

> A thread-safe boost::signals2::trackable mechanism would allow us to
> drop back to a single universal call:
>
> holler.listen(boost::bind(&SomeClass::method, ptr, _1));
>
> with connection management automatically engaged as appropriate.

You can implement this now, once you get some experience with visit_each.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFJk0CD5vihyNWuA4URAoyIAJ9u1cmheH4+MQx9hhLIZzGg41+x2gCg3Bat
24TIJ9OQCAAyQUXdr+90sqo=
=JPSL
-----END PGP SIGNATURE-----


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net