
I'd love to get some feedback on a tiny utility I've been thinking about. I oftenly create small objects which I just want to keep alive as long as some other object exists. It is often RAII objects, but many other types of small classes fall into this category. A simple "user heap" could take ownership of such instances and delay deletion until itself is deleted. The basic interface of - let's call it heap - would look like this: template<class T> T& heap::put(T*); Example usage: boost::shared_ptr<SomeView> view; // Keep controller alive while view exits view->get_heap().put(new SomeController(*view)); For classes with loads of RAII object members, usage could look like this: class Foo { Foo() { keep_alive_.put(new RAIIBar(...)); keep_alive_.put(new RAIIWhatever(...)); } private: heap keep_alive_; }; Support should be added for putting shared_ptrs and auto_ptrs. I have a wide variety of naming suggestions and an extended interface for premature deletion but I'll save those for a later post. What do you think? Please give me your thoughts. Johan

Hi, Johan Torp schrieb:
A simple "user heap" could take ownership of such instances and delay deletion until itself is deleted. The basic interface of - let's call it heap - would look like this:
That would be very similar to a ptr_* container that assumes ownership of the object, with a common base class for all the objects to facilitate destruction. Simon

Simon Richter-2 wrote:
That would be very similar to a ptr_* container that assumes ownership of the object, with a common base class for all the objects to facilitate destruction.
Glad to get some response :) Requiring a common base class/interface is a huge demand. This would couple client code a lot for the sake of such a small utility and it wouldn't be directly compatible with already existing classes. The proposed "heap" has very different semantics compared to a container. Once you put something in the heap you never want to access it again. All you want to achieve is delayed and synchronized destruction. You can achieve similar functionality using a std::vector<boost::any> in which you insert boost::shared_ptrs. The syntax is a lot worse though and more importantly, more difficult to understand. Compare: std::vector<boost::any> keep_alive; // Always use named smart ptrs boost::shared_ptr<boost::signals::scoped_connection> connection(new boost::signals::scoped_connection(signal, slot)); keep_alive.push_back(connection); boost::heap keep_alive; keep_alive.put(new boost::signals::scoped_connection(signal, slot)); In the latter case we clearly signal something - we're not interested in the connection variable, only it's lifetime. Johan -- View this message in context: http://www.nabble.com/RFC---lifetime-management-tf4425074.html#a12663742 Sent from the Boost - Dev mailing list archive at Nabble.com.

For classes with loads of RAII object members, usage could look like this:
class Foo { Foo() { keep_alive_.put(new RAIIBar(...)); keep_alive_.put(new RAIIWhatever(...)); } private: heap keep_alive_; };
To me, that sounds very much like a std::vector<boost:shared_ptr<void>
:
typedef std::vector<boost::shared_ptr<void> > heap; class Foo { Foo() { keep_alive_.push_back(boost::shared_ptr<RAIIBar>(new RAIIBar(...))); keep_alive_.push_back(boost::shared_ptr<RAIIWhatever>(new RAIIWhatever(...))); } private: heap keep_alive_; }; Does this do what you intended? With a bit of syntactic sugar, it would be possible to avoid the intermediate shared_ptr type, probably. I consider all real work already done.
Support should be added for putting shared_ptrs and auto_ptrs.
You get this for free with the above.
I have a wide variety of naming suggestions and an extended interface for premature deletion but I'll save those for a later post.
keep_alive_.erase(keep_alive_.begin()+n); Should do that. Again, some syntactic sugar might help. Is that what you thought about? Yours, Martin. -- Dr. Martin Schulz (schulz@synopsys.com) Software Engineer Synopsys GmbH Karl-Hammerschmidt-Str. 34 D-85609 Dornach, Germany Munich office: +49 (89) 993-20203 Home office: +49 (721) 6099511 http://www.synopsys.com

