3 * Reference-counted pointer template. */
6 * GiNaC Copyright (C) 1999-2003 Johannes Gutenberg University Mainz, Germany
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #ifndef __GINAC_PTR_H__
24 #define __GINAC_PTR_H__
29 #include "assertion.h"
33 /** Class of (intrusively) reference-counted pointers that support
34 * copy-on-write semantics.
37 * T::refcount member that supports ++refcount, --refcount, refcount = 1,
38 * refcount == 0 and refcount > 1
39 * T* T::duplicate() member function (only if makewriteable() is used) */
40 template <class T> class ptr {
41 friend class std::less< ptr<T> >;
43 // NB: This implementation of reference counting is not thread-safe.
44 // The reference counter needs to be incremented/decremented atomically,
45 // and makewritable() requires locking.
48 // no default ctor: a ptr is never unbound
50 /** Bind ptr to newly created object, start reference counting. */
51 ptr(T *t) : p(t) { GINAC_ASSERT(p); p->refcount = 1; }
53 /** Bind ptr to existing reference-counted object. */
54 explicit ptr(T &t) : p(&t) { ++p->refcount; }
56 ptr(const ptr & other) : p(other.p) { ++p->refcount; }
60 if (--p->refcount == 0)
64 ptr &operator=(const ptr & other)
66 // NB: must first increment other.p->refcount, since other might be *this.
68 if (--p->refcount == 0)
74 T &operator*() const { return *p; }
75 T *operator->() const { return p; }
77 friend inline T *get_pointer(const ptr & x) { return x.p; }
79 /** Announce your intention to modify the object bound to this ptr.
80 * This ensures that the object is not shared by any other ptrs. */
83 if (p->refcount > 1) {
84 T *p2 = p->duplicate();
91 /** Swap the bound object of this ptr with another ptr. */
92 void swap(ptr & other)
99 // ptr<>s are always supposed to be bound to a valid object, so we don't
100 // provide support for "if (p)", "if (!p)", "if (p==0)" and "if (p!=0)".
101 // We do, however, provide support for comparing ptr<>s with other ptr<>s
102 // to different (probably derived) types and raw pointers.
105 bool operator==(const ptr<U> & rhs) const { return p == get_pointer(rhs); }
108 bool operator!=(const ptr<U> & rhs) const { return p != get_pointer(rhs); }
111 inline friend bool operator==(const ptr & lhs, const U * rhs) { return lhs.p == rhs; }
114 inline friend bool operator!=(const ptr & lhs, const U * rhs) { return lhs.p != rhs; }
117 inline friend bool operator==(const U * lhs, const ptr & rhs) { return lhs == rhs.p; }
120 inline friend bool operator!=(const U * lhs, const ptr & rhs) { return lhs != rhs.p; }
122 inline friend std::ostream & operator<<(std::ostream & os, const ptr<T> & rhs)
135 /** Specialization of std::less for ptr<T> to enable ordering of ptr<T>
136 * objects (e.g. for the use as std::map keys). */
137 template <class T> struct less< GiNaC::ptr<T> >
138 : public binary_function<GiNaC::ptr<T>, GiNaC::ptr<T>, bool> {
139 bool operator()(const GiNaC::ptr<T> &lhs, const GiNaC::ptr<T> &rhs) const
141 return less<T*>()(lhs.p, rhs.p);
147 #endif // ndef __GINAC_PTR_H__