20 #include <winpr/config.h>
22 #include <winpr/crt.h>
24 #include <winpr/collections.h>
45 wBufferPoolItem* aArray;
49 wBufferPoolItem* uArray;
52 static BOOL BufferPool_Lock(wBufferPool* pool)
57 if (pool->synchronized)
58 EnterCriticalSection(&pool->lock);
62 static BOOL BufferPool_Unlock(wBufferPool* pool)
67 if (pool->synchronized)
68 LeaveCriticalSection(&pool->lock);
81 static BOOL BufferPool_ShiftAvailable(wBufferPool* pool,
size_t index,
int count)
85 if (pool->aSize + count > pool->aCapacity)
87 wBufferPoolItem* newArray = NULL;
88 SSIZE_T newCapacity = pool->aCapacity * 2;
90 if (pool->alignment > 0)
91 newArray = (wBufferPoolItem*)winpr_aligned_realloc(
92 pool->aArray,
sizeof(wBufferPoolItem) * newCapacity, pool->alignment);
95 (wBufferPoolItem*)realloc(pool->aArray,
sizeof(wBufferPoolItem) * newCapacity);
98 pool->aArray = newArray;
99 pool->aCapacity = newCapacity;
102 MoveMemory(&pool->aArray[index + count], &pool->aArray[index],
103 (pool->aSize - index) *
sizeof(wBufferPoolItem));
104 pool->aSize += count;
108 MoveMemory(&pool->aArray[index], &pool->aArray[index - count],
109 (pool->aSize - index) *
sizeof(wBufferPoolItem));
110 pool->aSize += count;
115 static BOOL BufferPool_ShiftUsed(wBufferPool* pool, SSIZE_T index, SSIZE_T count)
119 if (pool->uSize + count > pool->uCapacity)
121 SSIZE_T newUCapacity = pool->uCapacity * 2;
122 wBufferPoolItem* newUArray = NULL;
123 if (pool->alignment > 0)
124 newUArray = (wBufferPoolItem*)winpr_aligned_realloc(
125 pool->uArray,
sizeof(wBufferPoolItem) * newUCapacity, pool->alignment);
128 (wBufferPoolItem*)realloc(pool->uArray,
sizeof(wBufferPoolItem) * newUCapacity);
131 pool->uCapacity = newUCapacity;
132 pool->uArray = newUArray;
135 MoveMemory(&pool->uArray[index + count], &pool->uArray[index],
136 (pool->uSize - index) *
sizeof(wBufferPoolItem));
137 pool->uSize += count;
141 MoveMemory(&pool->uArray[index], &pool->uArray[index - count],
142 (pool->uSize - index) *
sizeof(wBufferPoolItem));
143 pool->uSize += count;
152 SSIZE_T BufferPool_GetPoolSize(wBufferPool* pool)
156 BufferPool_Lock(pool);
169 BufferPool_Unlock(pool);
178 SSIZE_T BufferPool_GetBufferSize(wBufferPool* pool,
const void* buffer)
183 BufferPool_Lock(pool);
188 size = pool->fixedSize;
195 for (SSIZE_T index = 0; index < pool->uSize; index++)
197 if (pool->uArray[index].buffer == buffer)
199 size = pool->uArray[index].size;
206 BufferPool_Unlock(pool);
208 return (found) ? size : -1;
215 void* BufferPool_Take(wBufferPool* pool, SSIZE_T size)
218 SSIZE_T maxIndex = 0;
219 SSIZE_T foundIndex = -1;
223 BufferPool_Lock(pool);
230 buffer = pool->array[--(pool->size)];
235 buffer = winpr_aligned_malloc(pool->fixedSize, pool->alignment);
237 buffer = malloc(pool->fixedSize);
251 size = pool->fixedSize;
253 for (SSIZE_T index = 0; index < pool->aSize; index++)
255 if (pool->aArray[index].size > maxSize)
258 maxSize = pool->aArray[index].size;
261 if (pool->aArray[index].size >= size)
269 if (!found && maxSize)
271 foundIndex = maxIndex;
282 buffer = winpr_aligned_malloc(size, pool->alignment);
284 buffer = malloc(size);
292 buffer = pool->aArray[foundIndex].buffer;
296 void* newBuffer = NULL;
298 newBuffer = winpr_aligned_realloc(buffer, size, pool->alignment);
300 newBuffer = realloc(buffer, size);
303 goto out_error_no_free;
308 if (!BufferPool_ShiftAvailable(pool, foundIndex, -1))
315 if (pool->uSize + 1 > pool->uCapacity)
317 size_t newUCapacity = pool->uCapacity * 2ULL;
318 if (newUCapacity > SSIZE_MAX)
320 wBufferPoolItem* newUArray =
321 (wBufferPoolItem*)realloc(pool->uArray,
sizeof(wBufferPoolItem) * newUCapacity);
325 pool->uCapacity = (SSIZE_T)newUCapacity;
326 pool->uArray = newUArray;
329 pool->uArray[pool->uSize].buffer = buffer;
330 pool->uArray[pool->uSize].size = size;
334 BufferPool_Unlock(pool);
340 winpr_aligned_free(buffer);
344 BufferPool_Unlock(pool);
352 BOOL BufferPool_Return(wBufferPool* pool,
void* buffer)
358 BufferPool_Lock(pool);
364 if ((pool->size + 1) >= pool->capacity)
366 SSIZE_T newCapacity = pool->capacity * 2;
367 void** newArray = (
void**)realloc(pool->array,
sizeof(
void*) * newCapacity);
371 pool->capacity = newCapacity;
372 pool->array = newArray;
375 pool->array[(pool->size)++] = buffer;
382 for (; index < pool->uSize; index++)
384 if (pool->uArray[index].buffer == buffer)
393 size = pool->uArray[index].size;
394 if (!BufferPool_ShiftUsed(pool, index, -1))
400 if ((pool->aSize + 1) >= pool->aCapacity)
402 SSIZE_T newCapacity = pool->aCapacity * 2;
403 wBufferPoolItem* newArray =
404 (wBufferPoolItem*)realloc(pool->aArray,
sizeof(wBufferPoolItem) * newCapacity);
408 pool->aCapacity = newCapacity;
409 pool->aArray = newArray;
412 pool->aArray[pool->aSize].buffer = buffer;
413 pool->aArray[pool->aSize].size = size;
420 BufferPool_Unlock(pool);
428 void BufferPool_Clear(wBufferPool* pool)
430 BufferPool_Lock(pool);
436 while (pool->size > 0)
441 winpr_aligned_free(pool->array[pool->size]);
443 free(pool->array[pool->size]);
450 while (pool->aSize > 0)
455 winpr_aligned_free(pool->aArray[pool->aSize].buffer);
457 free(pool->aArray[pool->aSize].buffer);
460 while (pool->uSize > 0)
465 winpr_aligned_free(pool->uArray[pool->uSize].buffer);
467 free(pool->uArray[pool->uSize].buffer);
471 BufferPool_Unlock(pool);
478 wBufferPool* BufferPool_New(BOOL
synchronized, SSIZE_T fixedSize, DWORD alignment)
480 wBufferPool* pool = NULL;
482 pool = (wBufferPool*)calloc(1,
sizeof(wBufferPool));
486 pool->fixedSize = fixedSize;
488 if (pool->fixedSize < 0)
491 pool->alignment = alignment;
492 pool->synchronized =
synchronized;
494 if (pool->synchronized)
495 InitializeCriticalSectionAndSpinCount(&pool->lock, 4000);
503 pool->array = (
void**)calloc(pool->capacity,
sizeof(
void*));
512 pool->aCapacity = 32;
513 pool->aArray = (wBufferPoolItem*)calloc(pool->aCapacity,
sizeof(wBufferPoolItem));
518 pool->uCapacity = 32;
519 pool->uArray = (wBufferPoolItem*)calloc(pool->uCapacity,
sizeof(wBufferPoolItem));
528 WINPR_PRAGMA_DIAG_PUSH
529 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
530 BufferPool_Free(pool);
531 WINPR_PRAGMA_DIAG_POP
535 void BufferPool_Free(wBufferPool* pool)
539 BufferPool_Clear(pool);
541 if (pool->synchronized)
542 DeleteCriticalSection(&pool->lock);