diff options
author | Miller Puckette <millerpuckette@users.sourceforge.net> | 2004-09-06 21:03:01 +0000 |
---|---|---|
committer | Miller Puckette <millerpuckette@users.sourceforge.net> | 2004-09-06 21:03:01 +0000 |
commit | 43da63a095b3bbcea1009337f1af027a04499266 (patch) | |
tree | 45c32d196d4d21fc55ef792ea2bb19b7d0610f77 /pd/portaudio/pa_common/pa_allocation.c | |
parent | cfc2f7d280ae57ef563dd69bad27c61a148d6ded (diff) |
More files I forgot to add
svn path=/trunk/; revision=2012
Diffstat (limited to 'pd/portaudio/pa_common/pa_allocation.c')
-rw-r--r-- | pd/portaudio/pa_common/pa_allocation.c | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/pd/portaudio/pa_common/pa_allocation.c b/pd/portaudio/pa_common/pa_allocation.c new file mode 100644 index 00000000..8bc7c72f --- /dev/null +++ b/pd/portaudio/pa_common/pa_allocation.c @@ -0,0 +1,224 @@ +/* + * $Id: pa_allocation.c,v 1.1.2.5 2003/09/20 21:04:44 rossbencina Exp $ + * Portable Audio I/O Library allocation group implementation + * memory allocation group for tracking allocation groups + * + * Based on the Open Source API proposed by Ross Bencina + * Copyright (c) 1999-2002 Ross Bencina, Phil Burk + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** @file + @brief Allocation Group implementation. +*/ + + +#include "pa_allocation.h" +#include "pa_util.h" + + +/* + Maintain 3 singly linked lists... + linkBlocks: the buffers used to allocate the links + spareLinks: links available for use in the allocations list + allocations: the buffers currently allocated using PaUtil_ContextAllocateMemory() + + Link block size is doubled every time new links are allocated. +*/ + + +#define PA_INITIAL_LINK_COUNT_ 16 + +struct PaUtilAllocationGroupLink +{ + struct PaUtilAllocationGroupLink *next; + void *buffer; +}; + +/* + Allocate a block of links. The first link will have it's buffer member + pointing to the block, and it's next member set to <nextBlock>. The remaining + links will have NULL buffer members, and each link will point to + the next link except the last, which will point to <nextSpare> +*/ +static struct PaUtilAllocationGroupLink *AllocateLinks( long count, + struct PaUtilAllocationGroupLink *nextBlock, + struct PaUtilAllocationGroupLink *nextSpare ) +{ + struct PaUtilAllocationGroupLink *result; + int i; + + result = (struct PaUtilAllocationGroupLink *)PaUtil_AllocateMemory( + sizeof(struct PaUtilAllocationGroupLink) * count ); + if( result ) + { + /* the block link */ + result[0].buffer = result; + result[0].next = nextBlock; + + /* the spare links */ + for( i=1; i<count; ++i ) + { + result[i].buffer = 0; + result[i].next = &result[i+1]; + } + result[count-1].next = nextSpare; + } + + return result; +} + + +PaUtilAllocationGroup* PaUtil_CreateAllocationGroup( void ) +{ + PaUtilAllocationGroup* result = 0; + struct PaUtilAllocationGroupLink *links; + + + links = AllocateLinks( PA_INITIAL_LINK_COUNT_, 0, 0 ); + if( links != 0 ) + { + result = (PaUtilAllocationGroup*)PaUtil_AllocateMemory( sizeof(PaUtilAllocationGroup) ); + if( result ) + { + result->linkCount = PA_INITIAL_LINK_COUNT_; + result->linkBlocks = &links[0]; + result->spareLinks = &links[1]; + result->allocations = 0; + } + else + { + PaUtil_FreeMemory( links ); + } + } + + return result; +} + + +void PaUtil_DestroyAllocationGroup( PaUtilAllocationGroup* group ) +{ + struct PaUtilAllocationGroupLink *current = group->linkBlocks; + struct PaUtilAllocationGroupLink *next; + + while( current ) + { + next = current->next; + PaUtil_FreeMemory( current->buffer ); + current = next; + } + + PaUtil_FreeMemory( group ); +} + + +void* PaUtil_GroupAllocateMemory( PaUtilAllocationGroup* group, long size ) +{ + struct PaUtilAllocationGroupLink *links, *link; + void *result = 0; + + /* allocate more links if necessary */ + if( !group->spareLinks ) + { + /* double the link count on each block allocation */ + links = AllocateLinks( group->linkCount, group->linkBlocks, group->spareLinks ); + if( links ) + { + group->linkCount += group->linkCount; + group->linkBlocks = &links[0]; + group->spareLinks = &links[1]; + } + } + + if( group->spareLinks ) + { + result = PaUtil_AllocateMemory( size ); + if( result ) + { + link = group->spareLinks; + group->spareLinks = link->next; + + link->buffer = result; + link->next = group->allocations; + + group->allocations = link; + } + } + + return result; +} + + +void PaUtil_GroupFreeMemory( PaUtilAllocationGroup* group, void *buffer ) +{ + struct PaUtilAllocationGroupLink *current = group->allocations; + struct PaUtilAllocationGroupLink *previous = 0; + + if( buffer == 0 ) + return; + + /* find the right link and remove it */ + while( current ) + { + if( current->buffer == buffer ) + { + previous->next = current->next; + + current->buffer = 0; + current->next = group->spareLinks; + group->spareLinks = current; + } + previous = current; + current = current->next; + } + + PaUtil_FreeMemory( buffer ); /* free the memory whether we found it in the list or not */ +} + + +void PaUtil_FreeAllAllocations( PaUtilAllocationGroup* group ) +{ + struct PaUtilAllocationGroupLink *current = group->allocations; + struct PaUtilAllocationGroupLink *previous = 0; + + /* free all buffers in the allocations list */ + while( current ) + { + PaUtil_FreeMemory( current->buffer ); + current->buffer = 0; + + previous = current; + current = current->next; + } + + /* link the former allocations list onto the front of the spareLinks list */ + if( previous ) + { + previous->next = group->spareLinks; + group->spareLinks = group->allocations; + group->allocations = 0; + } +} + |