[smart_ptr] Sole ownership of shared_ptr?

Hi everyone, Over the past few days I have been trying to integrate Boost smart pointers into my system, which is basically a manager (ObjectManager) class which creates, destroys, and keeps track of instances of another class (Object). The manager keeps a std::map of instances of type shared_ptr. The manager has a createObject() method which returns a shared_ptr instance to the user, thus the user becomes an owner of the object, alongside the manager. My problem arises because I want objects to _always_ be destroyed when the manager method destroyObject() is called. I realise that part of the reason to use smart pointers is to prevent data from being deleted while a reference to it still exists, but I figure they are still worth using just for the safety aspect. My specific reasons for wanting the manager to be able to destroy the objects on command are: 1.) The manager may keep track of the objects, but the objects are used elsewhere in the system (until their destruction). 2.) I don't want to put the responsibility with the user (me!) to have to delete all references to the object in order for it to be deleted. Even if I pass back a weak_ptr, it is likely that the user will store a locked version of the pointer for convenience. 3.) I am using lua, which has no C-style "delete" command, and handles object deletion in its own time. Thus, even if all references to the object have been deleted in lua, the object may not actually be deleted straight away (unless you invoke deletion by calling collectgarbage(), which is a very messy solution). Anyway, I came up with a solution, but am not sure if there is any better or cleaner way. I am relatively new to smart pointers and the whole idea of virtual methods, so if I use the wrong terminology I apologise. Here goes: I have an abstract ObjectInterface class, which outlines all the methods that the user will access. I then have an Object class, which is of type ObjectInterface, and implements its abstract methods. The ObjectManager will, as before, create and store a map of shared_ptr references. However, instead of returning a shared_ptr to the user, the ObjectManager::createObject() method now creates a shared_ptr<ObjectHandle> which it returns to the user. ObjectManager doesn't store a reference to the handle, so the user is the sole owner of that. ObjectHandle (I'm not sure this is the correct use of the term "Handle"?) is also of type ObjectInterface, but in its constructor it takes a shared_ptr reference from the ObjectManager, which it stores internally as a weak_ptr (so that ObjectManager remains the sole owner of Object). It implements the ObjectInterface methods by forwarding calls from the user to the Object, but only if the weak_ptr hasn't expired. I am also storing a raw pointer to the Object in ObjectHandle, so that it doesn't have to call shared_ptr<>::lock() every time it needs to forward a call; I think this is reasonable to do since I never copy the pointer, and certainly won't delete it. Attached is a fully working example that I have tried to make as concise and clear as possible. Maybe my solution is the best one and my question seems stupid, or maybe there is a far simpler way and my solution seems stupid, but either way I am asking because I am unsure about this kind of thing in general. Thanks very much for any help in advance! Joe http://www.nabble.com/file/p16528658/smart_ptr_example.cpp smart_ptr_example.cpp -- View this message in context: http://www.nabble.com/-smart_ptr--Sole-ownership-of-shared_ptr--tp16528658p1... Sent from the Boost - Users mailing list archive at Nabble.com.

I had recently run into a similar problem, trying to use shared_ptr as a giant hammer to be used in every case. My problem was with a multi-threaded simulation. I was using a factory object to create the major components of this system. These components then would execute in their own thread, with various association between these components, all implemented in terms of smart_ptrs. I had properly synchronized access to these components, and everything worked fine -- most of the time. It seems that if one of the components was short-lived, it could actually execute and be "destroyed" before the factory function released its shared_ptr. I put "destroyed" in quotes because the factory function was not allowing the destruction until a later time. This of course resulted in a deadlock. I guess the moral of the story is that although smart_ptrs can eliminate a whole class of lifetime management problems, they are not the solution when you want to actively control the lifetime of your objects. If your ObjectManager is the sole object managing the lifetime of your Objects, why not just use raw pointers? Since ObjectManager needs to be able to destroy the objects at a particular time (its destruction), clients of these objects must already have some other method of determining if they are referencing a valid object, so they could check before dereferencing the pointer. Another possibilty is to track your objects as shared_ptrs, but only return weak_ptrs to the clients. Client needs to derefence the pointer, it simply converts to a shared_ptr. Just make sure you use it then lose it -- don't store the shared_ptr anywhere. As for your interface heirarchy, I would have to look at the code to comment more. However, it seems that if you use the smart_ptr/weak_ptr method I outlined, you would be able to simplify your design considerably. Hope this helps, Dan -----Original Message----- From: boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] On Behalf Of Joseph Thomson Sent: Sunday, April 06, 2008 3:41 PM To: boost-users@lists.boost.org Subject: [Boost-users] [smart_ptr] Sole ownership of shared_ptr? Hi everyone, Over the past few days I have been trying to integrate Boost smart pointers into my system, which is basically a manager (ObjectManager) class which creates, destroys, and keeps track of instances of another class (Object). The manager keeps a std::map of instances of type shared_ptr. The manager has a createObject() method which returns a shared_ptr instance to the user, thus the user becomes an owner of the object, alongside the manager. My problem arises because I want objects to _always_ be destroyed when the manager method destroyObject() is called. I realise that part of the reason to use smart pointers is to prevent data from being deleted while a reference to it still exists, but I figure they are still worth using just for the safety aspect. My specific reasons for wanting the manager to be able to destroy the objects on command are: 1.) The manager may keep track of the objects, but the objects are used elsewhere in the system (until their destruction). 2.) I don't want to put the responsibility with the user (me!) to have to delete all references to the object in order for it to be deleted. Even if I pass back a weak_ptr, it is likely that the user will store a locked version of the pointer for convenience. 3.) I am using lua, which has no C-style "delete" command, and handles object deletion in its own time. Thus, even if all references to the object have been deleted in lua, the object may not actually be deleted straight away (unless you invoke deletion by calling collectgarbage(), which is a very messy solution). Anyway, I came up with a solution, but am not sure if there is any better or cleaner way. I am relatively new to smart pointers and the whole idea of virtual methods, so if I use the wrong terminology I apologise. Here goes: I have an abstract ObjectInterface class, which outlines all the methods that the user will access. I then have an Object class, which is of type ObjectInterface, and implements its abstract methods. The ObjectManager will, as before, create and store a map of shared_ptr references. However, instead of returning a shared_ptr to the user, the ObjectManager::createObject() method now creates a shared_ptr<ObjectHandle> which it returns to the user. ObjectManager doesn't store a reference to the handle, so the user is the sole owner of that. ObjectHandle (I'm not sure this is the correct use of the term "Handle"?) is also of type ObjectInterface, but in its constructor it takes a shared_ptr reference from the ObjectManager, which it stores internally as a weak_ptr (so that ObjectManager remains the sole owner of Object). It implements the ObjectInterface methods by forwarding calls from the user to the Object, but only if the weak_ptr hasn't expired. I am also storing a raw pointer to the Object in ObjectHandle, so that it doesn't have to call shared_ptr<>::lock() every time it needs to forward a call; I think this is reasonable to do since I never copy the pointer, and certainly won't delete it. Attached is a fully working example that I have tried to make as concise and clear as possible. Maybe my solution is the best one and my question seems stupid, or maybe there is a far simpler way and my solution seems stupid, but either way I am asking because I am unsure about this kind of thing in general. Thanks very much for any help in advance! Joe http://www.nabble.com/file/p16528658/smart_ptr_example.cpp smart_ptr_example.cpp -- View this message in context: http://www.nabble.com/-smart_ptr--Sole-ownership-of-shared_ptr--tp16528658p1 6528658.html Sent from the Boost - Users mailing list archive at Nabble.com. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (2)
-
Daniel J. Kelly
-
Joseph Thomson