[hazard pointers] add write barrier on clear as well
[mono-project.git] / eglib / src / gptrarray.c
blobd3e540733bd1c896a68f42fe372bb27f0e2b49eb
1 /*
2 * Pointer Array
4 * Author:
5 * Aaron Bockover (abockover@novell.com)
6 * Gonzalo Paniagua Javier (gonzalo@novell.com)
7 * Jeffrey Stedfast (fejj@novell.com)
9 * (C) 2006,2011 Novell, Inc.
11 * Permission is hereby granted, free of charge, to any person obtaining
12 * a copy of this software and associated documentation files (the
13 * "Software"), to deal in the Software without restriction, including
14 * without limitation the rights to use, copy, modify, merge, publish,
15 * distribute, sublicense, and/or sell copies of the Software, and to
16 * permit persons to whom the Software is furnished to do so, subject to
17 * the following conditions:
19 * The above copyright notice and this permission notice shall be
20 * included in all copies or substantial portions of the Software.
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 #include <stdlib.h>
32 #include <glib.h>
34 typedef struct _GPtrArrayPriv {
35 gpointer *pdata;
36 guint len;
37 guint size;
38 } GPtrArrayPriv;
40 static void
41 g_ptr_array_grow(GPtrArrayPriv *array, guint length)
43 guint new_length = array->len + length;
45 g_return_if_fail(array != NULL);
47 if(new_length <= array->size) {
48 return;
51 array->size = 1;
53 while(array->size < new_length) {
54 array->size <<= 1;
57 array->size = MAX(array->size, 16);
58 array->pdata = g_realloc(array->pdata, array->size * sizeof(gpointer));
61 GPtrArray *
62 g_ptr_array_new(void)
64 return g_ptr_array_sized_new(0);
67 GPtrArray *
68 g_ptr_array_sized_new(guint reserved_size)
70 GPtrArrayPriv *array = g_new0(GPtrArrayPriv, 1);
72 array->pdata = NULL;
73 array->len = 0;
74 array->size = 0;
76 if(reserved_size > 0) {
77 g_ptr_array_grow(array, reserved_size);
80 return (GPtrArray *)array;
83 gpointer *
84 g_ptr_array_free(GPtrArray *array, gboolean free_seg)
86 gpointer *data = NULL;
88 g_return_val_if_fail(array != NULL, NULL);
90 if(free_seg) {
91 g_free(array->pdata);
92 } else {
93 data = array->pdata;
96 g_free(array);
98 return data;
101 void
102 g_ptr_array_set_size(GPtrArray *array, gint length)
104 g_return_if_fail(array != NULL);
106 if((size_t)length > array->len) {
107 g_ptr_array_grow((GPtrArrayPriv *)array, length);
108 memset(array->pdata + array->len, 0, (length - array->len)
109 * sizeof(gpointer));
112 array->len = length;
115 void
116 g_ptr_array_add(GPtrArray *array, gpointer data)
118 g_return_if_fail(array != NULL);
119 g_ptr_array_grow((GPtrArrayPriv *)array, 1);
120 array->pdata[array->len++] = data;
123 gpointer
124 g_ptr_array_remove_index(GPtrArray *array, guint index)
126 gpointer removed_node;
128 g_return_val_if_fail(array != NULL, NULL);
129 g_return_val_if_fail(index < array->len, NULL);
131 removed_node = array->pdata[index];
133 if(index != array->len - 1) {
134 g_memmove(array->pdata + index, array->pdata + index + 1,
135 (array->len - index - 1) * sizeof(gpointer));
138 array->len--;
139 array->pdata[array->len] = NULL;
141 return removed_node;
144 gpointer
145 g_ptr_array_remove_index_fast(GPtrArray *array, guint index)
147 gpointer removed_node;
149 g_return_val_if_fail(array != NULL, NULL);
150 g_return_val_if_fail(index < array->len, NULL);
152 removed_node = array->pdata[index];
154 if(index != array->len - 1) {
155 g_memmove(array->pdata + index, array->pdata + array->len - 1,
156 sizeof(gpointer));
159 array->len--;
160 array->pdata[array->len] = NULL;
162 return removed_node;
165 gboolean
166 g_ptr_array_remove(GPtrArray *array, gpointer data)
168 guint i;
170 g_return_val_if_fail(array != NULL, FALSE);
172 for(i = 0; i < array->len; i++) {
173 if(array->pdata[i] == data) {
174 g_ptr_array_remove_index(array, i);
175 return TRUE;
179 return FALSE;
182 gboolean
183 g_ptr_array_remove_fast(GPtrArray *array, gpointer data)
185 guint i;
187 g_return_val_if_fail(array != NULL, FALSE);
189 for(i = 0; i < array->len; i++) {
190 if(array->pdata[i] == data) {
191 array->len--;
192 if (array->len > 0)
193 array->pdata [i] = array->pdata [array->len];
194 else
195 array->pdata [i] = NULL;
196 return TRUE;
200 return FALSE;
203 void
204 g_ptr_array_foreach(GPtrArray *array, GFunc func, gpointer user_data)
206 guint i;
208 for(i = 0; i < array->len; i++) {
209 func(g_ptr_array_index(array, i), user_data);
213 void
214 g_ptr_array_sort(GPtrArray *array, GCompareFunc compare)
216 g_return_if_fail(array != NULL);
217 qsort(array->pdata, array->len, sizeof(gpointer), compare);
220 void
221 g_ptr_array_sort_with_data (GPtrArray *array, GCompareDataFunc compare, gpointer user_data)
223 g_return_if_fail (array != NULL);
225 g_qsort_with_data (array->pdata, array->len, sizeof (gpointer), compare, user_data);