The weather kept me at home today, so I had time to hack in a new constructor for shared_ptr that keeps the count in a header which is allocated along with the counted object. Like intrusive_ptr, but intrusive in a different way. If anyone has time to apply the patches and see if it is as fast as it should be I would most grateful.
The new public constructor goes inside shared_ptr in shared_ptr.hpp: template<typename Y> explicit shared_ptr(Y * p,const detail::counted_header_tag<Y>&) : px(p), pn(detail::new_counted_base_in_object_header(p)) // Y must be complete { } To make it easier to get the tags right I added a few helper functions, which made me wish again for type-safe variadic functions. They go in the boost namespace in shared_ptr.hpp: template<typename T> inline shared_ptr<T> new_counted() { detail::counted_header_tag<T> counted; return shared_ptr<T>(new(counted) T(),counted); } template<typename T, typename P1> inline shared_ptr<T> new_counted(const P1& p1) { detail::counted_header_tag<T> counted; return shared_ptr<T>(new(counted) T(p1),counted); } template<typename T, typename P1, typename P2> inline shared_ptr<T> new_counted(const P1& p1,const P2& p2) { detail::counted_header_tag<T> counted; return shared_ptr<T>(new(counted) T(p1,p2),counted); } template<typename T, typename P1, typename P2, typename P3> inline shared_ptr<T> new_counted(const P1& p1,const P2& p2,const P3& p3) { detail::counted_header_tag<T> counted; return shared_ptr<T>(new(counted) T(p1,p2,p3),counted); } // ... repeat above with more args until bored The guts of the change go near the end of shared_count.hpp: namespace boost { namespace detail { template<class P, class D> class counted_base_header_impl: public counted_base { private: P ptr; // copy constructor must not throw D del; // copy constructor must not throw counted_base_header_impl(counted_base_header_impl const &); counted_base_header_impl & operator= (counted_base_header_impl const &); public: // pre: initial_use_count <= initial_weak_count, d(p) must not throw counted_base_header_impl(P p, D d, long initial_use_count, long initial_weak_count): counted_base(initial_use_count, initial_weak_count), ptr(p), del(d) { } virtual void destruct() // nothrow { } virtual void dispose() // nothrow { del(ptr); } }; template<typename T> struct object_with_counted_header { char header[sizeof(counted_base_header_impl<T*,checked_deleter<T> >)]; char object[sizeof(T)]; }; template<typename T> inline void* get_counted_object_header(T* p) { return (char*)p - offsetof(object_with_counted_header<T>,object); } template<class T> struct checked_counted_header_deleter { typedef void result_type; typedef T* argument_type; void operator()(T* p) { typedef char type_must_be_complete[sizeof(T)]; ::operator delete(get_counted_object_header(p)); } }; template<typename T> inline counted_base* new_counted_base_in_object_header(T* p) { return new (get_counted_object_header(p)) counted_base_header_impl<T*,checked_counted_header_deleter<T> > (p,checked_counted_header_deleter<T>(),1,1); } template<typename T> struct counted_header_tag {}; } // namespace detail } // namespace boost template <typename T> inline void* operator new(size_t n,const boost::detail::counted_header_tag<T>&) { assert(n == sizeof(T)); return (char*)::operator new(sizeof(boost::detail::object_with_counted_header<T>)) + offsetof(boost::detail::object_with_counted_header<T>,object); } I haven't bothered with an array version yet, and have tested only with GCC on Cygwin. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost