20 #include <winpr/config.h>
22 #include <winpr/crt.h>
23 #include <winpr/wlog.h>
25 #include <winpr/collections.h>
27 #include "../stream.h"
48 static INLINE
void StreamPool_Lock(wStreamPool* pool)
51 if (pool->synchronized)
52 EnterCriticalSection(&pool->lock);
59 static INLINE
void StreamPool_Unlock(wStreamPool* pool)
62 if (pool->synchronized)
63 LeaveCriticalSection(&pool->lock);
66 static BOOL StreamPool_EnsureCapacity(wStreamPool* pool,
size_t count, BOOL usedOrAvailable)
75 cap = (usedOrAvailable) ? &pool->uCapacity : &pool->aCapacity;
76 size = (usedOrAvailable) ? &pool->uSize : &pool->aSize;
77 array = (usedOrAvailable) ? &pool->uArray : &pool->aArray;
79 new_cap = *size + count;
80 else if (*size + count > *cap)
82 else if ((*size + count) < *cap / 3)
89 if (*cap < *size + count)
105 static void StreamPool_ShiftUsed(wStreamPool* pool,
size_t index, INT64 count)
110 const size_t pcount = (size_t)count;
111 StreamPool_EnsureCapacity(pool, pcount, TRUE);
113 MoveMemory(&pool->uArray[index + pcount], &pool->uArray[index],
114 (pool->uSize - index) *
sizeof(
wStream*));
115 pool->uSize += pcount;
119 const size_t pcount = (size_t)-count;
120 const size_t off = index + pcount;
121 if (pool->uSize > off)
123 MoveMemory(&pool->uArray[index], &pool->uArray[index + pcount],
124 (pool->uSize - index - pcount) *
sizeof(
wStream*));
127 pool->uSize -= pcount;
135 static void StreamPool_AddUsed(wStreamPool* pool,
wStream* s)
137 StreamPool_EnsureCapacity(pool, 1, TRUE);
138 pool->uArray[(pool->uSize)++] = s;
145 static void StreamPool_RemoveUsed(wStreamPool* pool,
wStream* s)
148 for (
size_t index = 0; index < pool->uSize; index++)
150 if (pool->uArray[index] == s)
152 StreamPool_ShiftUsed(pool, index, -1);
158 static void StreamPool_ShiftAvailable(wStreamPool* pool,
size_t index, INT64 count)
163 const size_t pcount = (size_t)count;
165 StreamPool_EnsureCapacity(pool, pcount, FALSE);
166 MoveMemory(&pool->aArray[index + pcount], &pool->aArray[index],
167 (pool->aSize - index) *
sizeof(
wStream*));
168 pool->aSize += pcount;
172 const size_t pcount = (size_t)-count;
173 const size_t off = index + pcount;
174 if (pool->aSize > off)
176 MoveMemory(&pool->aArray[index], &pool->aArray[index + pcount],
177 (pool->aSize - index - pcount) *
sizeof(
wStream*));
180 pool->aSize -= pcount;
188 wStream* StreamPool_Take(wStreamPool* pool,
size_t size)
191 size_t foundIndex = 0;
194 StreamPool_Lock(pool);
197 size = pool->defaultSize;
199 for (
size_t index = 0; index < pool->aSize; index++)
201 s = pool->aArray[index];
203 if (Stream_Capacity(s) >= size)
213 s = Stream_New(NULL, size);
219 Stream_SetPosition(s, 0);
220 Stream_SetLength(s, Stream_Capacity(s));
221 StreamPool_ShiftAvailable(pool, foundIndex, -1);
228 StreamPool_AddUsed(pool, s);
232 StreamPool_Unlock(pool);
241 static void StreamPool_Remove(wStreamPool* pool,
wStream* s)
243 StreamPool_EnsureCapacity(pool, 1, FALSE);
244 Stream_EnsureValidity(s);
245 for (
size_t x = 0; x < pool->aSize; x++)
251 pool->aArray[(pool->aSize)++] = s;
252 StreamPool_RemoveUsed(pool, s);
255 static void StreamPool_ReleaseOrReturn(wStreamPool* pool,
wStream* s)
257 StreamPool_Lock(pool);
261 StreamPool_Remove(pool, s);
262 StreamPool_Unlock(pool);
265 void StreamPool_Return(wStreamPool* pool,
wStream* s)
271 StreamPool_Lock(pool);
272 StreamPool_Remove(pool, s);
273 StreamPool_Unlock(pool);
285 StreamPool_Lock(s->pool);
287 StreamPool_Unlock(s->pool);
295 void Stream_Release(
wStream* s)
299 StreamPool_ReleaseOrReturn(s->pool, s);
306 wStream* StreamPool_Find(wStreamPool* pool,
const BYTE* ptr)
310 StreamPool_Lock(pool);
312 for (
size_t index = 0; index < pool->uSize; index++)
314 wStream* cur = pool->uArray[index];
316 if ((ptr >= Stream_Buffer(cur)) && (ptr < (Stream_Buffer(cur) + Stream_Capacity(cur))))
323 StreamPool_Unlock(pool);
332 void StreamPool_Clear(wStreamPool* pool)
334 StreamPool_Lock(pool);
336 while (pool->aSize > 0)
338 wStream* s = pool->aArray[--pool->aSize];
339 Stream_Free(s, s->isAllocatedStream);
342 while (pool->uSize > 0)
344 wStream* s = pool->uArray[--pool->uSize];
345 Stream_Free(s, s->isAllocatedStream);
348 StreamPool_Unlock(pool);
355 wStreamPool* StreamPool_New(BOOL
synchronized,
size_t defaultSize)
357 wStreamPool* pool = NULL;
359 pool = (wStreamPool*)calloc(1,
sizeof(wStreamPool));
363 pool->synchronized =
synchronized;
364 pool->defaultSize = defaultSize;
366 if (!StreamPool_EnsureCapacity(pool, 32, FALSE))
368 if (!StreamPool_EnsureCapacity(pool, 32, TRUE))
371 InitializeCriticalSectionAndSpinCount(&pool->lock, 4000);
376 WINPR_PRAGMA_DIAG_PUSH
377 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
378 StreamPool_Free(pool);
379 WINPR_PRAGMA_DIAG_POP
383 void StreamPool_Free(wStreamPool* pool)
387 StreamPool_Clear(pool);
389 DeleteCriticalSection(&pool->lock);
398 char* StreamPool_GetStatistics(wStreamPool* pool,
char* buffer,
size_t size)
402 if (!buffer || (size < 1))
404 (void)_snprintf(buffer, size - 1,
405 "aSize =%" PRIuz
", uSize =%" PRIuz
"aCapacity=%" PRIuz
406 ", uCapacity=%" PRIuz,
407 pool->aSize, pool->uSize, pool->aCapacity, pool->uCapacity);
408 buffer[size - 1] =
'\0';