CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
small_shared_n_way_ptr.h
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Small shared n-way pointer
4
5Author: Daniel Poetzl
6
7\*******************************************************************/
8
9#ifndef CPROVER_UTIL_SMALL_SHARED_N_WAY_PTR_H
10#define CPROVER_UTIL_SMALL_SHARED_N_WAY_PTR_H
11
12#include <limits>
13#include <tuple>
14#include <type_traits>
15#include <utility>
16
17#include "invariant.h"
18
20template <std::size_t I, typename... Ts>
22{
23 // NOLINTNEXTLINE(readability/identifiers)
24 typedef typename std::tuple_element<I, std::tuple<Ts...>>::type type;
25};
26
27template <std::size_t N, typename Num>
29
30// Struct to hold the static method destruct() to destruct the pointee of a
31// small shared n-way pointer.
32//
33// Note: This functionality should ideally be in a private static method of
34// small_shared_n_way_ptrt, but partial template specializations are not allowed
35// within other templates, hence it is defined at global scope.
36template <std::size_t I, typename pointee_baset, typename... Ts>
38{
39 static void destruct(pointee_baset *p)
40 {
41 if(p->template is_derived<I>())
42 {
43 typedef typename get_typet<I, Ts...>::type pointeet;
44 static_assert(
45 std::is_base_of<pointee_baset, pointeet>::value,
46 "indexed pointee type must be a subclass of the pointee base");
47
48 delete static_cast<pointeet *>(p);
49 }
50 else
51 {
53 }
54 }
55};
56
57template <typename pointee_baset, typename... Ts>
58struct destructt<0, pointee_baset, Ts...>
59{
60 static void destruct(pointee_baset *p)
61 {
62 PRECONDITION(p->template is_derived<0>());
63
64 typedef typename get_typet<0, Ts...>::type pointeet;
65 static_assert(
66 std::is_base_of<pointee_baset, pointeet>::value,
67 "indexed pointee type must be a subclass of the pointee base");
68
69 delete static_cast<pointeet *>(p);
70 }
71};
72
89template <typename... Ts>
91{
92public:
93 static const std::size_t num_types =
94 std::tuple_size<std::tuple<Ts...>>::value;
95
96 static_assert(
97 num_types >= 2,
98 "parameter pack should contain at least two types");
99
100 typedef decltype(std::declval<typename get_typet<0, Ts...>::type>()
101 .get_use_count()) use_countt;
102
104
106
114 template <std::size_t I>
115 static small_shared_n_way_ptrt<Ts...>
117 {
118 PRECONDITION(p != nullptr);
119 PRECONDITION(p->get_use_count() == 0);
120
121 p->template set_derived<I>();
122 p->increment_use_count();
123
124 return small_shared_n_way_ptrt<Ts...>(p);
125 }
126
128 {
130
131 if(p)
132 {
133 p->increment_use_count();
134 }
135 }
136
143
145 {
147
148 small_shared_n_way_ptrt copy(rhs);
149 swap(copy);
150 return *this;
151 }
152
154 {
156
157 swap(rhs);
158 return *this;
159 }
160
162 {
163 destruct();
164 }
165
168 void reset()
169 {
170 destruct();
171 p = nullptr;
172 }
173
175 {
177
178 std::swap(p, rhs.p);
179 }
180
185 {
186 return p ? p->get_use_count() : 0;
187 }
188
192 template <std::size_t I>
193 bool is_derived() const
194 {
195 return p == nullptr || p->template is_derived<I>();
196 }
197
204 {
205 return p;
206 }
207
211 template <std::size_t I>
212 typename get_typet<I, Ts...>::type *get_derived() const
213 {
215
216 return static_cast<typename get_typet<I, Ts...>::type *>(p);
217 }
218
222 bool is_same_type(const small_shared_n_way_ptrt &other) const
223 {
224 if(p == nullptr || other.p == nullptr)
225 return true;
226
227 return p->is_same_type(*other.p);
228 }
229
230 explicit operator bool() const
231 {
232 return p != nullptr;
233 }
234
235private:
236 template <typename T>
237 explicit small_shared_n_way_ptrt(T *p) : p(p)
238 {
239 }
240
241 void destruct()
242 {
243 if(!p)
244 {
245 return;
246 }
247
248 if(p->get_use_count() > 1)
249 {
250 p->decrement_use_count();
251 return;
252 }
253
255 }
256
257 pointee_baset *p = nullptr;
258};
259
271template <std::size_t I, typename U, typename V, typename... Ts>
273{
274 return small_shared_n_way_ptrt<U, V>::template create_small_shared_n_way_ptr<
275 I>(new typename get_typet<I, U, V>::type(std::forward<Ts>(ts)...));
276}
277
290template <std::size_t I, typename U, typename V, typename W, typename... Ts>
297
298template <typename... Ts>
302{
303 return lhs.get() == rhs.get();
304}
305
306template <typename... Ts>
310{
311 return lhs.get() != rhs.get();
312}
313
314template <std::size_t N, typename Num>
316{
317public:
318 static_assert(std::is_unsigned<Num>::value, "Num must be an unsigned type");
319
321
322 // The use count shall be unaffected
326
327 // The use count shall be unaffected
330 {
331 return *this;
332 }
333
335 {
336 return use_count & use_count_mask;
337 }
338
345
347 {
349
350 --use_count;
351 }
352
353 template <std::size_t I>
355 {
356 static_assert(I < N, "type index shall be within bounds");
357
360 }
361
362 template <std::size_t I>
363 bool is_derived() const
364 {
365 static_assert(I < N, "type index shall be within bounds");
366
367 return ((use_count & ~use_count_mask) >> use_count_bit_width) == I;
368 }
369
371 {
372 return !((use_count ^ other.use_count) & ~use_count_mask);
373 }
374
375private:
377
378 static const int bit_width = std::numeric_limits<Num>::digits;
379
380 static constexpr std::size_t num_bits(const std::size_t n)
381 {
382 return n < 2 ? 1 : 1 + num_bits(n >> 1);
383 }
384
385 static const std::size_t type_bit_width = num_bits(N);
386
387 static const std::size_t use_count_bit_width =
388 (std::size_t)bit_width - type_bit_width;
389
390 static const Num use_count_mask = ((Num)1 << use_count_bit_width) - 1;
391};
392
393#endif // CPROVER_UTIL_SMALL_SHARED_N_WAY_PTR_H
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
static const std::size_t use_count_bit_width
small_shared_n_way_pointee_baset(const small_shared_n_way_pointee_baset &)
small_shared_n_way_pointee_baset & operator=(const small_shared_n_way_pointee_baset &)
static constexpr std::size_t num_bits(const std::size_t n)
bool is_same_type(const small_shared_n_way_pointee_baset &other) const
This class is similar to small_shared_ptrt and boost's intrusive_ptr.
void reset()
Clears this shared pointer.
static small_shared_n_way_ptrt< Ts... > create_small_shared_n_way_ptr(typename get_typet< I, Ts... >::type *p)
Static factory method to construct a small shared n-way pointer, pointing to the given object *p of t...
small_shared_n_way_ptrt()=default
static const std::size_t num_types
get_typet< I, Ts... >::type * get_derived() const
Get pointer to the managed object.
small_shared_n_way_ptrt & operator=(const small_shared_n_way_ptrt &rhs)
decltype(std::declval< typename get_typet< 0, Ts... >::type >() .get_use_count()) use_countt
pointee_baset * get() const
Get base type pointer to the managed object.
use_countt use_count() const
Get the use count of the pointed-to object.
bool is_same_type(const small_shared_n_way_ptrt &other) const
Checks if the raw pointers held by *this and other both can be converted to a pointer to the same typ...
small_shared_n_way_ptrt(small_shared_n_way_ptrt &&rhs)
small_shared_n_way_ptrt & operator=(small_shared_n_way_ptrt &&rhs)
small_shared_n_way_ptrt(const small_shared_n_way_ptrt &rhs)
bool is_derived() const
Check if converting the held raw pointer to type Ts[I] is valid.
small_shared_n_way_pointee_baset< num_types, use_countt > pointee_baset
void swap(small_shared_n_way_ptrt &rhs)
small_shared_n_way_ptrt< U, V > make_shared_2(Ts &&... ts)
Constructs a small shared n-way pointer, with two possible pointee types (i.e., n = 2),...
bool operator==(const small_shared_n_way_ptrt< Ts... > &lhs, const small_shared_n_way_ptrt< Ts... > &rhs)
small_shared_n_way_ptrt< U, V, W > make_shared_3(Ts &&... ts)
Constructs a small shared n-way pointer, with three possible pointee types (i.e., n = 3),...
bool operator!=(const small_shared_n_way_ptrt< Ts... > &lhs, const small_shared_n_way_ptrt< Ts... > &rhs)
#define PRECONDITION(CONDITION)
Definition invariant.h:463
static void destruct(pointee_baset *p)
static void destruct(pointee_baset *p)
Get the type with the given index in the parameter pack.
std::tuple_element< I, std::tuple< Ts... > >::type type