Blender  V3.3
BLI_memblock.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2008 Blender Foundation. All rights reserved. */
3 
11 #include <stdlib.h>
12 #include <string.h>
13 
14 #include "atomic_ops.h"
15 
16 #include "BLI_utildefines.h"
17 
18 #include "BLI_memblock.h" /* own include */
19 
20 #include "MEM_guardedalloc.h"
21 
22 #include "BLI_strict_flags.h" /* keep last */
23 
24 #define CHUNK_LIST_SIZE 16
25 
26 struct BLI_memblock {
27  void **chunk_list;
28 
30  int elem_size;
32  int elem_next;
34  int elem_last;
44  int chunk_len;
45 };
46 
48 {
49  BLI_assert(elem_size < chunk_size);
50 
51  BLI_memblock *mblk = MEM_mallocN(sizeof(BLI_memblock), "BLI_memblock");
52  mblk->elem_size = (int)elem_size;
53  mblk->elem_next = 0;
54  mblk->elem_last = -1;
55  mblk->chunk_size = (int)chunk_size;
56  mblk->chunk_len = CHUNK_LIST_SIZE;
57  mblk->chunk_list = MEM_callocN(sizeof(void *) * (uint)mblk->chunk_len, "chunk list");
58  mblk->chunk_list[0] = MEM_mallocN_aligned((uint)mblk->chunk_size, 32, "BLI_memblock chunk");
59  memset(mblk->chunk_list[0], 0x0, (uint)mblk->chunk_size);
60  mblk->chunk_max_ofs = (mblk->chunk_size / mblk->elem_size) * mblk->elem_size;
61  mblk->elem_next_ofs = 0;
62  mblk->chunk_next = 0;
63  return mblk;
64 }
65 
67 {
68  int elem_per_chunk = mblk->chunk_size / mblk->elem_size;
69 
70  if (free_callback) {
71  for (int i = 0; i <= mblk->elem_last; i++) {
72  int chunk_idx = i / elem_per_chunk;
73  int elem_idx = i - elem_per_chunk * chunk_idx;
74  void *val = (char *)(mblk->chunk_list[chunk_idx]) + mblk->elem_size * elem_idx;
75  free_callback(val);
76  }
77  }
78 
79  for (int i = 0; i < mblk->chunk_len; i++) {
80  MEM_SAFE_FREE(mblk->chunk_list[i]);
81  }
83  MEM_freeN(mblk);
84 }
85 
87 {
88  int elem_per_chunk = mblk->chunk_size / mblk->elem_size;
89  int last_used_chunk = mblk->elem_next / elem_per_chunk;
90 
91  if (free_callback) {
92  for (int i = mblk->elem_last; i >= mblk->elem_next; i--) {
93  int chunk_idx = i / elem_per_chunk;
94  int elem_idx = i - elem_per_chunk * chunk_idx;
95  void *val = (char *)(mblk->chunk_list[chunk_idx]) + mblk->elem_size * elem_idx;
96  free_callback(val);
97  }
98  }
99 
100  for (int i = last_used_chunk + 1; i < mblk->chunk_len; i++) {
101  MEM_SAFE_FREE(mblk->chunk_list[i]);
102  }
103 
104  if (UNLIKELY(last_used_chunk + 1 < mblk->chunk_len - CHUNK_LIST_SIZE)) {
105  mblk->chunk_len -= CHUNK_LIST_SIZE;
106  mblk->chunk_list = 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  if (mblk->elem_last < mblk->elem_next) {
119  mblk->elem_last = mblk->elem_next;
120  }
121  mblk->elem_next++;
122 
123  void *ptr = (char *)(mblk->chunk_list[mblk->chunk_next]) + mblk->elem_next_ofs;
124 
125  mblk->elem_next_ofs += mblk->elem_size;
126 
127  if (mblk->elem_next_ofs == mblk->chunk_max_ofs) {
128  mblk->elem_next_ofs = 0;
129  mblk->chunk_next++;
130 
131  if (UNLIKELY(mblk->chunk_next >= mblk->chunk_len)) {
132  mblk->chunk_len += CHUNK_LIST_SIZE;
133  mblk->chunk_list = MEM_recallocN(mblk->chunk_list, sizeof(void *) * (uint)mblk->chunk_len);
134  }
135 
136  if (UNLIKELY(mblk->chunk_list[mblk->chunk_next] == NULL)) {
138  (uint)mblk->chunk_size, 32, "BLI_memblock chunk");
139  memset(mblk->chunk_list[mblk->chunk_next], 0x0, (uint)mblk->chunk_size);
140  }
141  }
142  return ptr;
143 }
144 
146 {
147  /* Small copy of the memblock used for better cache coherence. */
148  iter->chunk_list = mblk->chunk_list;
149  iter->end_index = mblk->elem_next;
150  iter->cur_index = 0;
151  iter->chunk_idx = 0;
152  iter->elem_ofs = 0;
153  iter->elem_size = mblk->elem_size;
154  iter->chunk_max_ofs = mblk->chunk_max_ofs;
155 }
156 
158 {
159  if (iter->cur_index == iter->end_index) {
160  return NULL;
161  }
162 
163  iter->cur_index++;
164 
165  void *ptr = (char *)(iter->chunk_list[iter->chunk_idx]) + iter->elem_ofs;
166 
167  iter->elem_ofs += iter->elem_size;
168 
169  if (iter->elem_ofs == iter->chunk_max_ofs) {
170  iter->elem_ofs = 0;
171  iter->chunk_idx++;
172  }
173  return ptr;
174 }
175 
176 void *BLI_memblock_elem_get(BLI_memblock *mblk, int chunk, int elem)
177 {
178  BLI_assert(chunk < mblk->chunk_len);
179  int elem_per_chunk = mblk->chunk_size / mblk->elem_size;
180  chunk += elem / elem_per_chunk;
181  elem = elem % elem_per_chunk;
182  return (char *)(mblk->chunk_list[chunk]) + mblk->elem_size * elem;
183 }
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define CHUNK_LIST_SIZE
Definition: BLI_memblock.c:24
void BLI_memblock_clear(BLI_memblock *mblk, MemblockValFreeFP free_callback)
Definition: BLI_memblock.c:86
BLI_memblock * BLI_memblock_create_ex(uint elem_size, uint chunk_size)
Definition: BLI_memblock.c:47
void * BLI_memblock_iterstep(BLI_memblock_iter *iter)
Definition: BLI_memblock.c:157
void BLI_memblock_iternew(BLI_memblock *mblk, BLI_memblock_iter *iter)
Definition: BLI_memblock.c:145
void * BLI_memblock_elem_get(BLI_memblock *mblk, int chunk, int elem)
Definition: BLI_memblock.c:176
void * BLI_memblock_alloc(BLI_memblock *mblk)
Definition: BLI_memblock.c:115
void BLI_memblock_destroy(BLI_memblock *mblk, MemblockValFreeFP free_callback)
Definition: BLI_memblock.c:66
void(* MemblockValFreeFP)(void *val)
Definition: BLI_memblock.h:21
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNLIKELY(x)
Read Guarded memory(de)allocation.
#define MEM_recallocN(vmemh, len)
#define MEM_SAFE_FREE(v)
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_mallocN_aligned)(size_t len, size_t alignment, const char *str)
Definition: mallocn.c:35
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
static const int chunk_size
void ** chunk_list
Definition: BLI_memblock.c:27
PointerRNA * ptr
Definition: wm_files.c:3480