1 #ifndef HALIDE_RUNTIME_BLOCK_STORAGE_H
2 #define HALIDE_RUNTIME_BLOCK_STORAGE_H
4 #include "../HalideRuntime.h"
5 #include "../printer.h"
39 void reserve(
void *user_context,
size_t capacity,
bool free_existing =
false);
40 void resize(
void *user_context,
size_t entry_count,
bool realloc =
true);
42 void assign(
void *user_context,
size_t index,
const void *entry_ptr);
43 void insert(
void *user_context,
size_t index,
const void *entry_ptr);
44 void prepend(
void *user_context,
const void *entry_ptr);
45 void append(
void *user_context,
const void *entry_ptr);
46 void remove(
void *user_context,
size_t index);
48 void fill(
void *user_context,
const void *array,
size_t array_size);
49 void insert(
void *user_context,
size_t index,
const void *array,
size_t array_size);
50 void replace(
void *user_context,
size_t index,
const void *array,
size_t array_size);
51 void prepend(
void *user_context,
const void *array,
size_t array_size);
52 void append(
void *user_context,
const void *array,
size_t array_size);
53 void remove(
void *user_context,
size_t index,
size_t entry_count);
58 void clear(
void *user_context);
59 void destroy(
void *user_context);
74 const void *
data()
const;
75 const void *
front()
const;
76 const void *
back()
const;
85 void allocate(
void *user_context,
size_t capacity);
95 : config(cfg), allocator(sma) {
105 :
BlockStorage(nullptr, other.config, other.allocator) {
107 resize(
nullptr, other.count);
118 if (ptr !=
nullptr) {
121 capacity = count = 0;
128 capacity = count = 0;
136 if (&other !=
this) {
137 config = other.config;
138 resize(
nullptr, other.count);
139 if (count != 0 && other.ptr !=
nullptr) {
150 if (count != other.count) {
157 return !(*
this == other);
161 if (array_size != 0) {
162 resize(user_context, array_size);
169 replace(user_context, index, entry_ptr, 1);
173 insert(user_context, 0, entry_ptr, 1);
177 append(user_context, entry_ptr, 1);
195 new_capacity =
max(new_capacity, count);
197 if ((new_capacity < capacity) && !free_existing) {
198 new_capacity = capacity;
201 allocate(user_context, new_capacity);
205 size_t current_size = capacity;
206 size_t requested_size = entry_count;
208 size_t actual_size = current_size;
209 count = requested_size;
212 if (requested_size > current_size) {
213 actual_size =
max(requested_size,
max(current_size * 3 / 2, minimum_size));
214 }
else if (!realloc) {
218 #ifdef DEBUG_RUNTIME_INTERNAL
219 debug(user_context) <<
"BlockStorage: Resize ("
220 <<
"requested_size=" << (
int32_t)requested_size <<
" "
221 <<
"current_size=" << (
int32_t)current_size <<
" "
222 <<
"minimum_size=" << (
int32_t)minimum_size <<
" "
223 <<
"actual_size=" << (
int32_t)actual_size <<
" "
225 <<
"realloc=" << (realloc ?
"true" :
"false") <<
")...\n";
228 allocate(user_context, actual_size);
232 if (capacity > count) {
233 void *new_ptr =
nullptr;
235 size_t actual_bytes = count * config.
entry_size;
236 new_ptr = allocator.
allocate(user_context, actual_bytes);
237 memcpy(new_ptr, ptr, actual_bytes);
246 insert(user_context, index, entry_ptr, 1);
250 remove(user_context, index, 1);
255 const size_t last_index =
size();
256 if (index < (last_index - entry_count)) {
257 size_t dst_offset = index * config.
entry_size;
258 size_t src_offset = (index + entry_count) * config.
entry_size;
259 size_t bytes = (last_index - index - entry_count) * config.
entry_size;
261 #ifdef DEBUG_RUNTIME_INTERNAL
262 debug(user_context) <<
"BlockStorage: Remove ("
263 <<
"index=" << (
int32_t)index <<
" "
264 <<
"entry_count=" << (
int32_t)entry_count <<
" "
266 <<
"last_index=" << (
int32_t)last_index <<
" "
267 <<
"src_offset=" << (
int32_t)src_offset <<
" "
268 <<
"dst_offset=" << (
int32_t)dst_offset <<
" "
269 <<
"bytes=" << (
int32_t)bytes <<
")...\n";
273 memmove(dst_ptr, src_ptr, bytes);
275 resize(user_context, last_index - entry_count);
281 size_t remaining = count - index;
284 debug(user_context) <<
"BlockStorage: Replace ("
285 <<
"index=" << (
int32_t)index <<
" "
286 <<
"array_size=" << (
int32_t)array_size <<
" "
288 <<
"offset=" << (
int32_t)offset <<
" "
289 <<
"remaining=" << (
int32_t)remaining <<
" "
290 <<
"capacity=" << (
int32_t)capacity <<
")...\n";
294 size_t copy_count =
min(remaining, array_size);
297 count =
max(count, index + copy_count);
302 const size_t last_index =
size();
303 resize(user_context, last_index + array_size);
304 if (index < last_index) {
305 size_t src_offset = index * config.
entry_size;
306 size_t dst_offset = (index + array_size) * config.
entry_size;
307 size_t bytes = (last_index - index) * config.
entry_size;
310 memmove(dst_ptr, src_ptr, bytes);
312 replace(user_context, index, array, array_size);
316 insert(user_context, 0, array, array_size);
320 const size_t last_index =
size();
321 insert(user_context, last_index, array, array_size);
329 return (count >= capacity);
333 return (index < capacity);
365 size_t index = count - 1;
380 size_t index = count - 1;
384 void BlockStorage::allocate(
void *user_context,
size_t new_capacity) {
385 if (new_capacity != capacity) {
387 size_t requested_bytes = new_capacity * config.
entry_size;
389 size_t block_count = (requested_bytes / block_size);
390 block_count += (requested_bytes % block_size) ? 1 : 0;
391 size_t alloc_size = block_count * block_size;
392 #ifdef DEBUG_RUNTIME_INTERNAL
393 debug(user_context) <<
"BlockStorage: Allocating ("
394 <<
"requested_bytes=" << (
int32_t)requested_bytes <<
" "
395 <<
"block_size=" << (
int32_t)block_size <<
" "
396 <<
"block_count=" << (
int32_t)block_count <<
" "
397 <<
"alloc_size=" << (
int32_t)alloc_size <<
") ...\n";
399 void *new_ptr = alloc_size ? allocator.
allocate(user_context, alloc_size) :
nullptr;
400 if (count != 0 && ptr !=
nullptr && new_ptr !=
nullptr) {
403 if (ptr !=
nullptr) {
407 capacity = new_capacity;
412 const SystemMemoryAllocatorFns &
414 return this->allocator;
419 static Config default_cfg;
432 return native_allocator;
441 #endif // HALIDE_RUNTIME_BLOCK_STORAGE_H