/[pcsx2_0.9.7]/trunk/3rdparty/portaudio/src/common/pa_allocation.c
ViewVC logotype

Contents of /trunk/3rdparty/portaudio/src/common/pa_allocation.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (show annotations) (download)
Mon Sep 6 11:40:06 2010 UTC (9 years, 11 months ago) by william
File MIME type: text/plain
File size: 7133 byte(s)
exported r3113 from ./upstream/trunk
1 /*
2 * $Id: pa_allocation.c 1097 2006-08-26 08:27:53Z rossb $
3 * Portable Audio I/O Library allocation group implementation
4 * memory allocation group for tracking allocation groups
5 *
6 * Based on the Open Source API proposed by Ross Bencina
7 * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining
10 * a copy of this software and associated documentation files
11 * (the "Software"), to deal in the Software without restriction,
12 * including without limitation the rights to use, copy, modify, merge,
13 * publish, distribute, sublicense, and/or sell copies of the Software,
14 * and to permit persons to whom the Software is furnished to do so,
15 * subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
24 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
25 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 */
28
29 /*
30 * The text above constitutes the entire PortAudio license; however,
31 * the PortAudio community also makes the following non-binding requests:
32 *
33 * Any person wishing to distribute modifications to the Software is
34 * requested to send the modifications to the original developer so that
35 * they can be incorporated into the canonical version. It is also
36 * requested that these non-binding requests be included along with the
37 * license above.
38 */
39
40 /** @file
41 @ingroup common_src
42
43 @brief Allocation Group implementation.
44 */
45
46
47 #include "pa_allocation.h"
48 #include "pa_util.h"
49
50
51 /*
52 Maintain 3 singly linked lists...
53 linkBlocks: the buffers used to allocate the links
54 spareLinks: links available for use in the allocations list
55 allocations: the buffers currently allocated using PaUtil_ContextAllocateMemory()
56
57 Link block size is doubled every time new links are allocated.
58 */
59
60
61 #define PA_INITIAL_LINK_COUNT_ 16
62
63 struct PaUtilAllocationGroupLink
64 {
65 struct PaUtilAllocationGroupLink *next;
66 void *buffer;
67 };
68
69 /*
70 Allocate a block of links. The first link will have it's buffer member
71 pointing to the block, and it's next member set to <nextBlock>. The remaining
72 links will have NULL buffer members, and each link will point to
73 the next link except the last, which will point to <nextSpare>
74 */
75 static struct PaUtilAllocationGroupLink *AllocateLinks( long count,
76 struct PaUtilAllocationGroupLink *nextBlock,
77 struct PaUtilAllocationGroupLink *nextSpare )
78 {
79 struct PaUtilAllocationGroupLink *result;
80 int i;
81
82 result = (struct PaUtilAllocationGroupLink *)PaUtil_AllocateMemory(
83 sizeof(struct PaUtilAllocationGroupLink) * count );
84 if( result )
85 {
86 /* the block link */
87 result[0].buffer = result;
88 result[0].next = nextBlock;
89
90 /* the spare links */
91 for( i=1; i<count; ++i )
92 {
93 result[i].buffer = 0;
94 result[i].next = &result[i+1];
95 }
96 result[count-1].next = nextSpare;
97 }
98
99 return result;
100 }
101
102
103 PaUtilAllocationGroup* PaUtil_CreateAllocationGroup( void )
104 {
105 PaUtilAllocationGroup* result = 0;
106 struct PaUtilAllocationGroupLink *links;
107
108
109 links = AllocateLinks( PA_INITIAL_LINK_COUNT_, 0, 0 );
110 if( links != 0 )
111 {
112 result = (PaUtilAllocationGroup*)PaUtil_AllocateMemory( sizeof(PaUtilAllocationGroup) );
113 if( result )
114 {
115 result->linkCount = PA_INITIAL_LINK_COUNT_;
116 result->linkBlocks = &links[0];
117 result->spareLinks = &links[1];
118 result->allocations = 0;
119 }
120 else
121 {
122 PaUtil_FreeMemory( links );
123 }
124 }
125
126 return result;
127 }
128
129
130 void PaUtil_DestroyAllocationGroup( PaUtilAllocationGroup* group )
131 {
132 struct PaUtilAllocationGroupLink *current = group->linkBlocks;
133 struct PaUtilAllocationGroupLink *next;
134
135 while( current )
136 {
137 next = current->next;
138 PaUtil_FreeMemory( current->buffer );
139 current = next;
140 }
141
142 PaUtil_FreeMemory( group );
143 }
144
145
146 void* PaUtil_GroupAllocateMemory( PaUtilAllocationGroup* group, long size )
147 {
148 struct PaUtilAllocationGroupLink *links, *link;
149 void *result = 0;
150
151 /* allocate more links if necessary */
152 if( !group->spareLinks )
153 {
154 /* double the link count on each block allocation */
155 links = AllocateLinks( group->linkCount, group->linkBlocks, group->spareLinks );
156 if( links )
157 {
158 group->linkCount += group->linkCount;
159 group->linkBlocks = &links[0];
160 group->spareLinks = &links[1];
161 }
162 }
163
164 if( group->spareLinks )
165 {
166 result = PaUtil_AllocateMemory( size );
167 if( result )
168 {
169 link = group->spareLinks;
170 group->spareLinks = link->next;
171
172 link->buffer = result;
173 link->next = group->allocations;
174
175 group->allocations = link;
176 }
177 }
178
179 return result;
180 }
181
182
183 void PaUtil_GroupFreeMemory( PaUtilAllocationGroup* group, void *buffer )
184 {
185 struct PaUtilAllocationGroupLink *current = group->allocations;
186 struct PaUtilAllocationGroupLink *previous = 0;
187
188 if( buffer == 0 )
189 return;
190
191 /* find the right link and remove it */
192 while( current )
193 {
194 if( current->buffer == buffer )
195 {
196 if( previous )
197 {
198 previous->next = current->next;
199 }
200 else
201 {
202 group->allocations = current->next;
203 }
204
205 current->buffer = 0;
206 current->next = group->spareLinks;
207 group->spareLinks = current;
208
209 break;
210 }
211
212 previous = current;
213 current = current->next;
214 }
215
216 PaUtil_FreeMemory( buffer ); /* free the memory whether we found it in the list or not */
217 }
218
219
220 void PaUtil_FreeAllAllocations( PaUtilAllocationGroup* group )
221 {
222 struct PaUtilAllocationGroupLink *current = group->allocations;
223 struct PaUtilAllocationGroupLink *previous = 0;
224
225 /* free all buffers in the allocations list */
226 while( current )
227 {
228 PaUtil_FreeMemory( current->buffer );
229 current->buffer = 0;
230
231 previous = current;
232 current = current->next;
233 }
234
235 /* link the former allocations list onto the front of the spareLinks list */
236 if( previous )
237 {
238 previous->next = group->spareLinks;
239 group->spareLinks = group->allocations;
240 group->allocations = 0;
241 }
242 }
243

  ViewVC Help
Powered by ViewVC 1.1.22