help boost::bind and shared pointers

Started by
11 comments, last by chairthrower 15 years, 11 months ago
i dont understand the bind used inside the bind, chairthrower :S

and i was hoping it not to throw, but do nothing. (just not do the call if the instance has been destroyed).

http://www.teatromagico.net
Advertisement
It seems I have completely misunderstood the issue.
It seems the OP doesn't want the callback to own the object (seems fairly weird to have a callback that can become empty at any time though)
Quote:i dont understand the bind used inside the bind, chairthrower :S


The inner bind is to yield a strong (shared_ptr) reference from the weak pointer. This has to be delayed until the time of the call and hence it is another bind. i totally agree that the syntax becomes more complicatated (ugly) but with the way bind works i dont think its possible to avoid the inner bind() while having the safety that comes from the locking of the weak reference to yield a strong reference that can then be subsequently used safely.

note that
f = bind( &A::method, bind( from_weak( ap)),  _1  );


has the same effect as the below except that lock() doesnt throw unfortunately and save us from executing the outer bind function
f = bind( &A::method, bind( &weak_ptr< A>::lock, wp),  _1  );


I said before that we have to ensure that we have a strong reference for the entire duration of the call (not guaranteed by a raw pointer) to avoid the possibility of another thread releasing the resource while we are in the middle of the call. in fact the more obvious case is that the call itself could release shared references which in turn release the instance object while we are doing something with it. using the stron g ref we can delay these releases until after we have finished our work.

the exception stuff is just a cheap way of avoiding the real call if the instance has been destroyed and as means of communication to facilitate clearing the resource which is the bound function. you could use it something like this.

template< class C, class A0> void call_each( C &c, const A0 &a1) {    for( typename C::iterator ip = c.begin(); ip != c.end();)     {           bool ok = true;         try { (*ip)( a1); }        catch( const bad_weak_ptr &e) { ok = false; }        if( !ok) ip = c.erase( ip);         else ++ip;    }   }int main(){    list< function< void( int) > >  callbacks;    {    shared_ptr< A>  ap( new A);    callbacks.push_back( bind( &A::method, bind( from_weak( ap)),  _1  ));    }    // does nothing since ap is out of scope     call_each( callbacks, 123);}


Perhaps it would be better to explicitly test for the failure case and avoid the overhead of the exception. (boost::lambda::if_then ?). Another possibility is that more recent releases of boost 1.35 allow you to apply a visitor pattern which could be used to explicitly verify whether the object is ok to call. this is pretty cool- the problem is that in my experimentation at least its not possible to visit a boost::function because of the complete type erasure that goes on with boost::function. also its potentially quite slow.

The other tradeoff in the above approach is that we have dangling resources that persist until we come along and make the call and then potentially go about cleaning them up if the underlying instance is not in scope.


This topic is closed to new replies.

Advertisement