fix doc build fix autogen
[platform/upstream/gstreamer.git] / gst / gstmemchunk.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <string.h>             /* memset */
21
22 #include "gstlog.h"
23 #include "gstutils.h"
24 #include "gstmemchunk.h"
25 #include "gsttrashstack.h"
26
27 #define GST_MEM_CHUNK_AREA(chunk)       (((GstMemChunkElement*)(chunk))->area)
28 #define GST_MEM_CHUNK_DATA(chunk)       ((gpointer)(((GstMemChunkElement*)(chunk)) + 1))
29 #define GST_MEM_CHUNK_LINK(mem)         ((GstMemChunkElement*)((guint8*)(mem) - sizeof (GstMemChunkElement)))
30
31 typedef struct _GstMemChunkElement GstMemChunkElement;
32
33 struct _GstMemChunkElement
34 {
35   GstTrashStackElement   elem;          /* make sure we can safely push it on the trashstack */
36   gpointer               area;          /* pointer to data areas */
37 };
38
39 struct _GstMemChunk
40 {
41   GstTrashStack  stack;
42
43   gchar         *name;
44   gulong         area_size;
45   gulong         chunk_size;
46   gulong         atom_size;
47   gboolean       cleanup;
48 };
49
50 /*******************************************************
51  *         area size
52  * +-------------------------------------------------------+
53  *   chunk size
54  * +-----------------+
55  *
56  * !next!area|data... !next!area!data.... !next!area!data...
57  *  !                  ^ !                 ^ !
58  *  +------------------+ +-----------------+ +--------> NULL
59  *
60  */
61 static gboolean
62 populate (GstMemChunk *mem_chunk) 
63 {
64   guint8 *area;
65   gint i;
66
67   if (mem_chunk->cleanup)
68     return FALSE;
69  
70   area = (guint8 *) g_malloc0 (mem_chunk->area_size);
71
72   for (i=0; i < mem_chunk->area_size; i += mem_chunk->chunk_size) { 
73     GST_MEM_CHUNK_AREA (area + i) = area;
74     gst_trash_stack_push (&mem_chunk->stack, area + i);
75   }
76
77   return TRUE;
78 }
79
80 /**
81  * gst_mem_chunk_new:
82  * @name: the name of the chunk
83  * @atom_size: the size of the allocated atoms
84  * @area_size: the initial size of the memory area
85  * @type: the allocation strategy to use
86  *
87  * Creates a new memchunk that will allocate atom_sized memchunks.
88  * The initial area is set to area_size and will grow automatically 
89  * when it is too small (with a small overhead when that happens)
90  *
91  * Returns: a new #GstMemChunk
92  */
93 GstMemChunk*
94 gst_mem_chunk_new (gchar* name, gint atom_size, gulong area_size, gint type)
95 {
96   GstMemChunk *mem_chunk;
97
98   g_return_val_if_fail (atom_size > 0, NULL);
99   g_return_val_if_fail (area_size >= atom_size, NULL);
100
101   mem_chunk = g_malloc (sizeof (GstMemChunk));
102
103   mem_chunk->chunk_size = atom_size + sizeof (GstMemChunkElement);
104   area_size = (area_size/atom_size) * mem_chunk->chunk_size;
105
106   mem_chunk->name = g_strdup (name);
107   mem_chunk->atom_size = atom_size;
108   mem_chunk->area_size = area_size;
109   mem_chunk->cleanup = FALSE;
110   gst_trash_stack_init (&mem_chunk->stack);
111
112   populate (mem_chunk);
113
114   return mem_chunk;
115 }
116
117 static gboolean
118 free_area (gpointer key, gpointer value, gpointer user_data)
119 {
120   g_free (key);
121
122   return TRUE;
123 }
124
125 /**
126  * gst_mem_chunk_destroy:
127  * @mem_chunk: the GstMemChunk to destroy
128  *
129  * Free the memory allocated by the memchunk
130  */
131 void
132 gst_mem_chunk_destroy (GstMemChunk *mem_chunk) 
133 {
134   GHashTable *elements = g_hash_table_new (NULL, NULL);
135   gpointer data;
136
137   mem_chunk->cleanup = TRUE;
138
139   data = gst_mem_chunk_alloc (mem_chunk);
140   while (data) {
141     GstMemChunkElement *elem = GST_MEM_CHUNK_LINK (data);
142
143     g_hash_table_insert (elements, GST_MEM_CHUNK_AREA (elem), NULL); 
144     
145     data = gst_mem_chunk_alloc (mem_chunk);
146   } 
147   g_hash_table_foreach_remove (elements, free_area, NULL);
148
149   g_hash_table_destroy (elements);
150   g_free (mem_chunk->name);
151   g_free (mem_chunk);
152 }
153
154 /**
155  * gst_mem_chunk_alloc:
156  * @mem_chunk: the mem chunk to use
157  *
158  * Allocate a new memory region from the chunk. The size
159  * of the allocated memory was specified when the memchunk
160  * was created.
161  *
162  * Returns: a pointer to the allocated memory region.
163  */
164 gpointer
165 gst_mem_chunk_alloc (GstMemChunk *mem_chunk)
166 {
167   GstMemChunkElement *chunk;
168   
169   g_return_val_if_fail (mem_chunk != NULL, NULL);
170
171 again:
172   chunk = gst_trash_stack_pop (&mem_chunk->stack);
173   /* chunk is empty, try to refill */
174   if (!chunk) {
175     if (populate (mem_chunk))
176       goto again;
177     else 
178       return NULL;
179   }
180
181   return GST_MEM_CHUNK_DATA (chunk);
182 }
183
184 /**
185  * gst_mem_chunk_alloc0:
186  * @mem_chunk: the mem chunk to use
187  *
188  * Allocate a new memory region from the chunk. The size
189  * of the allocated memory was specified when the memchunk
190  * was created. The memory will be set to all zeroes.
191  *
192  * Returns: a pointer to the allocated memory region.
193  */
194 gpointer
195 gst_mem_chunk_alloc0 (GstMemChunk *mem_chunk)
196 {
197   gpointer mem = gst_mem_chunk_alloc (mem_chunk);
198
199   if (mem)
200     memset (mem, 0, mem_chunk->atom_size);
201   
202   return mem;
203 }
204
205 /**
206  * gst_mem_chunk_free:
207  * @mem_chunk: the mem chunk to use
208  * @mem: the memory region to hand back to the chunk
209  *
210  * Free the memeory region allocated from the chunk.
211  */
212 void
213 gst_mem_chunk_free (GstMemChunk *mem_chunk, gpointer mem)
214 {
215   GstMemChunkElement *chunk;
216   
217   g_return_if_fail (mem_chunk != NULL);
218   g_return_if_fail (mem != NULL);
219
220   chunk = GST_MEM_CHUNK_LINK (mem);
221
222   gst_trash_stack_push (&mem_chunk->stack, chunk);
223 }