shared_ptr : how to build object chain shared_ptr down and weak_ptr up in object ctor?

I'd like to build a chain of objects with an upper layer holding a shared_ptr to a lower layer and the lower layer holding a weak_ptr back to the upper layer. The upper layer users the shared_ptr for control. The lower layer uses the weak_ptr for callbacks (first calling lock to convert it to a shared_ptr). And ... I'd like to do it in my class ctors. That's the kicker. It *seems* like the shared_from_this framework should give me what I want... #include <boost/weak_ptr.hpp> #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> class CIControl { virtual bool ControlOne(const bool) = 0; }; typedef boost::shared_ptr<CIControl> CIControlSPtr; class CICallback { virtual bool OnControlOneComplete(const bool) = 0; }; typedef boost::weak_ptr<CICallback> CICallbackWPtr; typedef boost::shared_ptr<CICallback> CICallbackSPtr; class CSlave : public CIControl { const CICallbackWPtr pUp_; public: CSlave(const CICallbackSPtr& p) : pUp_(p) { } bool ControlOne(const bool a) { return a; } }; class CMaster : public CICallback, public CIControl, public boost::enable_shared_from_this<CMaster> { CIControlSPtr pDown_; public: CMaster() : pDown_(CIControlSPtr(new CSlave(shared_from_this())) {} bool ControlOne(const bool a) { return a; }; bool OnControlOneComplete(const bool a) { return a; } }; void main(void) { CIControlSPtr p(new CMaster()); } Heck, it compiles and links Ok... :) But when I run it, shared_from_this() in the CMaster() ctor initializer for pDown_ asserts. It looks to me like the problem is there's no shared_ptr for CMaster itself, yet. We're still in the ctor, we have yet to return to main() to initialize "CIControlSPtr p". One answer is two-part initialization. First the ctor. Then a "bind" method to pass the fully-constructed shared_ptr down to the lower class to so it can initialize it's weak pointer back up. But it'd be nicer to do it in the ctor. For one thing, the weak_ptr can be const. I remember solving a similar problem creating COM objects wrapped in smart pointers by artificially bumping the refcount up (and down again) during object creation. But I haven't got my boost-brains sufficiently revved up to figure out if such a trick is possible in boost. Thanks, Tom Titchener

(apologies for starting a new response thread cloned from this, which I confess I lost in my inbox)
I'd like to build a chain of objects with an upper layer holding a shared_ptr to a lower layer and the lower layer holding a weak_ptr back to the upper layer. The upper layer users the shared_ptr for control. The lower layer uses the weak_ptr for callbacks (first calling lock to convert it to a shared_ptr). And ... I'd like to do it in my class ctors. That's the kicker. It *seems* like the shared_from_this framework should give me what I want...
I can't solve your particular problem, but it seems to be that using a weak pointer is the wrong solution in your example code. The callback is a member of the control, and thus cannot outlive it. In other words, the weak pointer ought to be superfluous - use an ordinary pointer. If the callback can actually outlive the control, then it shouldn't be the control that creates it. External code should create the callback and pass it the shared_ptr to an existing control.
Sebastian Redl
I don't think I specified my problem adequately. The layers are part of a communications framework that terminates at an API that manages a thread pool from which notifications are delivered. My goal is to use the weak_ptr -> shared_ptr conversion to independently manage the lifetime of the upper layers. If the conversion fails, the lower layer knows to cleanup context and continue. I'd like to leverage the thread safety of the conversion for a simple design that doesn't require a monitor to coordinate object lifetimes. I can achieve this by adding a binding step to the layer instantiation. But I'd rather do it through the ctors, if I could just figure out how to jigger the ref count framework... Thanks, TT
participants (1)
-
Tom Titchener