ESBMC
Efficient SMT-based Context-Bounded Model Checker
Loading...
Searching...
No Matches
persistent_map.h
Go to the documentation of this file.
1#ifndef UTIL_PERSISTENT_MAP_H_
2#define UTIL_PERSISTENT_MAP_H_
3
4#include <cstddef>
5#include <functional>
6#include <immer/algorithm.hpp>
7#include <immer/map.hpp>
8#include <immer/map_transient.hpp>
9#include <immer/memory_policy.hpp>
10#include <immer/set.hpp>
11
29template <typename K, typename V, typename Hash>
31{
32 using memory_policy = immer::memory_policy<
33 immer::default_heap_policy,
34 immer::unsafe_refcount_policy,
35 immer::no_lock_policy>;
36 using map_t = immer::map<K, V, Hash, std::equal_to<K>, memory_policy>;
37
38 map_t m_;
39
40public:
41 persistent_map() = default;
42
43 std::size_t size() const
44 {
45 return m_.size();
46 }
47
48 bool empty() const
49 {
50 return m_.size() == 0;
51 }
52
53 // nullptr if absent; otherwise a pointer into shared storage valid until
54 // the next mutation. Callers must not stash it across a set()/erase().
55 const V *find(const K &k) const
56 {
57 return m_.find(k);
58 }
59
60 // The value at a key known to be present. Like find(), the reference is
61 // valid only until the next mutation.
62 const V &at(const K &k) const
63 {
64 return m_.at(k);
65 }
66
67 // Insert or overwrite. O(log N), shares untouched subtrees.
68 void set(const K &k, const V &v)
69 {
70 m_ = std::move(m_).set(k, v);
71 }
72
73 // Move-in overload: immer's set takes its value by value, so handing it an
74 // rvalue moves rather than copies.
75 void set(const K &k, V &&v)
76 {
77 m_ = std::move(m_).set(k, std::move(v));
78 }
79
80 // Read-modify-write in one HAMT walk instead of find + set. fn receives the
81 // current value (value-initialised when the key is absent) and returns the
82 // new one.
83 template <class Fn>
84 void update(const K &k, Fn &&fn)
85 {
86 m_ = std::move(m_).update(k, std::forward<Fn>(fn));
87 }
88
89 // Erase; true when the key was present. O(log N), shares subtrees.
90 bool erase(const K &k)
91 {
92 std::size_t n = m_.size();
93 m_ = std::move(m_).erase(k);
94 return m_.size() != n;
95 }
96
97 void clear()
98 {
99 m_ = map_t{};
100 }
101
102 using const_iterator = typename map_t::iterator;
104 {
105 return m_.begin();
106 }
108 {
109 return m_.end();
110 }
111
112 // Structural diff against another map: added(kv) for keys in `other`
113 // not here, removed(kv) for keys here not in `other`, changed(a, b)
114 // for a shared key whose value differs. O(|diff|) when the two maps
115 // share structure (both descend from a common snapshot), which is
116 // the case at a control-flow merge — so a merge costs the paths'
117 // divergence, not the whole map.
118 template <class Added, class Removed, class Changed>
119 void diff(
120 const persistent_map &other,
121 Added &&added,
122 Removed &&removed,
123 Changed &&changed) const
124 {
125 immer::diff(
126 m_,
127 other.m_,
128 immer::make_differ(
129 std::forward<Added>(added),
130 std::forward<Removed>(removed),
131 std::forward<Changed>(changed)));
132 }
133};
134
143template <typename K, typename Hash>
145{
146 using memory_policy = immer::memory_policy<
147 immer::default_heap_policy,
148 immer::unsafe_refcount_policy,
149 immer::no_lock_policy>;
150 using set_t = immer::set<K, Hash, std::equal_to<K>, memory_policy>;
151
152 set_t s_;
153
154public:
155 persistent_set() = default;
156
157 std::size_t size() const
158 {
159 return s_.size();
160 }
161
162 bool empty() const
163 {
164 return s_.size() == 0;
165 }
166
167 // 1 if present, 0 otherwise.
168 std::size_t count(const K &k) const
169 {
170 return s_.count(k);
171 }
172
173 // Insert. O(log N), shares untouched subtrees.
174 void insert(const K &k)
175 {
176 s_ = std::move(s_).insert(k);
177 }
178
179 // Erase; true when the key was present. O(log N), shares subtrees.
180 bool erase(const K &k)
181 {
182 std::size_t n = s_.size();
183 s_ = std::move(s_).erase(k);
184 return s_.size() != n;
185 }
186
187 using const_iterator = typename set_t::iterator;
189 {
190 return s_.begin();
191 }
193 {
194 return s_.end();
195 }
196
197 // Structural diff against another set: added(k) for a key in `other` not
198 // here, removed(k) for one here not in `other`. O(|diff|) when the two
199 // sets share structure (both descend from a common snapshot) — so the
200 // union at a control-flow merge costs the paths' divergence, not N.
201 template <class Added, class Removed>
202 void diff(const persistent_set &other, Added &&added, Removed &&removed) const
203 {
204 immer::diff(
205 s_,
206 other.s_,
207 immer::make_differ(
208 std::forward<Added>(added), std::forward<Removed>(removed)));
209 }
210};
211
212#endif /* UTIL_PERSISTENT_MAP_H_ */
bool erase(const K &k)
Definition persistent_map.h:90
const V * find(const K &k) const
Definition persistent_map.h:55
void diff(const persistent_map &other, Added &&added, Removed &&removed, Changed &&changed) const
Definition persistent_map.h:119
const_iterator begin() const
Definition persistent_map.h:103
void set(const K &k, const V &v)
Definition persistent_map.h:68
persistent_map()=default
const V & at(const K &k) const
Definition persistent_map.h:62
void clear()
Definition persistent_map.h:97
std::size_t size() const
Definition persistent_map.h:43
bool empty() const
Definition persistent_map.h:48
const_iterator end() const
Definition persistent_map.h:107
void set(const K &k, V &&v)
Definition persistent_map.h:75
void update(const K &k, Fn &&fn)
Definition persistent_map.h:84
typename map_t::iterator const_iterator
Definition persistent_map.h:102
std::size_t size() const
Definition persistent_map.h:157
const_iterator end() const
Definition persistent_map.h:192
bool empty() const
Definition persistent_map.h:162
typename set_t::iterator const_iterator
Definition persistent_map.h:187
const_iterator begin() const
Definition persistent_map.h:188
void diff(const persistent_set &other, Added &&added, Removed &&removed) const
Definition persistent_map.h:202
persistent_set()=default
std::size_t count(const K &k) const
Definition persistent_map.h:168
void insert(const K &k)
Definition persistent_map.h:174
bool erase(const K &k)
Definition persistent_map.h:180
@ other
Definition converter_compare.cpp:887