/* Copyright (C) 1999-2007 id Software, Inc. and contributors. For a list of contributors, see the accompanying CONTRIBUTORS file. This file is part of GtkRadiant. GtkRadiant is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GtkRadiant is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // // ResourceManager.c // #include #include "resourcemanager.h" #include typedef struct ResMngr_Block_s { char *start; unsigned int size; struct ResMngr_Block_s *next; } ResMngr_Block_t; static void ResMngr_CreateBlock( ResourceManager_t *resource ){ unsigned int _blockSize; char *block; char **current; ResMngr_Block_t *temp; unsigned int i; _blockSize = resource->nodeSize * resource->resPerBlock; block = malloc( _blockSize ); assert( block ); temp = malloc( sizeof( *temp ) ); temp->start = block; temp->size = _blockSize; temp->next = resource->blockList; resource->blockList = temp; resource->free = (char **)( block ); current = resource->free; for ( i = 1; i < resource->resPerBlock; ++i ) { // set current->next to point to next node *current = (char *)( current ) + resource->nodeSize; // set current node to current->next current = (char **)( *current ); } *current = NULL; } H2COMMON_API void ResMngr_Con( ResourceManager_t *resource, size_t init_resSize, unsigned int init_resPerBlock, char *resman_name ){ resource->resSize = init_resSize; resource->resPerBlock = init_resPerBlock; resource->nodeSize = resource->resSize + sizeof( *resource->free ); resource->blockList = NULL; resource->numResourcesAllocated = 0; ResMngr_CreateBlock( resource ); } H2COMMON_API void ResMngr_Des( ResourceManager_t *resource ){ ResMngr_Block_t *toDelete; #if 0 if ( resource->numResourcesAllocated ) { char mess[100]; sprintf( mess,"Potential memory leak %d bytes unfreed\n",resource->resSize * resource->numResourcesAllocated ); OutputDebugString( mess ); } #endif while ( resource->blockList ) { toDelete = resource->blockList; resource->blockList = resource->blockList->next; free( toDelete->start ); free( toDelete ); } } H2COMMON_API void *ResMngr_AllocateResource( ResourceManager_t *resource, size_t size ){ char **toPop; assert( size == resource->resSize ); ++resource->numResourcesAllocated; assert( resource->free ); // constructor not called; possibly due to a static object // containing a static ResourceManagerFastLarge member being // constructed before its own static members toPop = resource->free; // set unallocated to the next node and check for NULL (end of list) if ( !( resource->free = (char **)( *resource->free ) ) ) { // if at end create new block ResMngr_CreateBlock( resource ); } // set next to NULL *toPop = NULL; // return the resource for the node return (void *)( toPop + 1 ); } H2COMMON_API void ResMngr_DeallocateResource( ResourceManager_t *resource, void *toDeallocate, size_t size ){ char **toPush; assert( size == resource->resSize ); --resource->numResourcesAllocated; toPush = (char **)( toDeallocate ) - 1; assert( resource->free ); // see same assert at top of AllocateResource // set toPop->next to current unallocated front *toPush = (char *)( resource->free ); // set unallocated to the node removed from allocated resource->free = toPush; } // end