cprover
small_shared_two_way_ptr.h
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Small shared two-way pointer
4 
5 Author: Daniel Poetzl
6 
7 \*******************************************************************/
8 
9 #ifndef CPROVER_UTIL_SMALL_SHARED_TWO_WAY_PTR_H
10 #define CPROVER_UTIL_SMALL_SHARED_TWO_WAY_PTR_H
11 
12 #include <type_traits>
13 #include <limits>
14 #include <utility>
15 
16 #include "invariant.h"
17 
18 template <typename Num>
20 
33 template <typename U, typename V>
35 {
36 public:
37  typedef decltype(std::declval<U>().use_count()) use_countt;
38 
40 
41  static_assert(std::is_base_of<pointeet, U>::value, "");
42  static_assert(std::is_base_of<pointeet, V>::value, "");
43 
44  small_shared_two_way_ptrt() = default;
45 
46  explicit small_shared_two_way_ptrt(U *u) : p(u)
47  {
48  PRECONDITION(u != nullptr);
49  PRECONDITION(u->use_count() == 0);
50 
51  p->set_derived_u();
53  }
54 
55  explicit small_shared_two_way_ptrt(V *v) : p(v)
56  {
57  PRECONDITION(v != nullptr);
58  PRECONDITION(v->use_count() == 0);
59 
60  p->set_derived_v();
62  }
63 
65  {
67 
68  if(p)
69  {
71  }
72  }
73 
75  {
77 
78  swap(rhs);
79  }
80 
82  {
84 
85  small_shared_two_way_ptrt copy(rhs);
86  swap(copy);
87  return *this;
88  }
89 
91  {
93 
94  swap(rhs);
95  return *this;
96  }
97 
99  {
100  if(!p)
101  {
102  return;
103  }
104 
105  auto use_count = p->use_count();
106 
107  if(use_count == 1)
108  {
109  if(p->is_derived_u())
110  {
111  U *u = static_cast<U *>(p);
112  delete u;
113  }
114  else
115  {
116  V *v = static_cast<V *>(p);
117  delete v;
118  }
119  }
120  else
121  {
123  }
124  }
125 
127  {
129 
130  std::swap(p, rhs.p);
131  }
132 
134  {
135  return p ? p->use_count() : 0;
136  }
137 
139  bool is_derived_u() const
140  {
141  return p == nullptr || p->is_derived_u();
142  }
143 
145  bool is_derived_v() const
146  {
147  return p == nullptr || p->is_derived_v();
148  }
149 
150  pointeet *get() const
151  {
152  return p;
153  }
154 
155  U *get_derived_u() const
156  {
158 
159  return static_cast<U *>(p);
160  }
161 
162  V *get_derived_v() const
163  {
165 
166  return static_cast<V *>(p);
167  }
168 
171  bool is_same_type(const small_shared_two_way_ptrt &other) const
172  {
173  if(p == nullptr || other.p == nullptr)
174  return true;
175 
176  return p->is_same_type(*other.p);
177  }
178 
179  explicit operator bool() const
180  {
181  return p != nullptr;
182  }
183 
184 private:
185  pointeet *p = nullptr;
186 };
187 
188 template <typename U, typename V, typename... Ts>
190 {
191  return small_shared_two_way_ptrt<U, V>(new U(std::forward<Ts>(ts)...));
192 }
193 
194 template <typename U, typename V, typename... Ts>
196 {
197  return small_shared_two_way_ptrt<U, V>(new V(std::forward<Ts>(ts)...));
198 }
199 
200 template <typename U, typename V>
204 {
205  return lhs.get() == rhs.get();
206 }
207 
208 template <typename U, typename V>
212 {
213  return lhs.get() != rhs.get();
214 }
215 
216 template <typename Num>
218 {
219 public:
220  static_assert(std::is_unsigned<Num>::value, "");
221 
222  static const int bit_idx = std::numeric_limits<Num>::digits - 1;
223  static const Num mask = ~((Num)1 << bit_idx);
224 
225  small_shared_two_way_pointeet() = default;
226 
227  // The use count shall be unaffected
229  {
230  }
231 
232  // The use count shall be unaffected
235  {
236  return *this;
237  }
238 
239  Num use_count() const
240  {
241  return use_count_ & mask;
242  }
243 
245  {
247 
248  use_count_++;
249  }
250 
252  {
253  PRECONDITION((use_count_ & mask) > 0);
254 
255  use_count_--;
256  }
257 
259  {
260  use_count_ &= mask;
261  }
262 
264  {
265  use_count_ |= ~mask;
266  }
267 
268  bool is_derived_u() const
269  {
270  return !(use_count_ & ~mask);
271  }
272 
273  bool is_derived_v() const
274  {
275  return (use_count_ & ~mask) != 0;
276  }
277 
279  {
280  return !((use_count_ ^ other.use_count_) & ~mask);
281  }
282 
283 private:
284  Num use_count_ = 0;
285 };
286 
287 #endif
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:438
small_shared_two_way_ptrt::use_countt
decltype(std::declval< U >().use_count()) typedef use_countt
Definition: small_shared_two_way_ptr.h:37
small_shared_two_way_ptrt::is_same_type
bool is_same_type(const small_shared_two_way_ptrt &other) const
Checks if the raw pointers held by *this and other both can be converted to either U* or V*.
Definition: small_shared_two_way_ptr.h:171
small_shared_two_way_pointeet::set_derived_u
void set_derived_u()
Definition: small_shared_two_way_ptr.h:258
small_shared_two_way_pointeet::use_count
Num use_count() const
Definition: small_shared_two_way_ptr.h:239
operator==
bool operator==(const small_shared_two_way_ptrt< U, V > &lhs, const small_shared_two_way_ptrt< U, V > &rhs)
Definition: small_shared_two_way_ptr.h:201
small_shared_two_way_pointeet::operator=
small_shared_two_way_pointeet & operator=(const small_shared_two_way_pointeet &)
Definition: small_shared_two_way_ptr.h:234
small_shared_two_way_pointeet::is_derived_u
bool is_derived_u() const
Definition: small_shared_two_way_ptr.h:268
small_shared_two_way_pointeet::small_shared_two_way_pointeet
small_shared_two_way_pointeet()=default
small_shared_two_way_pointeet::increment_use_count
void increment_use_count()
Definition: small_shared_two_way_ptr.h:244
small_shared_two_way_ptrt
This class is similar to small_shared_ptrt and boost's intrusive_ptr.
Definition: small_shared_two_way_ptr.h:34
small_shared_two_way_ptrt::p
pointeet * p
Definition: small_shared_two_way_ptr.h:185
small_shared_two_way_ptrt::small_shared_two_way_ptrt
small_shared_two_way_ptrt(const small_shared_two_way_ptrt &rhs)
Definition: small_shared_two_way_ptr.h:64
invariant.h
small_shared_two_way_pointeet
Definition: small_shared_two_way_ptr.h:19
small_shared_two_way_ptrt::is_derived_u
bool is_derived_u() const
Checks if converting the held raw pointer to U* is valid.
Definition: small_shared_two_way_ptr.h:139
small_shared_two_way_pointeet::mask
static const Num mask
Definition: small_shared_two_way_ptr.h:223
small_shared_two_way_pointeet::use_count_
Num use_count_
Definition: small_shared_two_way_ptr.h:284
make_shared_derived_v
small_shared_two_way_ptrt< U, V > make_shared_derived_v(Ts &&... ts)
Definition: small_shared_two_way_ptr.h:195
small_shared_two_way_pointeet::is_same_type
bool is_same_type(const small_shared_two_way_pointeet &other) const
Definition: small_shared_two_way_ptr.h:278
small_shared_two_way_ptrt::is_derived_v
bool is_derived_v() const
Checks if converting the held raw pointer to V* is valid.
Definition: small_shared_two_way_ptr.h:145
small_shared_two_way_ptrt::use_count
use_countt use_count() const
Definition: small_shared_two_way_ptr.h:133
small_shared_two_way_pointeet::set_derived_v
void set_derived_v()
Definition: small_shared_two_way_ptr.h:263
small_shared_two_way_ptrt::operator=
small_shared_two_way_ptrt & operator=(const small_shared_two_way_ptrt &rhs)
Definition: small_shared_two_way_ptr.h:81
small_shared_two_way_ptrt::swap
void swap(small_shared_two_way_ptrt &rhs)
Definition: small_shared_two_way_ptr.h:126
small_shared_two_way_pointeet::is_derived_v
bool is_derived_v() const
Definition: small_shared_two_way_ptr.h:273
small_shared_two_way_pointeet::bit_idx
static const int bit_idx
Definition: small_shared_two_way_ptr.h:222
operator!=
bool operator!=(const small_shared_two_way_ptrt< U, V > &lhs, const small_shared_two_way_ptrt< U, V > &rhs)
Definition: small_shared_two_way_ptr.h:209
small_shared_two_way_pointeet::decrement_use_count
void decrement_use_count()
Definition: small_shared_two_way_ptr.h:251
small_shared_two_way_ptrt::get_derived_u
U * get_derived_u() const
Definition: small_shared_two_way_ptr.h:155
small_shared_two_way_ptrt::small_shared_two_way_ptrt
small_shared_two_way_ptrt(small_shared_two_way_ptrt &&rhs)
Definition: small_shared_two_way_ptr.h:74
small_shared_two_way_ptrt::get
pointeet * get() const
Definition: small_shared_two_way_ptr.h:150
small_shared_two_way_ptrt::get_derived_v
V * get_derived_v() const
Definition: small_shared_two_way_ptr.h:162
small_shared_two_way_ptrt::operator=
small_shared_two_way_ptrt & operator=(small_shared_two_way_ptrt &&rhs)
Definition: small_shared_two_way_ptr.h:90
make_shared_derived_u
small_shared_two_way_ptrt< U, V > make_shared_derived_u(Ts &&... ts)
Definition: small_shared_two_way_ptr.h:189
small_shared_two_way_pointeet::small_shared_two_way_pointeet
small_shared_two_way_pointeet(const small_shared_two_way_pointeet &)
Definition: small_shared_two_way_ptr.h:228
small_shared_two_way_ptrt::small_shared_two_way_ptrt
small_shared_two_way_ptrt(V *v)
Definition: small_shared_two_way_ptr.h:55
small_shared_two_way_ptrt::~small_shared_two_way_ptrt
~small_shared_two_way_ptrt()
Definition: small_shared_two_way_ptr.h:98