GiNaC  1.8.0
ptr.h
Go to the documentation of this file.
1 
5 /*
6  * GiNaC Copyright (C) 1999-2020 Johannes Gutenberg University Mainz, Germany
7  *
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.
12  *
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.
17  *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #ifndef GINAC_PTR_H
24 #define GINAC_PTR_H
25 
26 #include "assertion.h"
27 
28 #include <cstddef> // for size_t
29 #include <functional>
30 #include <iosfwd>
31 
32 namespace GiNaC {
33 
35 class refcounted {
36 public:
37  refcounted() noexcept : refcount(0) {}
38 
39  unsigned int add_reference() noexcept { return ++refcount; }
40  unsigned int remove_reference() noexcept { return --refcount; }
41  unsigned int get_refcount() const noexcept { return refcount; }
42  void set_refcount(unsigned int r) noexcept { refcount = r; }
43 
44 private:
45  unsigned int refcount;
46 };
47 
48 
56 template <class T> class ptr {
57  friend struct std::less<ptr<T>>;
58 
59  // NB: This implementation of reference counting is not thread-safe.
60  // The reference counter needs to be incremented/decremented atomically,
61  // and makewritable() requires locking.
62 
63 public:
64  // no default ctor: a ptr is never unbound
65 
67  ptr(T *t) noexcept : p(t) { GINAC_ASSERT(p); p->set_refcount(1); }
68 
70  explicit ptr(T &t) noexcept : p(&t) { p->add_reference(); }
71 
72  ptr(const ptr & other) noexcept : p(other.p) { p->add_reference(); }
73 
74  ~ptr()
75  {
76  if (p->remove_reference() == 0)
77  delete p;
78  }
79 
80  ptr &operator=(const ptr & other)
81  {
82  // NB1: Must first add reference to "other", since other might be *this.
83  // NB2: Cache other.p, because if "other" is a subexpression of p,
84  // deleting p will also invalidate "other".
85  T *otherp = other.p;
86  otherp->add_reference();
87  if (p->remove_reference() == 0)
88  delete p;
89  p = otherp;
90  return *this;
91  }
92 
93  T &operator*() const noexcept { return *p; }
94  T *operator->() const noexcept { return p; }
95 
96  friend inline T *get_pointer(const ptr & x) noexcept { return x.p; }
97 
101  {
102  if (p->get_refcount() > 1) {
103  T *p2 = p->duplicate();
104  p2->set_refcount(1);
105  p->remove_reference();
106  p = p2;
107  }
108  }
109 
111  void swap(ptr & other) noexcept
112  {
113  T *t = p;
114  p = other.p;
115  other.p = t;
116  }
117 
118  // ptr<>s are always supposed to be bound to a valid object, so we don't
119  // provide support for "if (p)", "if (!p)", "if (p==0)" and "if (p!=0)".
120  // We do, however, provide support for comparing ptr<>s with other ptr<>s
121  // to different (probably derived) types and raw pointers.
122 
123  template <class U>
124  bool operator==(const ptr<U> & rhs) const noexcept { return p == get_pointer(rhs); }
125 
126  template <class U>
127  bool operator!=(const ptr<U> & rhs) const noexcept { return p != get_pointer(rhs); }
128 
129  template <class U>
130  inline friend bool operator==(const ptr & lhs, const U * rhs) noexcept { return lhs.p == rhs; }
131 
132  template <class U>
133  inline friend bool operator!=(const ptr & lhs, const U * rhs) noexcept { return lhs.p != rhs; }
134 
135  template <class U>
136  inline friend bool operator==(const U * lhs, const ptr & rhs) noexcept { return lhs == rhs.p; }
137 
138  template <class U>
139  inline friend bool operator!=(const U * lhs, const ptr & rhs) noexcept { return lhs != rhs.p; }
140 
141  inline friend std::ostream & operator<<(std::ostream & os, const ptr<T> & rhs)
142  {
143  os << rhs.p;
144  return os;
145  }
146 
147 private:
148  T *p;
149 };
150 
151 } // namespace GiNaC
152 
153 
154 namespace std {
155 
158 template <class T> struct less<GiNaC::ptr<T>> {
159  bool operator()(const GiNaC::ptr<T> &lhs, const GiNaC::ptr<T> &rhs) const
160  {
161  return less<T*>()(lhs.p, rhs.p);
162  }
163 };
164 
165 } // namespace std
166 
167 #endif // ndef GINAC_PTR_H
ptr & operator=(const ptr &other)
Definition: ptr.h:80
unsigned int refcount
reference counter
Definition: ptr.h:45
T & operator*() const noexcept
Definition: ptr.h:93
unsigned int remove_reference() noexcept
Definition: ptr.h:40
unsigned int add_reference() noexcept
Definition: ptr.h:39
~ptr()
Definition: ptr.h:74
friend T * get_pointer(const ptr &x) noexcept
Definition: ptr.h:96
ex rhs(const ex &thisex)
Definition: ex.h:817
Definition: add.cpp:38
Assertion macro definition.
Definition: ex.h:972
ex x
Definition: factor.cpp:1641
ptr(T *t) noexcept
Bind ptr to newly created object, start reference counting.
Definition: ptr.h:67
size_t r
Definition: factor.cpp:770
friend bool operator==(const ptr &lhs, const U *rhs) noexcept
Definition: ptr.h:130
T * operator->() const noexcept
Definition: ptr.h:94
refcounted() noexcept
Definition: ptr.h:37
ex lhs(const ex &thisex)
Definition: ex.h:814
#define GINAC_ASSERT(X)
Assertion macro for checking invariances.
Definition: assertion.h:33
bool operator()(const GiNaC::ptr< T > &lhs, const GiNaC::ptr< T > &rhs) const
Definition: ptr.h:159
T * p
Definition: ptr.h:148
void makewritable()
Announce your intention to modify the object bound to this ptr.
Definition: ptr.h:100
friend bool operator!=(const ptr &lhs, const U *rhs) noexcept
Definition: ptr.h:133
Base class for reference-counted objects.
Definition: ptr.h:35
void swap(ptr &other) noexcept
Swap the bound object of this ptr with another ptr.
Definition: ptr.h:111
ptr(const ptr &other) noexcept
Definition: ptr.h:72
bool operator==(const ptr< U > &rhs) const noexcept
Definition: ptr.h:124
friend bool operator!=(const U *lhs, const ptr &rhs) noexcept
Definition: ptr.h:139
ptr(T &t) noexcept
Bind ptr to existing reference-counted object.
Definition: ptr.h:70
unsigned int get_refcount() const noexcept
Definition: ptr.h:41
void set_refcount(unsigned int r) noexcept
Definition: ptr.h:42
friend bool operator==(const U *lhs, const ptr &rhs) noexcept
Definition: ptr.h:136
bool operator!=(const ptr< U > &rhs) const noexcept
Definition: ptr.h:127
Class of (intrusively) reference-counted pointers that support copy-on-write semantics.
Definition: ptr.h:56

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