X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fptr.h;h=93b16416f5471d9bd9eb165fd7d159767a3f2522;hp=1d1b49d2c94e78ebbe430bb8e2d6ef10baec3ebe;hb=8dc09f48182574d792a2ed7c37b66831d9267a6c;hpb=68fdf425abf14d016d5f95ee7b9d06a19a3c5926 diff --git a/ginac/ptr.h b/ginac/ptr.h index 1d1b49d2..93b16416 100644 --- a/ginac/ptr.h +++ b/ginac/ptr.h @@ -23,6 +23,7 @@ #ifndef __GINAC_PTR_H__ #define __GINAC_PTR_H__ +#include // for size_t #include #include @@ -30,12 +31,28 @@ namespace GiNaC { + +/** Base class for reference-counted objects. */ +class refcounted { +public: + refcounted() throw() : refcount(0) {} + + size_t add_reference() throw() { return ++refcount; } + size_t remove_reference() throw() { return --refcount; } + size_t get_refcount() const throw() { return refcount; } + void set_refcount(size_t r) throw() { refcount = r; } + +private: + size_t refcount; ///< reference counter +}; + + /** Class of (intrusively) reference-counted pointers that support * copy-on-write semantics. * * Requirements for T: - * T::refcount member that supports ++refcount, --refcount, refcount = 1, - * refcount == 0 and refcount > 1 + * must support the refcounted interface (usually by being derived + * from refcounted) * T* T::duplicate() member function (only if makewriteable() is used) */ template class ptr { friend class std::less< ptr >; @@ -48,48 +65,48 @@ public: // no default ctor: a ptr is never unbound /** Bind ptr to newly created object, start reference counting. */ - ptr(T *t) : p(t) { GINAC_ASSERT(p); p->refcount = 1; } + ptr(T *t) throw() : p(t) { GINAC_ASSERT(p); p->set_refcount(1); } /** Bind ptr to existing reference-counted object. */ - explicit ptr(T &t) : p(&t) { ++p->refcount; } + explicit ptr(T &t) throw() : p(&t) { p->add_reference(); } - ptr(const ptr & other) : p(other.p) { ++p->refcount; } + ptr(const ptr & other) throw() : p(other.p) { p->add_reference(); } ~ptr() { - if (--p->refcount == 0) + if (p->remove_reference() == 0) delete p; } ptr &operator=(const ptr & other) { - // NB: must first increment other.p->refcount, since other might be *this. - ++other.p->refcount; - if (--p->refcount == 0) + // NB: must first add reference to "other", since other might be *this. + other.p->add_reference(); + if (p->remove_reference() == 0) delete p; p = other.p; return *this; } - T &operator*() const { return *p; } - T *operator->() const { return p; } + T &operator*() const throw() { return *p; } + T *operator->() const throw() { return p; } - friend inline T *get_pointer(const ptr & x) { return x.p; } + friend inline T *get_pointer(const ptr & x) throw() { return x.p; } /** Announce your intention to modify the object bound to this ptr. * This ensures that the object is not shared by any other ptrs. */ void makewritable() { - if (p->refcount > 1) { + if (p->get_refcount() > 1) { T *p2 = p->duplicate(); - p2->refcount = 1; - --p->refcount; + p2->set_refcount(1); + p->remove_reference(); p = p2; } } /** Swap the bound object of this ptr with another ptr. */ - void swap(ptr & other) + void swap(ptr & other) throw() { T *t = p; p = other.p; @@ -102,22 +119,22 @@ public: // to different (probably derived) types and raw pointers. template - bool operator==(const ptr & rhs) const { return p == get_pointer(rhs); } + bool operator==(const ptr & rhs) const throw() { return p == get_pointer(rhs); } template - bool operator!=(const ptr & rhs) const { return p != get_pointer(rhs); } + bool operator!=(const ptr & rhs) const throw() { return p != get_pointer(rhs); } template - inline friend bool operator==(const ptr & lhs, const U * rhs) { return lhs.p == rhs; } + inline friend bool operator==(const ptr & lhs, const U * rhs) throw() { return lhs.p == rhs; } template - inline friend bool operator!=(const ptr & lhs, const U * rhs) { return lhs.p != rhs; } + inline friend bool operator!=(const ptr & lhs, const U * rhs) throw() { return lhs.p != rhs; } template - inline friend bool operator==(const U * lhs, const ptr & rhs) { return lhs == rhs.p; } + inline friend bool operator==(const U * lhs, const ptr & rhs) throw() { return lhs == rhs.p; } template - inline friend bool operator!=(const U * lhs, const ptr & rhs) { return lhs != rhs.p; } + inline friend bool operator!=(const U * lhs, const ptr & rhs) throw() { return lhs != rhs.p; } inline friend std::ostream & operator<<(std::ostream & os, const ptr & rhs) { @@ -130,6 +147,7 @@ private: } // namespace GiNaC + namespace std { /** Specialization of std::less for ptr to enable ordering of ptr @@ -144,4 +162,4 @@ template struct less< GiNaC::ptr > } // namespace std -#endif // ndef __GINAC_UTILS_H__ +#endif // ndef __GINAC_PTR_H__