/** * WinPR: Windows Portable Runtime * Object 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 Object Pool similar to C# BufferManager Class: * http://msdn.microsoft.com/en-us/library/ms405814.aspx */ /** * Methods */ /** * Gets an object from the pool. */ void* ObjectPool_Take(wObjectPool* pool) { void* obj = NULL; if (pool->synchronized) EnterCriticalSection(&pool->lock); if (pool->size > 0) obj = pool->array[--(pool->size)]; if (!obj) { if (pool->object.fnObjectNew) obj = pool->object.fnObjectNew(NULL); } if (pool->object.fnObjectInit) pool->object.fnObjectInit(obj); if (pool->synchronized) LeaveCriticalSection(&pool->lock); return obj; } /** * Returns an object to the pool. */ void ObjectPool_Return(wObjectPool* pool, void* obj) { if (pool->synchronized) EnterCriticalSection(&pool->lock); if ((pool->size + 1) >= pool->capacity) { int new_cap; void **new_arr; new_cap = pool->capacity * 2; new_arr = (void**) realloc(pool->array, sizeof(void*) * new_cap); if (!new_arr) return; pool->array = new_arr; pool->capacity = new_cap; } pool->array[(pool->size)++] = obj; if (pool->object.fnObjectUninit) pool->object.fnObjectUninit(obj); if (pool->synchronized) LeaveCriticalSection(&pool->lock); } /** * Releases the buffers currently cached in the pool. */ void ObjectPool_Clear(wObjectPool* pool) { if (pool->synchronized) EnterCriticalSection(&pool->lock); while (pool->size > 0) { (pool->size)--; if (pool->object.fnObjectFree) pool->object.fnObjectFree(pool->array[pool->size]); } if (pool->synchronized) LeaveCriticalSection(&pool->lock); } /** * Construction, Destruction */ wObjectPool* ObjectPool_New(BOOL synchronized) { wObjectPool* pool = NULL; pool = (wObjectPool*) calloc(1, sizeof(wObjectPool)); if (pool) { pool->capacity = 32; pool->size = 0; pool->array = (void**) calloc(pool->capacity, sizeof(void*)); if (!pool->array) { free(pool); return NULL; } pool->synchronized = synchronized; if (pool->synchronized) InitializeCriticalSectionAndSpinCount(&pool->lock, 4000); } return pool; } void ObjectPool_Free(wObjectPool* pool) { if (pool) { ObjectPool_Clear(pool); if (pool->synchronized) DeleteCriticalSection(&pool->lock); free(pool->array); free(pool); } }