GiNaC  1.6.2
ptr.h
Go to the documentation of this file.
00001 
00005 /*
00006  *  GiNaC Copyright (C) 1999-2011 Johannes Gutenberg University Mainz, Germany
00007  *
00008  *  This program is free software; you can redistribute it and/or modify
00009  *  it under the terms of the GNU General Public License as published by
00010  *  the Free Software Foundation; either version 2 of the License, or
00011  *  (at your option) any later version.
00012  *
00013  *  This program is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *  GNU General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU General Public License
00019  *  along with this program; if not, write to the Free Software
00020  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  */
00022 
00023 #ifndef GINAC_PTR_H
00024 #define GINAC_PTR_H
00025 
00026 #include "assertion.h"
00027 
00028 #include <cstddef> // for size_t
00029 #include <functional>
00030 #include <iosfwd>
00031 
00032 namespace GiNaC {
00033 
00035 class refcounted {
00036 public:
00037     refcounted() throw() : refcount(0) {}
00038 
00039     unsigned int add_reference() throw() { return ++refcount; }
00040     unsigned int remove_reference() throw() { return --refcount; }
00041     unsigned int get_refcount() const throw() { return refcount; }
00042     void set_refcount(unsigned int r) throw() { refcount = r; }
00043 
00044 private:
00045     unsigned int refcount; 
00046 };
00047 
00048 
00056 template <class T> class ptr {
00057     friend class std::less< ptr<T> >;
00058 
00059     // NB: This implementation of reference counting is not thread-safe.
00060     // The reference counter needs to be incremented/decremented atomically,
00061     // and makewritable() requires locking.
00062 
00063 public:
00064     // no default ctor: a ptr is never unbound
00065 
00067     ptr(T *t) throw() : p(t) { GINAC_ASSERT(p); p->set_refcount(1); }
00068 
00070     explicit ptr(T &t) throw() : p(&t) { p->add_reference(); }
00071 
00072     ptr(const ptr & other) throw() : p(other.p) { p->add_reference(); }
00073 
00074     ~ptr()
00075     {
00076         if (p->remove_reference() == 0)
00077             delete p;
00078     }
00079 
00080     ptr &operator=(const ptr & other)
00081     {
00082         // NB1: Must first add reference to "other", since other might be *this.
00083         // NB2: Cache other.p, because if "other" is a subexpression of p,
00084         //      deleting p will also invalidate "other".
00085         T *otherp = other.p;
00086         otherp->add_reference();
00087         if (p->remove_reference() == 0)
00088             delete p;
00089         p = otherp;
00090         return *this;
00091     }
00092 
00093     T &operator*() const throw() { return *p; }
00094     T *operator->() const throw() { return p; }
00095 
00096     friend inline T *get_pointer(const ptr & x) throw() { return x.p; }
00097 
00100     void makewritable()
00101     {
00102         if (p->get_refcount() > 1) {
00103             T *p2 = p->duplicate();
00104             p2->set_refcount(1);
00105             p->remove_reference();
00106             p = p2;
00107         }
00108     }
00109 
00111     void swap(ptr & other) throw()
00112     {
00113         T *t = p;
00114         p = other.p;
00115         other.p = t;
00116     }
00117 
00118     // ptr<>s are always supposed to be bound to a valid object, so we don't
00119     // provide support for "if (p)", "if (!p)", "if (p==0)" and "if (p!=0)".
00120     // We do, however, provide support for comparing ptr<>s with other ptr<>s
00121     // to different (probably derived) types and raw pointers.
00122 
00123     template <class U>
00124     bool operator==(const ptr<U> & rhs) const throw() { return p == get_pointer(rhs); }
00125 
00126     template <class U>
00127     bool operator!=(const ptr<U> & rhs) const throw() { return p != get_pointer(rhs); }
00128 
00129     template <class U>
00130     inline friend bool operator==(const ptr & lhs, const U * rhs) throw() { return lhs.p == rhs; }
00131 
00132     template <class U>
00133     inline friend bool operator!=(const ptr & lhs, const U * rhs) throw() { return lhs.p != rhs; }
00134 
00135     template <class U>
00136     inline friend bool operator==(const U * lhs, const ptr & rhs) throw() { return lhs == rhs.p; }
00137 
00138     template <class U>
00139     inline friend bool operator!=(const U * lhs, const ptr & rhs) throw() { return lhs != rhs.p; }
00140 
00141     inline friend std::ostream & operator<<(std::ostream & os, const ptr<T> & rhs)
00142     {
00143         os << rhs.p;
00144         return os;
00145     }
00146 
00147 private:
00148     T *p;
00149 };
00150 
00151 } // namespace GiNaC
00152 
00153 
00154 namespace std {
00155 
00158 template <class T> struct less< GiNaC::ptr<T> >
00159  : public binary_function<GiNaC::ptr<T>, GiNaC::ptr<T>, bool> {
00160     bool operator()(const GiNaC::ptr<T> &lhs, const GiNaC::ptr<T> &rhs) const
00161     {
00162         return less<T*>()(lhs.p, rhs.p);
00163     }
00164 };
00165 
00166 } // namespace std
00167 
00168 #endif // ndef GINAC_PTR_H

This page is part of the GiNaC developer's reference. It was generated automatically by doxygen. For an introduction, see the tutorial.