From f5d9b06252632713c064b5be71aa888d14d7d2c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 22 Jan 2013 20:36:08 -0500 Subject: [PATCH] libwinpr-utils: added buffer pool --- libfreerdp/codec/rfx.c | 11 +- winpr/include/winpr/collections.h | 21 +++ winpr/libwinpr/utils/CMakeLists.txt | 3 +- winpr/libwinpr/utils/collections/BufferPool.c | 165 ++++++++++++++++++ 4 files changed, 195 insertions(+), 5 deletions(-) create mode 100644 winpr/libwinpr/utils/collections/BufferPool.c diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index efbd2def3..00d239514 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -163,10 +163,13 @@ RFX_CONTEXT* rfx_context_new(void) rfx_context_set_pixel_format(context, RDP_PIXEL_FORMAT_B8G8R8A8); /* align buffers to 16 byte boundary (needed for SSE/SSE2 instructions) */ - context->priv->y_r_buffer = _aligned_malloc(4096 * 4, 16); /* 4096 = 64x64 */ - context->priv->cb_g_buffer = _aligned_malloc(4096 * 4, 16); /* 4096 = 64x64 */ - context->priv->cr_b_buffer = _aligned_malloc(4096 * 4, 16); /* 4096 = 64x64 */ - context->priv->dwt_buffer = _aligned_malloc(32 * 32 * 4 * 2 * 2, 16); /* maximum sub-band width is 32 */ + + context->priv->y_r_buffer = _aligned_malloc(16384, 16); /* 64 * 64 * 4 = 16384 (0x4000) */ + context->priv->cb_g_buffer = _aligned_malloc(16384, 16); /* 64 * 64 * 4 = 16384 (0x4000) */ + context->priv->cr_b_buffer = _aligned_malloc(16384, 16); /* 64 * 64 * 4 = 16384 (0x4000) */ + + /* maximum sub-band width is 32 */ + context->priv->dwt_buffer = _aligned_malloc(16384, 16); /* 32 * 32 * 2 * 2 * 4 = 16384 (0x4000) */ /* create profilers for default decoding routines */ rfx_profiler_create(context); diff --git a/winpr/include/winpr/collections.h b/winpr/include/winpr/collections.h index 1ba6cf7af..adf00378b 100644 --- a/winpr/include/winpr/collections.h +++ b/winpr/include/winpr/collections.h @@ -225,4 +225,25 @@ WINPR_API void CountdownEvent_Reset(wCountdownEvent* countdown, DWORD count); WINPR_API wCountdownEvent* CountdownEvent_New(DWORD initialCount); WINPR_API void CountdownEvent_Free(wCountdownEvent* countdown); +/* BufferPool */ + +struct _wBufferPool +{ + int size; + int capacity; + void** array; + HANDLE mutex; + int fixedSize; + DWORD alignment; + BOOL synchronized; +}; +typedef struct _wBufferPool wBufferPool; + +void* BufferPool_Take(wBufferPool* pool, int bufferSize); +void BufferPool_Return(wBufferPool* pool, void* buffer); +void BufferPool_Clear(wBufferPool* pool); + +wBufferPool* BufferPool_New(BOOL synchronized, int fixedSize, DWORD alignment); +void BufferPool_Free(wBufferPool* pool); + #endif /* WINPR_COLLECTIONS_H */ diff --git a/winpr/libwinpr/utils/CMakeLists.txt b/winpr/libwinpr/utils/CMakeLists.txt index 890673a18..67735fa71 100644 --- a/winpr/libwinpr/utils/CMakeLists.txt +++ b/winpr/libwinpr/utils/CMakeLists.txt @@ -26,7 +26,8 @@ set(${MODULE_PREFIX}_COLLECTIONS_SRCS collections/Dictionary.c collections/ListDictionary.c collections/KeyValuePair.c - collections/CountdownEvent.c) + collections/CountdownEvent.c + collections/BufferPool.c) set(${MODULE_PREFIX}_SRCS sam.c diff --git a/winpr/libwinpr/utils/collections/BufferPool.c b/winpr/libwinpr/utils/collections/BufferPool.c new file mode 100644 index 000000000..348e231b1 --- /dev/null +++ b/winpr/libwinpr/utils/collections/BufferPool.c @@ -0,0 +1,165 @@ +/** + * WinPR: Windows Portable Runtime + * Buffer Pool + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +/** + * C equivalent of the C# BufferManager Class: + * http://msdn.microsoft.com/en-us/library/ms405814.aspx + */ + +/** + * Methods + */ + +/** + * Gets a buffer of at least the specified size from the pool. + */ + +void* BufferPool_Take(wBufferPool* pool, int bufferSize) +{ + void* buffer = NULL; + + if (pool->synchronized) + WaitForSingleObject(pool->mutex, INFINITE); + + if (pool->fixedSize) + { + if (pool->size > 0) + buffer = pool->array[--(pool->size)]; + + if (!buffer) + { + if (pool->alignment) + buffer = _aligned_malloc(pool->fixedSize, pool->alignment); + else + buffer = malloc(pool->fixedSize); + } + } + else + { + printf("Variable-size BufferPool not yet implemented\n"); + } + + if (pool->synchronized) + ReleaseMutex(pool->mutex); + + return buffer; +} + +/** + * Returns a buffer to the pool. + */ + +void BufferPool_Return(wBufferPool* pool, void* buffer) +{ + if (pool->synchronized) + WaitForSingleObject(pool->mutex, INFINITE); + + if ((pool->size + 1) >= pool->capacity) + { + pool->capacity *= 2; + pool->array = (void**) realloc(pool->array, sizeof(void*) * pool->capacity); + } + + pool->array[(pool->size)++] = buffer; + + if (pool->synchronized) + ReleaseMutex(pool->mutex); +} + +/** + * Releases the buffers currently cached in the pool. + */ + +void BufferPool_Clear(wBufferPool* pool) +{ + if (pool->synchronized) + WaitForSingleObject(pool->mutex, INFINITE); + + while (pool->size > 0) + { + (pool->size)--; + + if (pool->alignment) + _aligned_free(pool->array[pool->size]); + else + free(pool->array[pool->size]); + } + + if (pool->synchronized) + ReleaseMutex(pool->mutex); +} + +/** + * Construction, Destruction + */ + +wBufferPool* BufferPool_New(BOOL synchronized, int fixedSize, DWORD alignment) +{ + wBufferPool* pool = NULL; + + pool = (wBufferPool*) malloc(sizeof(wBufferPool)); + + if (pool) + { + pool->fixedSize = fixedSize; + + if (pool->fixedSize < 0) + pool->fixedSize = 0; + + pool->alignment = alignment; + pool->synchronized = synchronized; + + if (pool->synchronized) + pool->mutex = CreateMutex(NULL, FALSE, NULL); + + if (!pool->fixedSize) + { + printf("Variable-size BufferPool not yet implemented\n"); + } + + pool->size = 0; + pool->capacity = 32; + pool->array = (void**) malloc(sizeof(void*) * pool->capacity); + } + + return pool; +} + +void BufferPool_Free(wBufferPool* pool) +{ + if (pool) + { + BufferPool_Clear(pool); + + if (pool->synchronized) + CloseHandle(pool->mutex); + + free(pool->array); + + free(pool); + } +}