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:
templatetypename Y
explicit shared_ptr(Y * p,const detail::counted_header_tagY)
: 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:
templatetypename T
inline shared_ptrT new_counted() {
detail::counted_header_tagT counted;
return shared_ptrT(new(counted) T(),counted);
}
templatetypename T, typename P1
inline shared_ptrT new_counted(const P1 p1) {
detail::counted_header_tagT counted;
return shared_ptrT(new(counted) T(p1),counted);
}
templatetypename T, typename P1, typename P2
inline shared_ptrT new_counted(const P1 p1,const P2 p2) {
detail::counted_header_tagT counted;
return shared_ptrT(new(counted) T(p1,p2),counted);
}
templatetypename T, typename P1, typename P2, typename P3
inline shared_ptrT new_counted(const P1 p1,const P2 p2,const P3 p3) {
detail::counted_header_tagT counted;
return shared_ptrT(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 {
templateclass 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);
}
};
templatetypename T struct object_with_counted_header {
char header[sizeof(counted_base_header_implT*,checked_deleterT )];
char object[sizeof(T)];
};
templatetypename T inline void* get_counted_object_header(T* p) {
return (char*)p - offsetof(object_with_counted_headerT,object);
}
templateclass 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));
}
};
templatetypename T
inline counted_base* new_counted_base_in_object_header(T* p) {
return new (get_counted_object_header(p))
counted_base_header_implT*,checked_counted_header_deleterT
(p,checked_counted_header_deleterT(),1,1);
}
templatetypename T struct counted_header_tag {};
} // namespace detail
} // namespace boost
template typename T
inline void* operator new(size_t n,const boost::detail::counted_header_tagT) {
assert(n == sizeof(T));
return (char*)::operator
new(sizeof(boost::detail::object_with_counted_headerT))
+ offsetof(boost::detail::object_with_counted_headerT,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