Halide 19.0.0
Halide compiler and libraries
Loading...
Searching...
No Matches
linked_list.h
Go to the documentation of this file.
1#ifndef HALIDE_RUNTIME_LINKED_LIST_H
2#define HALIDE_RUNTIME_LINKED_LIST_H
3
4#include "../HalideRuntime.h"
5#include "memory_arena.h"
6
7namespace Halide {
8namespace Runtime {
9namespace Internal {
10
11// Doubly linked list container
12// -- Implemented using MemoryArena for allocation
14public:
15 // Disable copy support
16 LinkedList(const LinkedList &) = delete;
17 LinkedList &operator=(const LinkedList &) = delete;
18
19 // Default initial capacity
20 static constexpr uint32_t default_capacity = uint32_t(32); // smallish
21
22 // List entry
23 struct EntryType {
24 void *value = nullptr;
25 EntryType *prev_ptr = nullptr;
26 EntryType *next_ptr = nullptr;
27 };
28
29 LinkedList(void *user_context, uint32_t entry_size, uint32_t capacity = default_capacity,
30 const SystemMemoryAllocatorFns &allocator = default_allocator());
32
33 void initialize(void *user_context, uint32_t entry_size, uint32_t capacity = default_capacity,
34 const SystemMemoryAllocatorFns &allocator = default_allocator());
35
37 EntryType *back();
38
39 const EntryType *front() const;
40 const EntryType *back() const;
41
42 EntryType *prepend(void *user_context);
43 EntryType *prepend(void *user_context, const void *value);
44
45 EntryType *append(void *user_context);
46 EntryType *append(void *user_context, const void *value);
47
48 void pop_front(void *user_context);
49 void pop_back(void *user_context);
50
51 EntryType *insert_before(void *user_context, EntryType *entry_ptr);
52 EntryType *insert_before(void *user_context, EntryType *entry_ptr, const void *value);
53
54 EntryType *insert_after(void *user_context, EntryType *entry_ptr);
55 EntryType *insert_after(void *user_context, EntryType *entry_ptr, const void *value);
56
57 void remove(void *user_context, EntryType *entry_ptr);
58 void clear(void *user_context);
59 void destroy(void *user_context);
60
61 size_t size() const;
62 bool empty() const;
63
66
67private:
68 EntryType *reserve(void *user_context);
69 void reclaim(void *user_context, EntryType *entry_ptr);
70
71 MemoryArena *link_arena = nullptr;
72 MemoryArena *data_arena = nullptr;
73 EntryType *front_ptr = nullptr;
74 EntryType *back_ptr = nullptr;
75 size_t entry_count = 0;
76};
77
78LinkedList::LinkedList(void *user_context, uint32_t entry_size, uint32_t capacity,
79 const SystemMemoryAllocatorFns &sma) {
80 uint32_t arena_capacity = max(capacity, MemoryArena::default_capacity);
81 link_arena = MemoryArena::create(user_context, {sizeof(EntryType), arena_capacity, 0}, sma);
82 data_arena = MemoryArena::create(user_context, {entry_size, arena_capacity, 0}, sma);
83 front_ptr = nullptr;
84 back_ptr = nullptr;
85 entry_count = 0;
86}
87
89 destroy(nullptr);
90}
91
92void LinkedList::initialize(void *user_context, uint32_t entry_size, uint32_t capacity,
93 const SystemMemoryAllocatorFns &sma) {
94 uint32_t arena_capacity = max(capacity, MemoryArena::default_capacity);
95 link_arena = MemoryArena::create(user_context, {sizeof(EntryType), arena_capacity, 0}, sma);
96 data_arena = MemoryArena::create(user_context, {entry_size, arena_capacity, 0}, sma);
97 front_ptr = nullptr;
98 back_ptr = nullptr;
99 entry_count = 0;
100}
101
102void LinkedList::destroy(void *user_context) {
103 clear(nullptr);
104 if (link_arena) {
105 MemoryArena::destroy(nullptr, link_arena);
106 }
107 if (data_arena) {
108 MemoryArena::destroy(nullptr, data_arena);
109 }
110 link_arena = nullptr;
111 data_arena = nullptr;
112 front_ptr = nullptr;
113 back_ptr = nullptr;
114 entry_count = 0;
115}
116
118 return front_ptr;
119}
120
122 return back_ptr;
123}
124
126 return front_ptr;
127}
128
130 return back_ptr;
131}
132
133typename LinkedList::EntryType *
134LinkedList::prepend(void *user_context) {
135 EntryType *entry_ptr = reserve(user_context);
136 if (empty()) {
137 front_ptr = entry_ptr;
138 back_ptr = entry_ptr;
139 entry_count = 1;
140 } else {
141 entry_ptr->next_ptr = front_ptr;
142 front_ptr->prev_ptr = entry_ptr;
143 front_ptr = entry_ptr;
144 ++entry_count;
145 }
146 return entry_ptr;
147}
148
149typename LinkedList::EntryType *
150LinkedList::append(void *user_context) {
151 EntryType *entry_ptr = reserve(user_context);
152 if (empty()) {
153 front_ptr = entry_ptr;
154 back_ptr = entry_ptr;
155 entry_count = 1;
156 } else {
157 entry_ptr->prev_ptr = back_ptr;
158 back_ptr->next_ptr = entry_ptr;
159 back_ptr = entry_ptr;
160 ++entry_count;
161 }
162 return entry_ptr;
163}
164
165typename LinkedList::EntryType *
166LinkedList::prepend(void *user_context, const void *value) {
167 EntryType *entry_ptr = prepend(user_context);
168 memcpy(entry_ptr->value, value, data_arena->current_config().entry_size);
169 return entry_ptr;
170}
171
172typename LinkedList::EntryType *
173LinkedList::append(void *user_context, const void *value) {
174 EntryType *entry_ptr = append(user_context);
175 memcpy(entry_ptr->value, value, data_arena->current_config().entry_size);
176 return entry_ptr;
177}
178
179void LinkedList::pop_front(void *user_context) {
180 halide_debug_assert(user_context, (entry_count > 0));
181 EntryType *remove_ptr = front_ptr;
182 EntryType *next_ptr = remove_ptr->next_ptr;
183 if (next_ptr != nullptr) {
184 next_ptr->prev_ptr = nullptr;
185 }
186 front_ptr = next_ptr;
187 reclaim(user_context, remove_ptr);
188 --entry_count;
189}
190
191void LinkedList::pop_back(void *user_context) {
192 halide_debug_assert(user_context, (entry_count > 0));
193 EntryType *remove_ptr = back_ptr;
194 EntryType *prev_ptr = remove_ptr->prev_ptr;
195 if (prev_ptr != nullptr) {
196 prev_ptr->next_ptr = nullptr;
197 }
198 back_ptr = prev_ptr;
199 reclaim(user_context, remove_ptr);
200 --entry_count;
201}
202
203void LinkedList::clear(void *user_context) {
204 if (empty() == false) {
205 EntryType *remove_ptr = back_ptr;
206 while (remove_ptr != nullptr) {
207 EntryType *prev_ptr = remove_ptr->prev_ptr;
208 reclaim(user_context, remove_ptr);
209 remove_ptr = prev_ptr;
210 }
211 front_ptr = nullptr;
212 back_ptr = nullptr;
213 entry_count = 0;
214 }
215}
216
217void LinkedList::remove(void *user_context, EntryType *entry_ptr) {
218 halide_debug_assert(user_context, (entry_ptr != nullptr));
219 halide_debug_assert(user_context, (entry_count > 0));
220
221 if (entry_ptr->prev_ptr != nullptr) {
222 entry_ptr->prev_ptr->next_ptr = entry_ptr->next_ptr;
223 } else {
224 halide_debug_assert(user_context, (front_ptr == entry_ptr));
225 front_ptr = entry_ptr->next_ptr;
226 }
227
228 if (entry_ptr->next_ptr != nullptr) {
229 entry_ptr->next_ptr->prev_ptr = entry_ptr->prev_ptr;
230 } else {
231 halide_debug_assert(user_context, (back_ptr == entry_ptr));
232 back_ptr = entry_ptr->prev_ptr;
233 }
234
235 reclaim(user_context, entry_ptr);
236 --entry_count;
237}
238
239typename LinkedList::EntryType *
240LinkedList::insert_before(void *user_context, EntryType *entry_ptr) {
241 if (entry_ptr != nullptr) {
242 EntryType *prev_ptr = entry_ptr->prev_ptr;
243 EntryType *new_ptr = reserve(user_context);
244 new_ptr->prev_ptr = prev_ptr;
245 new_ptr->next_ptr = entry_ptr;
246 entry_ptr->prev_ptr = new_ptr;
247 if (prev_ptr != nullptr) {
248 prev_ptr->next_ptr = new_ptr;
249 } else {
250 halide_debug_assert(user_context, (front_ptr == entry_ptr));
251 front_ptr = new_ptr;
252 }
253 ++entry_count;
254 return new_ptr;
255 } else {
256 return append(user_context);
257 }
258}
259
260typename LinkedList::EntryType *
261LinkedList::insert_after(void *user_context, EntryType *entry_ptr) {
262 if (entry_ptr != nullptr) {
263 EntryType *next_ptr = entry_ptr->next_ptr;
264 EntryType *new_ptr = reserve(user_context);
265 new_ptr->next_ptr = next_ptr;
266 new_ptr->prev_ptr = entry_ptr;
267 entry_ptr->next_ptr = new_ptr;
268 if (next_ptr != nullptr) {
269 next_ptr->prev_ptr = new_ptr;
270 } else {
271 halide_debug_assert(user_context, (back_ptr == entry_ptr));
272 back_ptr = new_ptr;
273 }
274 ++entry_count;
275 return new_ptr;
276 } else {
277 return prepend(user_context);
278 }
279}
280
281typename LinkedList::EntryType *
282LinkedList::insert_before(void *user_context, EntryType *entry_ptr, const void *value) {
283 EntryType *new_ptr = insert_before(user_context, entry_ptr);
284 memcpy(new_ptr->value, value, data_arena->current_config().entry_size);
285 return new_ptr;
286}
287
288typename LinkedList::EntryType *
289LinkedList::insert_after(void *user_context, EntryType *entry_ptr, const void *value) {
290 EntryType *new_ptr = insert_after(user_context, entry_ptr);
291 memcpy(new_ptr->value, value, data_arena->current_config().entry_size);
292 return new_ptr;
293}
294
295size_t LinkedList::size() const {
296 return entry_count;
297}
298
299bool LinkedList::empty() const {
300 return entry_count == 0;
301}
302
305 return link_arena->current_allocator();
306}
307
312
313typename LinkedList::EntryType *
314LinkedList::reserve(void *user_context) {
315 EntryType *entry_ptr = static_cast<EntryType *>(
316 link_arena->reserve(user_context, true));
317 entry_ptr->value = data_arena->reserve(user_context, true);
318 entry_ptr->next_ptr = nullptr;
319 entry_ptr->prev_ptr = nullptr;
320 return entry_ptr;
321}
322
323void LinkedList::reclaim(void *user_context, EntryType *entry_ptr) {
324 void *value_ptr = entry_ptr->value;
325 entry_ptr->value = nullptr;
326 entry_ptr->next_ptr = nullptr;
327 entry_ptr->prev_ptr = nullptr;
328 data_arena->reclaim(user_context, value_ptr);
329 link_arena->reclaim(user_context, entry_ptr);
330}
331
332// --
333
334} // namespace Internal
335} // namespace Runtime
336} // namespace Halide
337
338#endif // HALIDE_RUNTIME_LINKED_LIST_H
This file declares the routines used by Halide internally in its runtime.
void initialize(void *user_context, uint32_t entry_size, uint32_t capacity=default_capacity, const SystemMemoryAllocatorFns &allocator=default_allocator())
Definition linked_list.h:92
EntryType * prepend(void *user_context)
const SystemMemoryAllocatorFns & current_allocator() const
EntryType * append(void *user_context)
void clear(void *user_context)
void pop_front(void *user_context)
LinkedList & operator=(const LinkedList &)=delete
static const SystemMemoryAllocatorFns & default_allocator()
EntryType * insert_after(void *user_context, EntryType *entry_ptr)
void remove(void *user_context, EntryType *entry_ptr)
void pop_back(void *user_context)
void destroy(void *user_context)
static constexpr uint32_t default_capacity
Definition linked_list.h:20
LinkedList(const LinkedList &)=delete
EntryType * insert_before(void *user_context, EntryType *entry_ptr)
void * reserve(void *user_context, bool initialize=false)
static MemoryArena * create(void *user_context, const Config &config, const SystemMemoryAllocatorFns &allocator=default_allocator())
const Config & current_config() const
static constexpr uint32_t default_capacity
const SystemMemoryAllocatorFns & current_allocator() const
static void destroy(void *user_context, MemoryArena *arena)
void reclaim(void *user_context, void *ptr)
static const SystemMemoryAllocatorFns & default_allocator()
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
@ Internal
Not visible externally, similar to 'static' linkage in C.
Expr max(const FuncRef &a, const FuncRef &b)
Definition Func.h:600
#define halide_debug_assert(user_context, cond)
halide_debug_assert() is like halide_assert(), but only expands into a check when DEBUG_RUNTIME is de...
void * memcpy(void *s1, const void *s2, size_t n)
unsigned __INT32_TYPE__ uint32_t
Definition linked_list.h:23
EntryType * prev_ptr
Definition linked_list.h:25
EntryType * next_ptr
Definition linked_list.h:26
void * value
Definition linked_list.h:24