mCRL2
Loading...
Searching...
No Matches
free_list.h
Go to the documentation of this file.
1// Author(s): Maurice Laveaux
2// Copyright: see the accompanying file COPYING or copy at
3// https://github.com/mCRL2org/mCRL2/blob/master/COPYING
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8
9#ifndef MCRL2_UTILITIES_DETAIL_FREELIST_H_
10#define MCRL2_UTILITIES_DETAIL_FREELIST_H_
11
12#include <cassert>
13#include <atomic>
14#include <cstddef>
15#include <cstdint>
16#include <limits>
17#include <iterator>
18
19namespace mcrl2
20{
21namespace utilities
22{
23namespace detail
24{
25
30template<typename Element>
32{
33public:
34
36 static constexpr std::uintptr_t FreeListSentinel = std::numeric_limits<std::uintptr_t>::max();
37
39 union slot
40 {
41 public:
42 slot() {}
43 ~slot() {}
44
46 slot* next() const noexcept { return m_next; }
47
49 bool has_next() const noexcept { return m_next != nullptr; }
50
52 void next(slot* next) noexcept { m_next = next; }
53
55 Element& element() noexcept { return m_element; }
56
58 operator Element&() { return m_element; }
59
61 void mark() { m_next = reinterpret_cast<slot*>(FreeListSentinel); }
62
64 bool is_marked() const noexcept { return m_next == reinterpret_cast<slot*>(FreeListSentinel); }
65 protected:
66
68 slot* m_next = nullptr;
69
71 Element m_element;
72 };
73
75 template<bool Constant = true>
76 class slot_iterator : std::iterator_traits<Element>
77 {
78 struct Sentinel{};
79
80 using tag = std::input_iterator_tag;
81
82 friend class free_list<Element>;
83 using Freelist = typename std::conditional<Constant, const free_list<Element>, free_list<Element>>::type;
84 using reference = typename std::conditional<Constant, const Element&, Element&>::type;
85 using slot_pointer = typename std::conditional<Constant, const slot*, slot*>::type;
86
87 public:
89 static constexpr Sentinel EndIterator{};
90
92 : m_slot(slot)
93 {}
94
96 : m_slot(list.head()->next())
97 {}
98
100 : m_slot(nullptr)
101 {}
102
104 {
105 m_slot = m_slot->next();
106 return *this;
107 }
108
109 template<bool Constant_ = Constant>
110 typename std::enable_if<!Constant_, reference>::type operator*()
111 {
112 return m_slot->element();
113 }
114
115 template<bool Constant_ = Constant>
116 typename std::enable_if<Constant_, reference>::type operator*() const
117 {
118 return m_slot->element();
119 }
120
121 bool operator != (const slot_iterator& it) const noexcept
122 {
123 return m_slot != it.m_slot;
124 }
125
126 bool operator != (Sentinel) const noexcept
127 {
128 return m_slot != nullptr;
129 }
130
132 {
133 return m_slot;
134 }
135
136 private:
138 };
139
140public:
144
146
148 iterator begin() { return iterator(head().next()); }
149 iterator end() { return iterator(); }
150
153
155 const_iterator begin() const { return const_iterator(*this); }
156 const_iterator end() const { return const_iterator(); }
157
160
163 {
164 slot* current_node = it.get_node();
165 assert(current_node->next() != nullptr); // Cannot erase after the last node.
166
167 // Keep track of the node that we should remove.
168 slot* erased_node = current_node->next();
169 slot* next_node = erased_node->next();
170
171 // Update the next pointer of the current node.
172 current_node->next(next_node);
173 return iterator(next_node);
174 }
175
177 void clear() { head().next(nullptr); }
178
180 bool contains(Element* pointer)
181 {
182 union slot* slot = reinterpret_cast<union slot*>(pointer);
183 for (auto it = begin(); it != end(); ++it)
184 {
185 if (slot == *it)
186 {
187 return true;
188 }
189 }
190
191 return false;
192 }
193
195 std::size_t count()
196 {
197 std::size_t length = 0;
198 for (auto it = begin(); it != end(); ++it)
199 {
200 ++length;
201 }
202 return length;
203 }
204
207 {
208 for (auto it = begin(); it != end();)
209 {
210 slot* current_slot = it.get_slot();
211 ++it;
212 current_slot->mark();
213 }
214
215 head().next(nullptr);
216 }
217
219 bool empty() const noexcept
220 {
221 return !head().has_next();
222 }
223
226 {
227 slot& current = *it.get_slot();
228 element.next(current.next());
229 current.next(&element);
230 return iterator(&element);
231 }
232
234 Element& pop_front()
235 {
236 slot* element = head().next();
237 head().next(element->next());
238 return element->element();
239 }
240
243 {
244 slot.next(head().next());
245 head().next(&slot);
246 }
247
250 void erase_after(iterator position, iterator last)
251 {
252 position.get_slot()->next(last.get_slot());
253 }
254
255private:
257 slot& head() noexcept { return m_head; }
258 const slot& head() const noexcept { return m_head; }
259
263};
264
265} // namespace detail
266} // namespace utilities
267} // namespace mcrl2
268
269#endif // MCRL2_UTILITIES_DETAIL_FREELIST_H_
Iterator over all keys in a bucket list.
Definition free_list.h:77
typename std::conditional< Constant, const free_list< Element >, free_list< Element > >::type Freelist
Definition free_list.h:83
static constexpr Sentinel EndIterator
A end of the iterator sentinel.
Definition free_list.h:89
bool operator!=(const slot_iterator &it) const noexcept
Definition free_list.h:121
std::enable_if< Constant_, reference >::type operator*() const
Definition free_list.h:116
typename std::conditional< Constant, const slot *, slot * >::type slot_pointer
Definition free_list.h:85
std::enable_if<!Constant_, reference >::type operator*()
Definition free_list.h:110
typename std::conditional< Constant, const Element &, Element & >::type reference
Definition free_list.h:84
This essentially implements the std::forward_list, with the difference that it does not own the nodes...
Definition free_list.h:32
bool empty() const noexcept
Definition free_list.h:219
void clear()
Empties the bucket list.
Definition free_list.h:177
void erase_after(iterator position, iterator last)
Erases elements in the range (position, last], constant complexity since no destructors will be calle...
Definition free_list.h:250
bool contains(Element *pointer)
Definition free_list.h:180
slot_iterator< false > iterator
Definition free_list.h:142
static constexpr std::uintptr_t FreeListSentinel
A sentinel value for the next of a slot to indicate that it belonged to the freelist.
Definition free_list.h:36
void push_front(slot &slot)
Puts the given node before the head of the list.
Definition free_list.h:242
const_iterator before_begin() const
Definition free_list.h:159
slot m_head
The first node in the bucket list.
Definition free_list.h:262
const_iterator begin() const
Definition free_list.h:155
slot_iterator< true > const_iterator
Definition free_list.h:143
iterator erase_after(iterator it)
Removes the element after the given iterator from the list. The returned iterator.
Definition free_list.h:162
Element & pop_front()
Removes the head of the list and returns a reference to this head slot.
Definition free_list.h:234
void destructive_mark()
Mark all elements in this list with a special value, destroys the list.
Definition free_list.h:206
slot & head() noexcept
Provides access to the head as if it was an actual slot.
Definition free_list.h:257
iterator insert_after(iterator it, slot &element)
Inserts an element at the position after the iterator.
Definition free_list.h:225
const_iterator end() const
Definition free_list.h:156
const slot & head() const noexcept
Definition free_list.h:258
T * pointer(const T *p)
A class that takes a linear process specification and checks all tau-summands of that LPS for conflue...
Definition indexed_set.h:72
The nodes of the free list without.
Definition free_list.h:40
slot * m_next
Pointer to the next node.
Definition free_list.h:68
void next(slot *next) noexcept
Set the next pointer to the given next pointer.
Definition free_list.h:52
Element m_element
Store the actual element.
Definition free_list.h:71
void mark()
Mark this slot with a special value, destroys the slot.
Definition free_list.h:61