I'm wondering about how to (using C++11 and hopefully with backwards (boost or TR1) compatible smart pointer types) achieve:
One class instance (ModelController) owns a resource (InputConsumer), while another component (InputSender, which in this case is a singleton) has access to it.
The model is InputSender holds a list of references to InputConsumers, of which there will be many.
ModelController may have none, one, or many InputConsumers, and there may be many ModelControllers. The InputSender is NOT aware.
Here's what would be nice: A way for InputSender to track the InputConsumers assigned to it, in such a way that it can find out for itself whether the individual InputConsumers are valid or not.
It seems to me that weak_ptr is perfect for this purpose as their use requires checking this condition.
If InputSender stops tracking any of its weak_ptr refs, nothing bad happens, the corresponding InputConsumers will just experience radio silence.
If a ModelController is deleted, or if a ModelController deletes some of its InputConsumers, any InputSenders that have registered with them will recognize at the next time they try to access them that they no longer exist, and can clean up, without the need to send a message or do anything.
So the question is, is this an appropriate situation for using shared_ptr and weak_ptr? I wonder if shared_ptr is completely appropriate because the InputConsumers are conceptually owned by their ModelControllers, so they should be member variables. I dunno how much sense it makes for ModelController to only manage them via shared_ptr. I can't tell if unique_ptr works together with weak_ptr. Am I supposed to just manage the shared_ptrs in ModelController's ctor/dtor?
There may also be a well-known (not to me!) design pattern that this falls into, so if anyone knows of such a thing please tell me.
I do not have a lot of expertise in shared pointers, but yes, this seems a very appropriate use of
weak_ptr.In this case, you are just annoyed that:
InputConsumers directly as members ofModelControllers, since its a trivial ownership relation.shared_ptrto make it work with aweak_ptr.I think this is solved by using a
shared_ptras an alias of a member object. According to C++.com:I never did it myself, but this seems adapted to your situation:
InputConsumers members ofModelControllersshared_ptrfor each of themInputSenderusingweak_ptrsEDIT
Here is a complete minimal working example:
It prints:
The tricky part is to be able to create a
weak_ptrtoowner->foo1(would be the same forfoo2). To do that, we first need ashared_ptrthat is an alias ofowner->foo1. This can only be done by:where
other_shared_ptris ashared_ptr<T>whose lifetime is at least as long as the one ofowner->foo1. To achieve this, using ashared_ptr<T>which is also a member ofowneris a good idea, since it ensures the lifetime would be the same. Finally, we need a valid non-null pointer to give to it, and since we don't want to create anything on the heap, we must use an existing object.thisis a good candidate, since we know it is valid and get destroyed only after its members are destroyed. Hence ourother_shared_ptris for instance:However, this means that when
selfgets out of scope, i.e. during the destruction ofowner, it will calldelete this. We do not want this deletion to occur, otherwisethiswould be deleted twice (which is undefined behaviour, in practice a segfault). Hence we also provide to the constructor ofselfa Deleter that actually doesn't delete anything.The rest of the code should be self-explanatory with the comments.