Blame winpr/libwinpr/utils/collections/ObjectPool.c

Packit Service fa4841
/**
Packit Service fa4841
 * WinPR: Windows Portable Runtime
Packit Service fa4841
 * Object Pool
Packit Service fa4841
 *
Packit Service fa4841
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit Service fa4841
 *
Packit Service fa4841
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit Service fa4841
 * you may not use this file except in compliance with the License.
Packit Service fa4841
 * You may obtain a copy of the License at
Packit Service fa4841
 *
Packit Service fa4841
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit Service fa4841
 *
Packit Service fa4841
 * Unless required by applicable law or agreed to in writing, software
Packit Service fa4841
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit Service fa4841
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit Service fa4841
 * See the License for the specific language governing permissions and
Packit Service fa4841
 * limitations under the License.
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
#ifdef HAVE_CONFIG_H
Packit Service fa4841
#include "config.h"
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
#include <winpr/crt.h>
Packit Service fa4841
Packit Service fa4841
#include <winpr/collections.h>
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * C Object Pool similar to C# BufferManager Class:
Packit Service fa4841
 * http://msdn.microsoft.com/en-us/library/ms405814.aspx
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Methods
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Gets an object from the pool.
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
void* ObjectPool_Take(wObjectPool* pool)
Packit Service fa4841
{
Packit Service fa4841
	void* obj = NULL;
Packit Service fa4841
Packit Service fa4841
	if (pool->synchronized)
Packit Service fa4841
		EnterCriticalSection(&pool->lock);
Packit Service fa4841
Packit Service fa4841
	if (pool->size > 0)
Packit Service fa4841
		obj = pool->array[--(pool->size)];
Packit Service fa4841
Packit Service fa4841
	if (!obj)
Packit Service fa4841
	{
Packit Service fa4841
		if (pool->object.fnObjectNew)
Packit Service fa4841
			obj = pool->object.fnObjectNew(NULL);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (pool->object.fnObjectInit)
Packit Service fa4841
		pool->object.fnObjectInit(obj);
Packit Service fa4841
Packit Service fa4841
	if (pool->synchronized)
Packit Service fa4841
		LeaveCriticalSection(&pool->lock);
Packit Service fa4841
Packit Service fa4841
	return obj;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Returns an object to the pool.
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
void ObjectPool_Return(wObjectPool* pool, void* obj)
Packit Service fa4841
{
Packit Service fa4841
	if (pool->synchronized)
Packit Service fa4841
		EnterCriticalSection(&pool->lock);
Packit Service fa4841
Packit Service fa4841
	if ((pool->size + 1) >= pool->capacity)
Packit Service fa4841
	{
Packit Service bb5c11
		int new_cap;
Packit Service bb5c11
		void **new_arr;
Packit Service fa4841
Packit Service fa4841
		new_cap = pool->capacity * 2;
Packit Service bb5c11
		new_arr = (void**) realloc(pool->array, sizeof(void*) * new_cap);
Packit Service fa4841
		if (!new_arr)
Packit Service bb5c11
			return;
Packit Service fa4841
		pool->array = new_arr;
Packit Service fa4841
		pool->capacity = new_cap;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	pool->array[(pool->size)++] = obj;
Packit Service fa4841
Packit Service fa4841
	if (pool->object.fnObjectUninit)
Packit Service fa4841
		pool->object.fnObjectUninit(obj);
Packit Service fa4841
Packit Service fa4841
	if (pool->synchronized)
Packit Service fa4841
		LeaveCriticalSection(&pool->lock);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Releases the buffers currently cached in the pool.
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
void ObjectPool_Clear(wObjectPool* pool)
Packit Service fa4841
{
Packit Service fa4841
	if (pool->synchronized)
Packit Service fa4841
		EnterCriticalSection(&pool->lock);
Packit Service fa4841
Packit Service fa4841
	while (pool->size > 0)
Packit Service fa4841
	{
Packit Service fa4841
		(pool->size)--;
Packit Service fa4841
Packit Service fa4841
		if (pool->object.fnObjectFree)
Packit Service fa4841
			pool->object.fnObjectFree(pool->array[pool->size]);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (pool->synchronized)
Packit Service fa4841
		LeaveCriticalSection(&pool->lock);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Construction, Destruction
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
wObjectPool* ObjectPool_New(BOOL synchronized)
Packit Service fa4841
{
Packit Service fa4841
	wObjectPool* pool = NULL;
Packit Service fa4841
Packit Service bb5c11
	pool = (wObjectPool*) calloc(1, sizeof(wObjectPool));
Packit Service fa4841
Packit Service fa4841
	if (pool)
Packit Service fa4841
	{
Packit Service fa4841
		pool->capacity = 32;
Packit Service fa4841
		pool->size = 0;
Packit Service bb5c11
		pool->array = (void**) calloc(pool->capacity, sizeof(void*));
Packit Service fa4841
		if (!pool->array)
Packit Service fa4841
		{
Packit Service fa4841
			free(pool);
Packit Service fa4841
			return NULL;
Packit Service fa4841
		}
Packit Service fa4841
		pool->synchronized = synchronized;
Packit Service fa4841
Packit Service fa4841
		if (pool->synchronized)
Packit Service fa4841
			InitializeCriticalSectionAndSpinCount(&pool->lock, 4000);
Packit Service bb5c11
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return pool;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
void ObjectPool_Free(wObjectPool* pool)
Packit Service fa4841
{
Packit Service fa4841
	if (pool)
Packit Service fa4841
	{
Packit Service fa4841
		ObjectPool_Clear(pool);
Packit Service fa4841
Packit Service fa4841
		if (pool->synchronized)
Packit Service fa4841
			DeleteCriticalSection(&pool->lock);
Packit Service fa4841
Packit Service fa4841
		free(pool->array);
Packit Service fa4841
Packit Service fa4841
		free(pool);
Packit Service fa4841
	}
Packit Service fa4841
}