CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
reference_counting.h
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Reference Counting
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
11
12#ifndef CPROVER_UTIL_REFERENCE_COUNTING_H
13#define CPROVER_UTIL_REFERENCE_COUNTING_H
14
15#include "invariant.h"
16
19template <typename T, const T &empty = T::blank>
20// NOLINTNEXTLINE(readability/identifiers)
22{
23public:
27
28 explicit reference_counting(const T &other):d(NULL)
29 {
30 write()=other;
31 }
32
33 // copy constructor
35 {
36 if(d!=nullptr)
37 {
39 d->ref_count++;
40 #ifdef REFERENCE_COUNTING_DEBUG
41 std::cout << "COPY " << d << " " << d->ref_count << '\n';
42 #endif
43 }
44 }
45
47 {
48 copy_from(other);
49 return *this;
50 }
51
53 {
55 d=nullptr;
56 }
57
59 {
60 std::swap(other.d, d);
61 }
62
63 void clear()
64 {
66 d=nullptr;
67 }
68
69 const T &read() const
70 {
71 if(d==nullptr)
72 return empty;
73 return *d;
74 }
75
76 T &write()
77 {
78 detach();
79 return *d;
80 }
81
82protected:
83 class dt:public T
84 {
85 public:
86 unsigned ref_count;
87
89 {
90 }
91 };
92
93 dt *d;
94
95 void remove_ref(dt *old_d);
96
97 void detach();
98
99 void copy_from(const reference_counting &other)
100 {
101 PRECONDITION(&other != this); // check if we assign to ourselves
102
103 #ifdef REFERENCE_COUNTING_DEBUG
104 std::cout << "COPY " << (&other) << "\n";
105 #endif
106
107 remove_ref(d);
108 d=other.d;
109 if(d!=nullptr)
110 d->ref_count++;
111 }
112
113public:
114 dt *get_d() const
115 {
116 return d;
117 }
118};
119
120template <class T, const T &empty>
122{
123 if(old_d==nullptr)
124 return;
125
126 PRECONDITION(old_d->ref_count != 0);
127
128 #ifdef REFERENCE_COUNTING_DEBUG
129 std::cout << "R: " << old_d << " " << old_d->ref_count << '\n';
130 #endif
131
132 old_d->ref_count--;
133 if(old_d->ref_count==0)
134 {
135 #ifdef REFERENCE_COUNTING_DEBUG
136 std::cout << "DELETING " << old_d << '\n';
137 old_d->clear();
138 std::cout << "DEALLOCATING " << old_d << "\n";
139 #endif
140
141 delete old_d;
142
143 #ifdef REFERENCE_COUNTING_DEBUG
144 std::cout << "DONE\n";
145 #endif
146 }
147}
148
149template <class T, const T &empty>
151{
152 #ifdef REFERENCE_COUNTING_DEBUG
153 std::cout << "DETACH1: " << d << '\n';
154 #endif
155
156 if(d==nullptr)
157 {
158 d=new dt;
159
160 #ifdef REFERENCE_COUNTING_DEBUG
161 std::cout << "ALLOCATED " << d << '\n';
162 #endif
163 }
164 else if(d->ref_count>1)
165 {
166 dt *old_d(d);
167 d=new dt(*old_d);
168
169 #ifdef REFERENCE_COUNTING_DEBUG
170 std::cout << "ALLOCATED " << d << '\n';
171 #endif
172
173 d->ref_count=1;
174 remove_ref(old_d);
175 }
176
177 POSTCONDITION(d->ref_count == 1);
178
179 #ifdef REFERENCE_COUNTING_DEBUG
180 std::cout << "DETACH2: " << d << '\n'
181 #endif
182}
183
184template <class T, const T &empty>
188{
189 if(o1.get_d()==o2.get_d())
190 return true;
191 return o1.read()==o2.read();
192}
193
194template <class T, const T &empty>
195inline bool operator!=(
198{ return !(i1==i2); }
199
200#endif // CPROVER_UTIL_REFERENCE_COUNTING_H
virtual void clear()
Reset the abstract state.
Definition ai.h:265
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
ait()
Definition ai.h:565
reference_counting(const T &other)
void remove_ref(dt *old_d)
void swap(reference_counting &other)
reference_counting(const reference_counting &other)
void copy_from(const reference_counting &other)
const T & read() const
reference_counting & operator=(const reference_counting &other)
bool operator==(const reference_counting< T, empty > &o1, const reference_counting< T, empty > &o2)
bool operator!=(const reference_counting< T, empty > &i1, const reference_counting< T, empty > &i2)
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define POSTCONDITION(CONDITION)
Definition invariant.h:479