
[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 <boost/config.hpp> // 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<typename T, class Storage = DirectDetached<T> > class counted_ptr: public Storage { public: typedef T element_type; explicit counted_ptr(T* p = 0) : Storage(p) {} template<typename Y, typename S> counted_ptr(const counted_ptr<Y, S>& r) : Storage(r) {} // never throws template<typename Y, typename S> counted_ptr& operator=(const counted_ptr<Y, S>& r) { *static_cast<Storage*>(this) = static_cast<const S&>(r); return *this; } counted_ptr(const counted_ptr& r) : Storage(r) {} // never throws counted_ptr& operator=(const counted_ptr& r) { *static_cast<Storage*>(this) = static_cast<const Storage&>(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