Blender V5.0
BLI_memblock.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include <algorithm>
12#include <cstdlib>
13#include <cstring>
14
15#include "BLI_utildefines.h"
16
17#include "BLI_memblock.h" /* own include */
18
19#include "MEM_guardedalloc.h"
20
21#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
22
23#define CHUNK_LIST_SIZE 16
24
45
47{
48 BLI_assert(elem_size < chunk_size);
49
50 BLI_memblock *mblk = MEM_callocN<BLI_memblock>("BLI_memblock");
51 mblk->elem_size = int(elem_size);
52 mblk->elem_next = 0;
53 mblk->elem_last = -1;
54 mblk->chunk_size = int(chunk_size);
56 mblk->chunk_list = MEM_calloc_arrayN<void *>(size_t(mblk->chunk_len), "chunk list");
57 mblk->chunk_list[0] = MEM_mallocN_aligned(size_t(mblk->chunk_size), 32, "BLI_memblock chunk");
58 memset(mblk->chunk_list[0], 0x0, uint(mblk->chunk_size));
59 mblk->chunk_max_ofs = (mblk->chunk_size / mblk->elem_size) * mblk->elem_size;
60 mblk->elem_next_ofs = 0;
61 mblk->chunk_next = 0;
62 return mblk;
63}
64
66{
67 int elem_per_chunk = mblk->chunk_size / mblk->elem_size;
68
69 if (free_callback) {
70 for (int i = 0; i <= mblk->elem_last; i++) {
71 int chunk_idx = i / elem_per_chunk;
72 int elem_idx = i - elem_per_chunk * chunk_idx;
73 void *val = (char *)(mblk->chunk_list[chunk_idx]) + mblk->elem_size * elem_idx;
74 free_callback(val);
75 }
76 }
77
78 for (int i = 0; i < mblk->chunk_len; i++) {
80 }
82 MEM_freeN(mblk);
83}
84
86{
87 int elem_per_chunk = mblk->chunk_size / mblk->elem_size;
88 int last_used_chunk = mblk->elem_next / elem_per_chunk;
89
90 if (free_callback) {
91 for (int i = mblk->elem_last; i >= mblk->elem_next; i--) {
92 int chunk_idx = i / elem_per_chunk;
93 int elem_idx = i - elem_per_chunk * chunk_idx;
94 void *val = (char *)(mblk->chunk_list[chunk_idx]) + mblk->elem_size * elem_idx;
95 free_callback(val);
96 }
97 }
98
99 for (int i = last_used_chunk + 1; i < mblk->chunk_len; i++) {
100 MEM_SAFE_FREE(mblk->chunk_list[i]);
101 }
102
103 if (UNLIKELY(last_used_chunk + 1 < mblk->chunk_len - CHUNK_LIST_SIZE)) {
104 mblk->chunk_len -= CHUNK_LIST_SIZE;
105 mblk->chunk_list = static_cast<void **>(
106 MEM_recallocN(mblk->chunk_list, sizeof(void *) * uint(mblk->chunk_len)));
107 }
108
109 mblk->elem_last = mblk->elem_next - 1;
110 mblk->elem_next = 0;
111 mblk->elem_next_ofs = 0;
112 mblk->chunk_next = 0;
113}
114
116{
117 /* Bookkeeping. */
118 mblk->elem_last = std::max(mblk->elem_last, mblk->elem_next);
119 mblk->elem_next++;
120
121 void *ptr = (char *)(mblk->chunk_list[mblk->chunk_next]) + mblk->elem_next_ofs;
122
123 mblk->elem_next_ofs += mblk->elem_size;
124
125 if (mblk->elem_next_ofs == mblk->chunk_max_ofs) {
126 mblk->elem_next_ofs = 0;
127 mblk->chunk_next++;
128
129 if (UNLIKELY(mblk->chunk_next >= mblk->chunk_len)) {
130 mblk->chunk_len += CHUNK_LIST_SIZE;
131 mblk->chunk_list = static_cast<void **>(
132 MEM_recallocN(mblk->chunk_list, sizeof(void *) * uint(mblk->chunk_len)));
133 }
134
135 if (UNLIKELY(mblk->chunk_list[mblk->chunk_next] == nullptr)) {
137 uint(mblk->chunk_size), 32, "BLI_memblock chunk");
138 memset(mblk->chunk_list[mblk->chunk_next], 0x0, uint(mblk->chunk_size));
139 }
140 }
141 return ptr;
142}
143
145{
146 /* Small copy of the memblock used for better cache coherence. */
147 iter->chunk_list = mblk->chunk_list;
148 iter->end_index = mblk->elem_next;
149 iter->cur_index = 0;
150 iter->chunk_idx = 0;
151 iter->elem_ofs = 0;
152 iter->elem_size = mblk->elem_size;
153 iter->chunk_max_ofs = mblk->chunk_max_ofs;
154}
155
157{
158 if (iter->cur_index == iter->end_index) {
159 return nullptr;
160 }
161
162 iter->cur_index++;
163
164 void *ptr = (char *)(iter->chunk_list[iter->chunk_idx]) + iter->elem_ofs;
165
166 iter->elem_ofs += iter->elem_size;
167
168 if (iter->elem_ofs == iter->chunk_max_ofs) {
169 iter->elem_ofs = 0;
170 iter->chunk_idx++;
171 }
172 return ptr;
173}
174
175void *BLI_memblock_elem_get(BLI_memblock *mblk, int chunk, int elem)
176{
177 BLI_assert(chunk < mblk->chunk_len);
178 int elem_per_chunk = mblk->chunk_size / mblk->elem_size;
179 chunk += elem / elem_per_chunk;
180 elem = elem % elem_per_chunk;
181 return (char *)(mblk->chunk_list[chunk]) + mblk->elem_size * elem;
182}
#define BLI_assert(a)
Definition BLI_assert.h:46
#define CHUNK_LIST_SIZE
void BLI_memblock_clear(BLI_memblock *mblk, MemblockValFreeFP free_callback)
BLI_memblock * BLI_memblock_create_ex(uint elem_size, uint chunk_size)
void * BLI_memblock_elem_get(BLI_memblock *mblk, int chunk, int elem)
void * BLI_memblock_iterstep(BLI_memblock_iter *iter)
void BLI_memblock_iternew(BLI_memblock *mblk, BLI_memblock_iter *iter)
void * BLI_memblock_alloc(BLI_memblock *mblk)
void BLI_memblock_destroy(BLI_memblock *mblk, MemblockValFreeFP free_callback)
void(* MemblockValFreeFP)(void *val)
unsigned int uint
#define UNLIKELY(x)
Read Guarded memory(de)allocation.
#define MEM_recallocN(vmemh, len)
#define MEM_SAFE_FREE(v)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_mallocN_aligned(size_t len, size_t alignment, const char *str)
Definition mallocn.cc:138
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
void ** chunk_list
i
Definition text_draw.cc:230
PointerRNA * ptr
Definition wm_files.cc:4238