Martin Schulz-3 wrote:
To me, that sounds very much like a std::vector<boost:shared_ptr<void> [snip] Does this do what you intended?
With a bit of syntactic sugar, it would be possible to avoid the intermediate shared_ptr type, probably. I consider all real work already done.
Is that what you thought about?
Yes that's basically it! I often create std::vector<boost::any> containing boost:shared_ptrs. Using std::vector<boost::shared_ptr<void> > is clearer and lessens the need for this utility class a bit. Still, the heap class is even more clear, easier to use and easier to reason about. I see the following benefits over std::vector<boost::shared_ptr<void> >: 1. More informative class and method names 2. You can't access anything put in the heap through the heap. This makes code analysis a lot easier. For instance, using heap.put(new Foo) you are sure noone can access the Foo instance at all. 3. There is no way to delete something in a heap or clear it so you are sure what's put will remain alive as long as the heap. (I no longer believe premature deletion is good idea). Heaps should be non-copyable, vectors aren't. 4. Because of 2 & 3 suitable classes (such as display list nodes) can expose a get_heap-method without risking the class's clients affecting each other or the instance. 5. Raw pointers can be handled more efficiently than shared_ptrs 6. Better syntax. Repeating a long type name twice as with boost shared_ptr can be tedious Still I'm not sure if these points are enough to motivate a new utility class. It's not exactly a killer app, even though I find it very useful in MVC architectures (linking controllers life time to views) and classes with lots of RAII members. What do you think? Thanks for your input! /Johan -- View this message in context: http://www.nabble.com/RFC---lifetime-management-tf4425074.html#a12766798 Sent from the Boost - Dev mailing list archive at Nabble.com.

Still, the heap class is even more clear, easier to use and easier to reason about. I see the following benefits over std::vector<boost::shared_ptr<void> >:
1. More informative class and method names
Well, the name heap makes me think of a certain kind of memory management system. Probably a name like Keepalive_bucket would be clearer?
Heaps should be non-copyable, vectors aren't.
Ok, that is a design choice and clearly influences the semantic.
5. Raw pointers can be handled more efficiently than shared_ptrs
But think of it - if that pointed-to object is in use by some other means, it would be destroyed by the heap destructor nevertheless. Using shared pointers, the pointed-to objects are kept alive as long as either the heap lives or as long they are used, whatever is longer.
6. Better syntax. Repeating a long type name twice as with boost shared_ptr can be tedious
Yes, I already noted that.
Still I'm not sure if these points are enough to motivate a new utility class. It's not exactly a killer app, even though I find it very useful in MVC architectures (linking controllers life time to views) and classes with lots of RAII members. What do you think?
If ist helpfull to you, then go ahead and use & improve it. An (untested) wrapper class I would start with would be something like: class Keepalive: private boost::noncopyable { Std::vector< boost::shared_ptr<void> > v; public: template <typename T> void put(boost::shared_ptr<T> p) { v.push_back(p); }; template <typename T> void put(std::auto_ptr<T>& p) { v.push_back(boost::shared_ptr<T>(p)); }; template <typename T> void put(T *p) { v.push_back(boost::shared_ptr<T>(p)); }; }; Does that solve your needs? -- Dr. Martin Schulz (schulz@synopsys.com) Software Engineer Synopsys GmbH Karl-Hammerschmidt-Str. 34 D-85609 Dornach, Germany Munich office: +49 (89) 993-20203 Home office: +49 (721) 6099511 http://www.synopsys.com

1. More informative class and method names
Well, the name heap makes me think of a certain kind of memory management system. Probably a name like Keepalive_bucket would be clearer?
Yes! There are probably even better names. Names might involve manual/garbage collection, owner, life time [synchronizer], delayed/synchronized destruction/or, respirator, reaper, .. well, probably getting a bit too creative here :) I'd love more suggestions/opinions though!
5. Raw pointers can be handled more efficiently than shared_ptrs
But think of it - if that pointed-to object is in use by some other means, it would be destroyed by the heap destructor nevertheless.
Creating a shared_ptr from a raw pointer has the same "problem". If users fail to realize this, they've misunderstood the whole point of the class.
An (untested) wrapper class I would start with would be something like:
class Keepalive: private boost::noncopyable { Std::vector< boost::shared_ptr<void> > v; public: template <typename T> void put(boost::shared_ptr<T> p) { v.push_back(p); }; template <typename T> void put(std::auto_ptr<T>& p) { v.push_back(boost::shared_ptr<T>(p)); }; template <typename T> void put(T *p) { v.push_back(boost::shared_ptr<T>(p)); }; };
Does that solve your needs?
Yes, this is basically what the implementation I'm using today I looks like. The question is if anybody else finds it useful. Again - thanks for your input! Johan -- View this message in context: http://www.nabble.com/RFC---lifetime-management-tf4425074.html#a12777199 Sent from the Boost - Dev mailing list archive at Nabble.com.
participants (3)
-
Johan Torp
-
Martin Schulz
-
Simon Richter