@@ -101,7 +101,7 @@ pl_freelist_get_node(plFreeList* ptFreeList, uint64_t uSize)
101101
102102 // find best block
103103 uint64_t szSmallestDiff = ~(uint64_t )0 ;
104- plFreeListNode * ptCurrentBlock = & ptFreeList -> _tFreeList ;
104+ plFreeListNode * ptCurrentBlock = ptFreeList -> _tFreeList . _ptNext ;
105105 while (ptCurrentBlock )
106106 {
107107
@@ -151,96 +151,75 @@ pl_freelist_return_node(plFreeList* ptFreeList, plFreeListNode* ptNode)
151151{
152152 ptFreeList -> uUsedSpace -= ptNode -> uSize ;
153153
154- // if the free list is not empty
155- if (ptFreeList -> _tFreeList ._ptNext != NULL )
154+
155+ // If free list is empty, add as first node
156+ if (ptFreeList -> _tFreeList ._ptNext == NULL )
156157 {
157- // Add node to free list
158- plFreeListNode * ptFreeBlock = ptFreeList -> _tFreeList ._ptNext ;
159- while (ptFreeBlock )
160- {
161- // Insert new node to middle
162- if (ptFreeBlock > ptNode )
163- {
164- plFreeListNode * _ptNext = ptFreeBlock ;
165- plFreeListNode * _ptPrev = ptFreeBlock -> _ptPrev ;
166-
167- _ptNext -> _ptPrev = ptNode ;
168- ptNode -> _ptNext = _ptNext ;
169- ptNode -> _ptPrev = _ptPrev ;
170- _ptPrev -> _ptNext = ptNode ;
171- break ;
172-
173- }
158+ ptNode -> _ptPrev = & ptFreeList -> _tFreeList ;
159+ ptNode -> _ptNext = NULL ;
160+ ptFreeList -> _tFreeList ._ptNext = ptNode ;
161+ return ;
162+ }
174163
175- // There isn't a next block so Insert new node to the end
176- if (ptFreeBlock -> _ptNext == NULL )
177- {
178- ptNode -> _ptNext = NULL ;
179- ptNode -> _ptPrev = ptFreeBlock ;
180- ptFreeBlock -> _ptNext = ptNode ;
181- break ;
182- }
164+ // 1) Insert by uOffset order (not by pointer!)
165+ plFreeListNode * it = ptFreeList -> _tFreeList ._ptNext ;
166+ plFreeListNode * insert_after = & ptFreeList -> _tFreeList ;
183167
184- ptFreeBlock = ptFreeBlock -> _ptNext ;
185- }
168+ while (it && it -> uOffset < ptNode -> uOffset )
169+ {
170+ insert_after = it ;
171+ it = it -> _ptNext ;
172+ }
186173
187- // Defrag
188- plFreeListNode * _ptPrevBlock = ptNode -> _ptPrev ;
189- plFreeListNode * _ptNextBlock = ptNode -> _ptNext ;
174+ ptNode -> _ptPrev = insert_after ;
175+ ptNode -> _ptNext = it ;
176+ insert_after -> _ptNext = ptNode ;
177+ if (it ) it -> _ptPrev = ptNode ;
190178
191- if (_ptPrevBlock != & ptFreeList -> _tFreeList )
179+ // 2) Coalesce with previous if adjacent
180+ if (ptNode -> _ptPrev != & ptFreeList -> _tFreeList )
181+ {
182+ plFreeListNode * prev = ptNode -> _ptPrev ;
183+ if (prev -> uOffset + prev -> uSize == ptNode -> uOffset )
192184 {
193- // if prev block and block are adjacent
194- if ((_ptPrevBlock -> uOffset + _ptPrevBlock -> uSize ) == ptNode -> uOffset )
195- {
196- _ptPrevBlock -> uSize += ptNode -> uSize ;
197- pl_sb_push (ptFreeList -> _sbuFreeNodeHoleSlot , ptNode -> _uIndex );
198-
199- // delete node
200- if (_ptNextBlock != NULL ) {_ptNextBlock -> _ptPrev = _ptPrevBlock ; }
201- _ptPrevBlock -> _ptNext = _ptNextBlock ;
202- ptNode -> _ptNext = NULL ;
203- ptNode -> _ptPrev = NULL ;
204- ptNode -> uOffset = 0 ;
205- ptNode -> uSize = 0 ;
206-
207- // Allows us to defrag with the next block without checking if we defragged with this one
208- ptNode = _ptPrevBlock ;
209- }
210- }
185+ prev -> uSize += ptNode -> uSize ;
211186
212- if ( _ptNextBlock != NULL )
213- {
187+ // Recycle this node descriptor
188+ pl_sb_push ( ptFreeList -> _sbuFreeNodeHoleSlot , ptNode -> _uIndex );
214189
215- plFreeListNode * _ptNextNextBlock = _ptNextBlock -> _ptNext ;
190+ // Remove ptNode from the list
191+ if (ptNode -> _ptNext ) ptNode -> _ptNext -> _ptPrev = prev ;
192+ prev -> _ptNext = ptNode -> _ptNext ;
216193
217- // if block and next block are adjacent
218- if ((ptNode -> uOffset + ptNode -> uSize ) == _ptNextBlock -> uOffset )
219- {
220- ptNode -> uSize += _ptNextBlock -> uSize ;
221- pl_sb_push (ptFreeList -> _sbuFreeNodeHoleSlot , _ptNextBlock -> _uIndex );
222-
223- // delete next node
224- if (_ptNextNextBlock != NULL )
225- {
226- _ptNextNextBlock -> _ptPrev = ptNode ;
227- }
228- ptNode -> _ptNext = _ptNextNextBlock ;
229- _ptNextBlock -> _ptNext = NULL ;
230- _ptNextBlock -> _ptPrev = NULL ;
231- _ptNextBlock -> uOffset = 0 ;
232- _ptNextBlock -> uSize = 0 ;
194+ // Clean up metadata
195+ ptNode -> _ptPrev = ptNode -> _ptNext = NULL ;
196+ ptNode -> uOffset = 0 ;
197+ ptNode -> uSize = 0 ;
233198
234- }
199+ // Continue coalescing using the merged 'prev' block
200+ ptNode = prev ;
235201 }
236202 }
237- else
203+
204+ // 3) Coalesce forward as long as next is adjacent
205+ while (ptNode -> _ptNext &&
206+ (ptNode -> uOffset + ptNode -> uSize ) == ptNode -> _ptNext -> uOffset )
238207 {
239- // Add node to the front of the free list if list is empty
240- ptNode -> _ptNext = NULL ;
241- ptNode -> _ptPrev = & ptFreeList -> _tFreeList ;
242- ptFreeList -> _tFreeList ._ptNext = ptNode ;
208+ plFreeListNode * next = ptNode -> _ptNext ;
209+ plFreeListNode * nn = next -> _ptNext ;
210+
211+ ptNode -> uSize += next -> uSize ;
212+ pl_sb_push (ptFreeList -> _sbuFreeNodeHoleSlot , next -> _uIndex );
213+
214+ // unlink next
215+ ptNode -> _ptNext = nn ;
216+ if (nn ) nn -> _ptPrev = ptNode ;
217+
218+ next -> _ptPrev = next -> _ptNext = NULL ;
219+ next -> uOffset = 0 ;
220+ next -> uSize = 0 ;
243221 }
222+
244223}
245224
246225//-----------------------------------------------------------------------------
0 commit comments