
Emil: Interesting twist. I haven't looked at shared_ptr before, but you are aware of the Lakos allocator model? www.open-std.org/jtc1/sc22/ wg21/docs/papers/2005/n1850.pdf It essentially advocates this approach. The whole STL can be made to follow that protocol, although in that document it is advocated that there is a pure abstract base class allocator, and that polymorphic instances be passed as allocator* (in actuality, pointing to an instance of a type derived from allocator). Doug, this seems to me what you are trying to achieve, but without the Lakos model... I've never actually looked at boost:shared_ptr in detail to see how it can keep an allocator and use it in the destructor, but I just did: it works b/c the shared_ptr holds a pointer to a polymorphic representation, i.e. a base class (not a template) with a virtual destructor (and other virtual functions that must know the template arguments), such that the class template (which knows the allocator and derives from the base representation class) can release memory when the base representation is destroyed. Interesting trick, shows the power of OO+templates combined. In order to destroy your function object with an allocator passed at construction, seems like you should be using the same trick, which requires that your function object stores a pointer to a wrapper which instantiates a class template (allocator being one of the tmpl args) that derives from a base representation with a virtual destructor. As best I understand... you can use the same trick by having a boost::function base manager which has a virtual manage member function, and dispatch this call to a derived class templated by the allocator. In that way, the base manager does not know about the allocator, so function object does not need to know either. Unfortunately, I can't be interested in implementing it, but if someone with time on their hands was wondering how it's done, I hope I helped a tiny bit. In any case, it was interesting to me to (re-) learn the technique... (I think I had learned it once, but it's always worthwhile to revisit this kind of stuff). Btw, the overhead you add by this technique is a virtual function call for all management-related functions (cloning, destroying, etc.) including for functions which do not care about allocator (function pointers, member functions and functors with small buffer optimization). In fact, I think that this cost may be undesirable at several levels because it also will prevent a number of optimizations since polymorphic dispatch cuts the compiler off from compile-time resolution. So it may be best to provide two function class templates, one without and one with allocators. In passing, I think the allocator pure abstract base class (as in the Lakos-allocator model) is better in this respect: you always have an extra pointer for storing the allocator passed at construction, but the invocation is not a template nor a polymorphic call (at least not until you actually want to deallocate). So it does not prevent the optimizations. Thanks. I learned something more tonight. On Jun 4, 2007, at 11:24 PM, Douglas Gregor wrote:
On Jun 4, 2007, at 10:57 PM, Emil Dotchevski wrote:
One important advantage of using boost::function is that it acts like a function pointer, reducing physical coupling between compilation units. This is very much like shared_ptr.
A nice feature of shared_ptr is that it has a single template parameter, T, even though diferent instances of shared_ptr<T> can use different allocators.
When using boost::function, one can also provide an allocator, but unlike shared_ptr, the allocator is a default parameter of the boost::function class template.
Is there a reason why this is necessary? Can't boost::function use similar technique to the one employed by shared_ptr to avoid the need for this second template parameter?
You know, I never even thought about adding it. I didn't know about the shared_ptr technique when I put the allocator into boost::function, and after the C++ committee removed the allocator I didn't think about it any more.
The biggest issue with moving the allocator into the constructor (like shared_ptr) is that boost::function doesn't know what type it is going to be interacting with... shared_ptr<T> knows it's 'T', function does not. However, I think we can work around this issue. It certainly would be better to have the allocator supplied in the constructor.
I don't know when I would have time to implement this, although I would certainly consider adding this functionality to Boost's "function". Might you be interested in implementing it?
- Doug _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/ listinfo.cgi/boost