[Note: There was no attached file.]
Oh, sorry! Here is the attached code. Am I right?
Thanks very much. But still I haven't understand placement attached:-)
#ifndef COUNTED_PTR_HPP
#define COUNTED_PTR_HPP
#include <cstring>
#include
// counted_ptr --------------------------------------------------------------//
template <typename T> class RefLinking
{
protected:
RefLinking(T* p) { init(p); }
~RefLinking() { dispose(); }
template<typename Y>
RefLinking(const RefLinking<Y>& r) { insert(&r); } // never throws
RefLinking(const RefLinking& r) { insert(&r); } // never throws
public:
template<typename Y>
void operator=(const RefLinking<Y>& r) { share(&r); }
void operator=(const RefLinking& r) { share(&r); }
void reset(T* p=0) {
if ( px == p ) return; // fix: self-assignment safe
dispose();
init(p);
} // reset
T* get() const { return px; } // never throws
long use_count() const
{
long i = 0;
const RefLinking* p = prev;
while(p){ p = p->prev; ++i; }
p = this;
while(p){ p = p->next; ++i; }
return i;
} // never throws
#if ( defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) ) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
private:
#endif
T* px;
RefLinking *prev, *next;
// Don't split this line into two; that causes problems for some GCC 2.95.2 builds
#if !defined( BOOST_NO_MEMBER_TEMPLATES ) && !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
template<typename Y> friend class RefLinking;
#endif
void init(T* p)
{
px = p;
prev = 0;
next = 0;
}
void dispose()
{
if(prev)
prev->next = next;
else if(next)
next->prev = prev;
else
delete px;
}
template <class Y> void insert(Y* rr)
{
RefLinking* r = (RefLinking*)rr;
px = r->px;
prev = (r);
next = r->next;
r->next = this;
if(next) next->prev = this;
}
template <class Y> void share(Y* r) {
if ((void*)this != (void*)r) {
dispose();
insert(r);
}
} // share
};
//*/
template <typename T> class EmbeddedAttached
{
protected:
EmbeddedAttached(T* p) { init(p); }
~EmbeddedAttached() { dispose(); }
template<typename Y>
EmbeddedAttached(const EmbeddedAttached<Y>& r) : ptr(r.ptr) { // never throws
if(ptr) ++(ptr->pn);
}
EmbeddedAttached(const EmbeddedAttached& r) : ptr(r.ptr)
{ if(ptr) ++(ptr->pn); } // never throws
public:
template<typename Y>
void operator=(const EmbeddedAttached<Y>& r) { share(r.ptr); }
void operator=(const EmbeddedAttached& r) { share(r.ptr); }
void reset(T* p=0) {
if ( ptr == p ) return; // fix: self-assignment safe
dispose();
init(p);
} // reset
T* get() const { return ptr; } // never throws
long use_count() const { return (ptr)? ptr->pn: 0; } // never throws
#if ( defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) ) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
private:
#endif
T* ptr;
// Don't split this line into two; that causes problems for some GCC 2.95.2 builds
#if !defined( BOOST_NO_MEMBER_TEMPLATES ) && !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
template<typename Y> friend class EmbeddedAttached;
#endif
void init(T* p)
{
ptr = p;
if(ptr) ++(ptr->pn);
}
void dispose() { if(ptr&&--(ptr->pn)== 0) delete ptr; }
void share(T* r) {
if (ptr != r && r) { // Q: why not px != rpx? A: fails when both == 0
++(r->pn); // done before dispose() in case rpn transitively
// dependent on *this (bug reported by Ken Johnson)
dispose();
ptr = r;
}
} // share
};
template <typename T> class IndirectDetached
{
protected:
IndirectDetached(T* p) { init(p); }
~IndirectDetached() { dispose(); }
template<typename Y>
IndirectDetached(const IndirectDetached<Y>& r) : ptr(r.ptr) { // never throws
++(ptr->pn);
}
IndirectDetached(const IndirectDetached& r) : ptr(r.ptr)
{ ++(ptr->pn); } // never throws
public:
template<typename Y>
void operator=(const IndirectDetached<Y>& r) { share(r.ptr); }
void operator=(const IndirectDetached& r) { share(r.ptr); }
void reset(T* p=0) {
if ( ptr->px == p ) return; // fix: self-assignment safe
dispose();
init(p);
} // reset
T* get() const { return ptr->px; } // never throws
long use_count() const { return ptr->pn; } // never throws
#if ( defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) ) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
private:
#endif
struct IDHelper{
T* px;
long pn;
IDHelper(T* p): px(p), pn(1) {}
~IDHelper() { delete px; }
};
IDHelper* ptr;
// Don't split this line into two; that causes problems for some GCC 2.95.2 builds
#if !defined( BOOST_NO_MEMBER_TEMPLATES ) && !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
template<typename Y> friend class IndirectDetached;
#endif
void init(T* p)
{
try { ptr = new IDHelper(p); }
catch (...) { delete p; throw; }
}
void dispose() { if(--(ptr->pn) == 0) delete ptr; }
template <class Y> void share(IDHelper* r) {
if ((void*)ptr != (void*)r) { // Q: why not px != rpx? A: fails when both == 0
++(r->pn); // done before dispose() in case rpn transitively
// dependent on *this (bug reported by Ken Johnson)
dispose();
ptr = r;
}
} // share
};
//*/
template <typename T> class DirectDetached
{
protected:
DirectDetached(T* p) : px(p) {
try { pn = new long(1); }
catch (...) { delete p; throw; }
}
~DirectDetached() { dispose(); }
template<typename Y>
DirectDetached(const DirectDetached<Y>& r) : px(r.px) { // never throws
++*(pn = r.pn);
}
DirectDetached(const DirectDetached& r) : px(r.px)
{ ++*(pn = r.pn); } // never throws
public:
template<typename Y>
void operator=(const DirectDetached<Y>& r) { share(r.px, r.pn); }
void operator=(const DirectDetached& r) { share(r.px, r.pn); }
void reset(T* p=0) {
if ( px == p ) return; // fix: self-assignment safe
if (--*pn == 0) { delete px; }
else { // allocate new reference counter
try { pn = new long; } // fix: prevent leak if new throws
catch (...) {
++*pn; // undo effect of --*pn above to meet effects guarantee
delete p;
throw;
} // catch
} // allocate new reference counter
*pn = 1;
px = p;
} // reset
T* get() const { return px; } // never throws
long use_count() const { return *pn; } // never throws
// Tasteless as this may seem, making all members public allows member templates
// to work in the absence of member template friends. (Matthew Langston)
// Don't split this line into two; that causes problems for some GCC 2.95.2 builds
#if ( defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) ) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
private:
#endif
T* px; // contained pointer
long* pn; // ptr to reference counter
// Don't split this line into two; that causes problems for some GCC 2.95.2 builds
#if !defined( BOOST_NO_MEMBER_TEMPLATES ) && !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
template<typename Y> friend class DirectDetached;
#endif
void dispose() { if (--*pn == 0) { delete px; delete pn; } }
void share(T* rpx, long* rpn) {
if (pn != rpn) { // Q: why not px != rpx? A: fails when both == 0
++*rpn; // done before dispose() in case rpn transitively
// dependent on *this (bug reported by Ken Johnson)
dispose();
px = rpx;
pn = rpn;
}
} // share
};
template
class counted_ptr: public Storage {
public:
typedef T element_type;
explicit counted_ptr(T* p = 0) : Storage(p) {}
template
counted_ptr(const counted_ptr& r) : Storage(r) {} // never throws
template
counted_ptr& operator=(const counted_ptr& r) {
*static_cast(this) = static_cast(r);
return *this;
}
counted_ptr(const counted_ptr& r) : Storage(r) {} // never throws
counted_ptr& operator=(const counted_ptr& r) {
*static_cast(this) = static_cast(r);
return *this;
}
T& operator*() const { return *get(); } // never throws
T* operator->() const { return get(); } // never throws
bool unique() const { return use_count() == 1; } // never throws
void swap(counted_ptr& other) // never throws
{
using std::memcpy;
const int size = sizeof(counted_ptr);
char temp[size];
memcpy(temp, &other, size);
memcpy(&other, this, size);
memcpy(this, temp, size);
}
}; // counted_ptr
#endif // COUNTED_PTR_HPP
Jon Wang
2002-02-04