1 /*
2     SuperCollider real time audio synthesis system
3     Copyright (c) 2002 James McCartney. All rights reserved.
4     http://www.audiosynth.com
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
19 */
20 
21 
22 #include "AdvancingAllocPool.h"
23 #include "SC_AllocPool.h"
24 //#include <assert.h>
25 
26 
AdvancingAllocPool()27 AdvancingAllocPool::AdvancingAllocPool() {
28     mAllocPool = nullptr;
29     mInitSize = 0;
30     mGrowSize = 0;
31     mTooBig = 0;
32     mCurSize = 0;
33     mChunks = nullptr;
34     mFatties = nullptr;
35 }
36 
Init(AllocPool * inAllocPool,size_t initSize,size_t growSize,size_t tooBigSize)37 void AdvancingAllocPool::Init(AllocPool* inAllocPool, size_t initSize, size_t growSize, size_t tooBigSize) {
38     mAllocPool = inAllocPool;
39     mInitSize = initSize;
40     mGrowSize = growSize;
41     mTooBig = tooBigSize;
42     mChunks = nullptr;
43     AddChunk(initSize);
44     mFatties = nullptr;
45     // assert(SanityCheck());
46 }
47 
AddChunk(size_t inSize)48 void AdvancingAllocPool::AddChunk(size_t inSize) {
49     size_t chunkSize = sizeof(AdvancingAllocPoolChunkHdr) + inSize;
50     AdvancingAllocPoolChunk* chunk = (AdvancingAllocPoolChunk*)mAllocPool->Alloc(chunkSize);
51     FailNil(chunk);
52     chunk->mNext = mChunks;
53     mChunks = chunk;
54     chunk->mSize = mGrowSize;
55     mCurSize = 0;
56 }
57 
Alloc(size_t reqsize)58 void* AdvancingAllocPool::Alloc(size_t reqsize) {
59     // assert(SanityCheck());
60     // assert(mAllocPool);
61     size_t size = (reqsize + 15) & ~15; // round up to 16 byte alignment
62     if (size < mTooBig) {
63         if (!mChunks)
64             AddChunk(mInitSize);
65         else if (mCurSize + size > mChunks->mSize)
66             AddChunk(mGrowSize);
67         char* space = mChunks->mSpace + mCurSize;
68         mCurSize += size;
69 
70         // assert(SanityCheck());
71         return (void*)space;
72     } else {
73         size_t chunkSize = sizeof(AdvancingAllocPoolChunkHdr) + size;
74         AdvancingAllocPoolChunk* fatty = (AdvancingAllocPoolChunk*)mAllocPool->Alloc(chunkSize);
75         FailNil(fatty);
76         fatty->mNext = mFatties;
77         mFatties = fatty;
78         fatty->mSize = size;
79 
80         // assert(SanityCheck());
81         return (void*)fatty->mSpace;
82     }
83 }
84 
FreeAll()85 void AdvancingAllocPool::FreeAll() {
86     // assert(SanityCheck());
87     AdvancingAllocPoolChunk *chunk, *next;
88     for (chunk = mChunks; chunk; chunk = next) {
89         next = chunk->mNext;
90         mAllocPool->Free(chunk);
91     }
92     for (chunk = mFatties; chunk; chunk = next) {
93         next = chunk->mNext;
94         mAllocPool->Free(chunk);
95     }
96     mChunks = nullptr;
97     mFatties = nullptr;
98     mCurSize = 0;
99     // assert(SanityCheck());
100 }
101 
SanityCheck()102 bool AdvancingAllocPool::SanityCheck() {
103     AdvancingAllocPoolChunk *chunk, *next;
104     for (chunk = mChunks; chunk; chunk = next) {
105         next = chunk->mNext;
106         mAllocPool->DoCheckInUseChunk(AllocPool::MemToChunk(chunk));
107     }
108     for (chunk = mFatties; chunk; chunk = next) {
109         next = chunk->mNext;
110         mAllocPool->DoCheckInUseChunk(AllocPool::MemToChunk(chunk));
111     }
112     return true;
113 }
114