History

reworked mempool to use a linked list of free space and headers at the start of allocated regions

Matthew Wang committed 7 years ago

Commit 1fdec381 parent 4f70bc68 files · +220 −145Browse files

Unified · Split

8 files
  1. .DS_Store +0 −0
  2. LEAF/Inc/leaf-math.h +14 −0
  3. LEAF/Inc/leaf-mempool.h +10 −10
  4. LEAF/Src/leaf-effects.c +3 −1
  5. LEAF/Src/leaf-envelopes.c +0 −61
  6. LEAF/Src/leaf-math.c +57 −0
  7. LEAF/Src/leaf-mempool.c +130 −67
  8. LEAF_JUCEPlugin/Source/MyTest.cpp +7 −7
.DS_Store+0−0

Binary file not shown.

LEAF/Inc/leaf-math.h+14−0
@@ -128,6 +128,20 @@ int fastabs_int(int in); · 127 unmodified lines
128128 // alternative implementation for abs()
129129 // REQUIRES: 32 bit floats
130130 float fastabs(float f);
131+
132+#define LOGTEN 2.302585092994
133+
134+float mtof(float f);
135+
136+float ftom(float f);
137+
138+float powtodb(float f);
139+
140+float rmstodb(float f);
141+
142+float dbtopow(float f);
143+
144+float dbtorms(float f);
131145
132146 //==============================================================================
133147
LEAF/Inc/leaf-mempool.h+10−10
@@ -57,19 +57,20 @@ extern "C" { · 56 unmodified lines
5757 /**
5858 * memory pool structure
5959 */
60−typedef struct mpool_pool_t {
60+
61+// node of free list
62+typedef struct mpool_node_t {
6163 void *pool; // memory pool field
62− struct mpool_pool_t *next; // next memory pool's pointer
64+ struct mpool_node_t *next; // next node pointer
65+ struct mpool_node_t *prev; // prev node pointer
6366 size_t size;
64− int used; // used flag
65−} mpool_pool_t;
67+} mpool_node_t;
6668
6769 typedef struct mpool_t {
68− mpool_pool_t *head; // memory pool's head
69− size_t usize; // used pool size of current pool
70− size_t msize; // max pool size of current pool
71− mpool_pool_t *mpool; // memory pool
72− int next;
70+ void* mpool; // start of the mpool
71+ size_t usize; // used size of the pool
72+ size_t msize; // max size of the pool
73+ mpool_node_t* head; // first node of memory pool free list
7374 } mpool_t;
7475
7576 void mpool_create (char* memory, size_t size, mpool_t* pool);
@@ -80,7 +81,6 @@ void mpool_free(void* ptr, mpool_t* pool); · 4 unmodified lines
8081 size_t mpool_get_size(mpool_t* pool);
8182 size_t mpool_get_used(mpool_t* pool);
8283
83−
8484 void leaf_pool_init(char* memory, size_t size);
8585
8686 void* leaf_alloc(size_t size);
LEAF/Src/leaf-effects.c+3−1
@@ -779,7 +779,9 @@ float tPitchShift_shiftToFreq (tPitchShift* ps, float freq) · 778 unmodified lines
779779
780780 tSOLAD_setPeriod(&ps->sola, period);
781781
782− ps->pitchFactor = period*freq*leaf.invSampleRate;
782+ if (period != 0) ps->pitchFactor = period*freq*leaf.invSampleRate;
783+ else ps->pitchFactor = 1.0f;
784+
783785 tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
784786
785787 tSOLAD_ioSamples(&ps->sola, &(ps->p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
LEAF/Src/leaf-envelopes.c+0−61
@@ -23,67 +23,6 @@ · 22 unmodified lines
2323
2424 #endif
2525
26−#define LOGTEN 2.302585092994
27−
28−float mtof(float f)
29−{
30− if (f <= -1500.0f) return(0);
31− else if (f > 1499.0f) return(mtof(1499.0f));
32− else return (8.17579891564f * expf(0.0577622650f * f));
33−}
34−
35−float ftom(float f)
36−{
37− return (f > 0 ? 17.3123405046f * logf(.12231220585f * f) : -1500.0f);
38−}
39−
40−float powtodb(float f)
41−{
42− if (f <= 0) return (0);
43− else
44− {
45− float val = 100 + 10.f/LOGTEN * logf(f);
46− return (val < 0 ? 0 : val);
47− }
48−}
49−
50−float rmstodb(float f)
51−{
52− if (f <= 0) return (0);
53− else
54− {
55− float val = 100 + 20.f/LOGTEN * log(f);
56− return (val < 0 ? 0 : val);
57− }
58−}
59−
60−float dbtopow(float f)
61−{
62− if (f <= 0)
63− return(0);
64− else
65− {
66− if (f > 870.0f)
67− f = 870.0f;
68− return (expf((LOGTEN * 0.1f) * (f-100.0f)));
69− }
70−}
71−
72−float dbtorms(float f)
73−{
74− if (f <= 0)
75− return(0);
76− else
77− {
78− if (f > 485.0f)
79− f = 485.0f;
80− }
81− return (expf((LOGTEN * 0.05f) * (f-100.0f)));
82−}
83−
84−
85−
86−
8726 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Envelope ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
8827 void tEnvelope_init(tEnvelope* const env, float attack, float decay, oBool loop)
8928 {
LEAF/Src/leaf-math.c+57−0
@@ -356,4 +356,61 @@ float LEAF_interpolation_linear (float A, float B, float alpha) · 355 unmodified lines
356356 return out;
357357 }
358358
359+#define LOGTEN 2.302585092994
360+
361+float mtof(float f)
362+{
363+ if (f <= -1500.0f) return(0);
364+ else if (f > 1499.0f) return(mtof(1499.0f));
365+ else return (8.17579891564f * expf(0.0577622650f * f));
366+}
367+
368+float ftom(float f)
369+{
370+ return (f > 0 ? 17.3123405046f * logf(.12231220585f * f) : -1500.0f);
371+}
372+
373+float powtodb(float f)
374+{
375+ if (f <= 0) return (0);
376+ else
377+ {
378+ float val = 100 + 10.f/LOGTEN * logf(f);
379+ return (val < 0 ? 0 : val);
380+ }
381+}
382+
383+float rmstodb(float f)
384+{
385+ if (f <= 0) return (0);
386+ else
387+ {
388+ float val = 100 + 20.f/LOGTEN * log(f);
389+ return (val < 0 ? 0 : val);
390+ }
391+}
392+
393+float dbtopow(float f)
394+{
395+ if (f <= 0)
396+ return(0);
397+ else
398+ {
399+ if (f > 870.0f)
400+ f = 870.0f;
401+ return (expf((LOGTEN * 0.1f) * (f-100.0f)));
402+ }
403+}
404+
405+float dbtorms(float f)
406+{
407+ if (f <= 0)
408+ return(0);
409+ else
410+ {
411+ if (f > 485.0f)
412+ f = 485.0f;
413+ }
414+ return (expf((LOGTEN * 0.05f) * (f-100.0f)));
415+}
359416
LEAF/Src/leaf-mempool.c+130−67
@@ -48,33 +48,30 @@ · 47 unmodified lines
4848
4949 #endif
5050
51−// This might be too low.
52−#define NUM_BLOCKS 50
53−
54−mpool_pool_t blocks[NUM_BLOCKS];
5551 mpool_t leaf_pool;
52+size_t header_size;
5653
5754 /**
5855 * private function
5956 */
6057 static inline size_t mpool_align(size_t size);
61−
58+static inline mpool_node_t* create_node(void* block_location, mpool_node_t* next, mpool_node_t* prev, size_t size);
59+static inline void delink_node(mpool_node_t* node);
6260
6361 /**
6462 * create memory pool
6563 */
6664 void mpool_create (char* memory, size_t size, mpool_t* pool)
6765 {
68− pool->mpool = &blocks[0];
69−
70− pool->mpool->pool = (void*)memory;
71− pool->mpool->size = size;
72− pool->mpool->used = 0;
66+ header_size = mpool_align(sizeof(mpool_node_t));
7367
68+ pool->mpool = (void*)memory;
7469 pool->usize = 0;
7570 pool->msize = size;
7671
77− for (int i = 0; i < size; i++) memory[i]=0;
72+ pool->head = create_node(pool->mpool, NULL, NULL, pool->msize-header_size);
73+
74+ for (int i = 0; i < pool->head->size; i++) memory[i+header_size]=0;
7875 }
7976
8077 void leaf_pool_init(char* memory, size_t size)
@@ -85,45 +82,61 @@ void leaf_pool_init(char* memory, size_t size) · 4 unmodified lines
8582 /**
8683 * allocate memory from memory pool
8784 */
88−void* mpool_alloc(size_t size, mpool_t* pool)
85+void* mpool_alloc(size_t asize, mpool_t* pool)
8986 {
90− pool->next += 1;
87+ // If the head is NULL, the mempool is full
88+ if (pool->head == NULL) return NULL;
9189
92− if (pool->next >= NUM_BLOCKS) return NULL;
90+ // Should we alloc the first block large enough or check all blocks and pick the one closest in size?
91+ size_t size_to_alloc = mpool_align(asize);
92+ mpool_node_t* node_to_alloc = pool->head;
9393
94− mpool_pool_t* new_chunk = &blocks[pool->next];
95− new_chunk->size = mpool_align(size);
94+ // Traverse the free list for a large enough block
95+ while (node_to_alloc->size < size_to_alloc)
96+ {
97+ node_to_alloc = node_to_alloc->next;
98+
99+ // If we reach the end of the free list, there
100+ // are no blocks large enough, return NULL
101+ if (node_to_alloc == NULL) return NULL;
102+ }
96103
97− int idx = pool->next - 1;
98− for (mpool_pool_t *old_chunk = &blocks[idx]; idx >= 0; old_chunk = &blocks[--idx])
104+ // Create a new node after the node to be allocated if there is enough space
105+ mpool_node_t* new_node;
106+ size_t leftover = node_to_alloc->size - size_to_alloc;
107+ node_to_alloc->size = size_to_alloc;
108+ if (leftover > header_size)
99109 {
100− if (old_chunk->used == 0)
101− {
102− if (new_chunk->size < old_chunk->size)
103− {
104− // set memory start pointer of this chunk to that of old chunk, mark new chunk used
105− new_chunk->pool = old_chunk->pool;
106− new_chunk->used = 1;
107−
108− // increment memory start pointer of old chunk
109− char* ptr = (char*)old_chunk->pool;
110− ptr += new_chunk->size;
111− old_chunk->pool = (void*)ptr;
112−
113− // decrement size of old chunk by size of new chunk
114− old_chunk->size -= new_chunk->size;
115−
116− // increment used size of whole mempool by size of new chunk
117− pool->usize += new_chunk->size;
118−
119− // return memory pointer of new chunk
120− return new_chunk->pool;
121− }
122− }
110+ long offset = node_to_alloc - (mpool_node_t*) pool->mpool;
111+ offset *= sizeof(mpool_node_t);
112+ offset += header_size + node_to_alloc->size;
113+ new_node = create_node(&pool->mpool[offset],
114+ node_to_alloc->next,
115+ node_to_alloc->prev,
116+ leftover - header_size);
117+ }
118+ else
119+ {
120+ // Add any leftover space to the allocated node to avoid fragmentation
121+ node_to_alloc->size += leftover;
122+
123+ new_node = node_to_alloc->next;
124+ }
125+
126+ // Update the head if we are allocating the first node of the free list
127+ // The head will be NULL if there is no space left
128+ if (pool->head == node_to_alloc)
129+ {
130+ pool->head = new_node;
123131 }
124132
125− // if not enough space anywhere, return NULL
126− return NULL;
133+ // Remove the allocated node from the free list
134+ delink_node(node_to_alloc);
135+
136+ pool->usize += header_size + node_to_alloc->size;
137+
138+ // Return the pool of the allocated node;
139+ return node_to_alloc->pool;
127140 }
128141
129142 void* leaf_alloc(size_t size)
@@ -138,30 +151,50 @@ void* leaf_alloc(size_t size) · 8 unmodified lines
138151
139152 void mpool_free(void* ptr, mpool_t* pool)
140153 {
141− //printf("finding %p\n", ptr);
154+ //if (ptr < pool->mpool || ptr >= pool->mpool + pool->msize)
155+ // Get the node at the freed space
156+ mpool_node_t* freed_node = (mpool_node_t*) (ptr - header_size);
142157
143− int idx = 0;
144− for (mpool_pool_t *block = &blocks[0]; idx < NUM_BLOCKS; block = &blocks[++idx])
158+ pool->usize -= header_size + freed_node->size;
159+
160+ // Check each node in the list against the newly freed one to see if it's adjacent in memory
161+ mpool_node_t* other_node = pool->head;
162+ mpool_node_t* next_node;
163+ while (other_node != NULL)
145164 {
146− if (block->pool == ptr)
165+ next_node = other_node->next;
166+ // Check if a node is directly after the freed node
167+ if ((long) freed_node + (header_size + freed_node->size) == (long) other_node)
147168 {
148− // Mark unused
149− block->used = 0;
150−
151−
152− // Format to all zeros (kinda arbitrary, but possibly handy / needed)
153− char* buff = (char*)block->pool;
154− for (int i = 0; i < block->size; i++)
155− {
156− buff[i] = 0;
157− }
158−
159− // decrement overall pool size
160− pool->usize -= block->size;
161−
162− break;
169+ // Increase freed node's size
170+ freed_node->size += header_size + other_node->size;
171+ // Delink the merged node
172+ delink_node(other_node);
173+ // Attach the merging node to the head
174+ freed_node->next = pool->head;
163175 }
176+ // Check if a node is directly before the freed node
177+ else if ((long) other_node + (header_size + other_node->size) == (long) freed_node)
178+ {
179+ // Increase the merging node's size
180+ other_node->size += header_size + freed_node->size;
181+ // Delink the merging node
182+ delink_node(other_node);
183+ // Attach the merging node to the head
184+ other_node->next = pool->head;
185+ // Nodes are merged
186+ freed_node = other_node;
187+ }
188+
189+ other_node = next_node;
164190 }
191+
192+ // Do this after any merging
193+ pool->head = freed_node;
194+
195+ // Format the freed pool
196+ char* freed_pool = (char*)freed_node->pool;
197+ for (int i = 0; i < freed_node->size; i++) freed_pool[i] = 0;
165198 }
166199
167200 void leaf_free(void* ptr)
@@ -174,14 +207,14 @@ size_t mpool_get_size(mpool_t* pool) · 6 unmodified lines
174207 return pool->msize;
175208 }
176209
177−size_t leaf_pool_get_size(void)
210+size_t mpool_get_used(mpool_t* pool)
178211 {
179− return mpool_get_size(&leaf_pool);
212+ return pool->usize;
180213 }
181214
182−size_t mpool_get_used(mpool_t* pool)
215+size_t leaf_pool_get_size(void)
183216 {
184− return pool->usize;
217+ return mpool_get_size(&leaf_pool);
185218 }
186219
187220 size_t leaf_pool_get_used(void)
@@ -191,7 +224,7 @@ size_t leaf_pool_get_used(void) · 3 unmodified lines
191224
192225 void* leaf_pool_get_pool(void)
193226 {
194− float* buff = (float*)leaf_pool.mpool->pool;
227+ float* buff = (float*)leaf_pool.mpool;
195228
196229 return buff;
197230 }
@@ -203,6 +236,36 @@ static inline size_t mpool_align(size_t size) { · 5 unmodified lines
203236 return (size + (MPOOL_ALIGN_SIZE - 1)) & ~(MPOOL_ALIGN_SIZE - 1);
204237 }
205238
239+static inline mpool_node_t* create_node(void* block_location, mpool_node_t* next, mpool_node_t* prev, size_t size)
240+{
241+ mpool_node_t* node = (mpool_node_t*)block_location;
242+ node->pool = block_location + header_size;
243+ node->next = next;
244+ node->prev = prev;
245+ node->size = size;
246+
247+ return node;
248+}
249+
250+static inline void delink_node(mpool_node_t* node)
251+{
252+ // If there is a node after the node to remove
253+ if (node->next != NULL)
254+ {
255+ // Close the link
256+ node->next->prev = node->prev;
257+ }
258+ // If there is a node before the node to remove
259+ if (node->prev != NULL)
260+ {
261+ // Close the link
262+ node->prev->next = node->next;
263+ }
264+
265+ node->next = NULL;
266+ node->prev = NULL;
267+}
268+
206269 void leaf_mempool_overrun(void)
207270 {
208271
LEAF_JUCEPlugin/Source/MyTest.cpp+7−7
@@ -42,8 +42,8 @@ void LEAFTest_init (float sampleRate, int blockSize) · 41 unmodified lines
4242 tDelay_free(&delay); //most basic free test
4343 tDelay_init(&delay, 44100, 44100);
4444
45− tRetune_init(&retune, 1, 4096, 2048);
46− tAutotune_init(&autotune, 1, 4096, 2048);
45+ tRetune_init(&retune, 1, 2048, 1024);
46+ tAutotune_init(&autotune, 8, 2048, 1024);
4747 }
4848
4949 float LEAFTest_tick (float input)
@@ -53,9 +53,9 @@ float LEAFTest_tick (float input) · 3 unmodified lines
5353 float* autotuneOut = tAutotune_tick(&autotune, sample);
5454 float r1 = retuneOut[0];
5555 //float r2 = retuneOut[1];
56− float a1 = autotuneOut[0];
57− //float a2 = autotuneOut[1];
58− sample = a1;
56+ float a1 = autotuneOut[6];
57+ float a2 = autotuneOut[7];
58+ sample = a1 + a2;
5959
6060 return sample * 0.25f;
6161 }
@@ -67,11 +67,11 @@ void LEAFTest_block (void) · 5 unmodified lines
6767 {
6868 float val = getSliderValue("mod freq");
6969 tRetune_setPitchFactor(&retune, val*4.0f + 0.5f, 0);
70− tAutotune_setFreq(&autotune, val*5000.0f + 50.0f, 0);
70+ tAutotune_setFreq(&autotune, val*5000.0f + 50.0f, 7);
7171
7272 val = getSliderValue("mod depth");
7373 tRetune_setPitchFactor(&retune, val*4.0f + 0.5f, 1);
74− tAutotune_setFreq(&autotune, val*5000.0f + 50.0f, 1);
74+ tAutotune_setFreq(&autotune, val*5000.0f + 50.0f, 6);
7575 }
7676
7777 void LEAFTest_controllerInput (int cnum, float cval)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t