* Removed all Id tags.
[cacao.git] / src / toolbox / list.c
1 /* src/toolbox/list.c - double linked list
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25 */
26
27
28 #include "config.h"
29
30 #include <stdlib.h>
31
32 #include "vm/types.h"
33
34 #include "mm/memory.h"
35
36 #include "threads/lock-common.h"
37
38 #include "toolbox/list.h"
39
40
41 /* list_create *****************************************************************
42
43    Allocates a new list and initializes the lock object.
44
45 *******************************************************************************/
46
47 list_t *list_create(s4 nodeoffset)
48 {
49         list_t *l;
50
51         l = NEW(list_t);
52
53         LOCK_INIT_OBJECT_LOCK(l);
54
55         l->first      = NULL;
56         l->last       = NULL;
57         l->nodeoffset = nodeoffset;
58         l->size       = 0;
59
60         return l;
61 }
62
63
64 /* list_create_dump ************************************************************
65
66    Allocates a new list on the dump memory.
67
68    ATTENTION: This list does NOT initialize the locking object!!!
69
70 *******************************************************************************/
71
72 list_t *list_create_dump(s4 nodeoffset)
73 {
74         list_t *l;
75
76         l = DNEW(list_t);
77
78         l->first      = NULL;
79         l->last       = NULL;
80         l->nodeoffset = nodeoffset;
81         l->size       = 0;
82
83         return l;
84 }
85
86
87 /* list_add_first **************************************************************
88
89    Adds the element as first element.
90
91 *******************************************************************************/
92
93 void list_add_first(list_t *l, void *element)
94 {
95         LOCK_MONITOR_ENTER(l);
96
97         list_add_first_unsynced(l, element);
98
99         LOCK_MONITOR_EXIT(l);
100 }
101
102
103 /* list_add_first_unsynced *****************************************************
104
105    Adds the element as first element, but WITHOUT LOCKING!
106
107    ATTENTION: Use this function with care!!!
108
109 *******************************************************************************/
110
111 void list_add_first_unsynced(list_t *l, void *element)
112 {
113         listnode_t *ln;
114
115         ln = (listnode_t *) (((u1 *) element) + l->nodeoffset);
116
117         if (l->first) {
118                 ln->prev       = NULL;
119                 ln->next       = l->first;
120                 l->first->prev = ln;
121                 l->first       = ln;
122         }
123         else {
124                 ln->prev = NULL;
125                 ln->next = NULL;
126                 l->last  = ln;
127                 l->first = ln;
128         }
129
130         /* increase number of elements */
131
132         l->size++;
133 }
134
135
136 /* list_add_last ***************************************************************
137
138    Adds the element as last element.
139
140 *******************************************************************************/
141
142 void list_add_last(list_t *l, void *element)
143 {
144         LOCK_MONITOR_ENTER(l);
145
146         list_add_last_unsynced(l, element);
147
148         LOCK_MONITOR_EXIT(l);
149 }
150
151
152 /* list_add_last_unsynced ******************************************************
153
154    Adds the element as last element but does NO locking!
155
156    ATTENTION: Use this function with care!!!
157
158 *******************************************************************************/
159
160 void list_add_last_unsynced(list_t *l, void *element)
161 {
162         listnode_t *ln;
163
164         ln = (listnode_t *) (((u1 *) element) + l->nodeoffset);
165
166         if (l->last) {
167                 ln->prev      = l->last;
168                 ln->next      = NULL;
169                 l->last->next = ln;
170                 l->last       = ln;
171         }
172         else {
173                 ln->prev = NULL;
174                 ln->next = NULL;
175                 l->last  = ln;
176                 l->first = ln;
177         }
178
179         /* increase number of elements */
180
181         l->size++;
182 }
183
184
185 /* list_add_before *************************************************************
186
187    Adds the element newelement to the list l before element.
188
189    [ A ] <-> [ newn ] <-> [ n ] <-> [ B ]
190
191 *******************************************************************************/
192
193 void list_add_before(list_t *l, void *element, void *newelement)
194 {
195         listnode_t *ln;
196         listnode_t *newln;
197
198         ln    = (listnode_t *) (((u1 *) element) + l->nodeoffset);
199         newln = (listnode_t *) (((u1 *) newelement) + l->nodeoffset);
200
201         LOCK_MONITOR_ENTER(l);
202
203         /* set the new links */
204
205         newln->prev = ln->prev;
206         newln->next = ln;
207
208         if (newln->prev)
209                 newln->prev->next = newln;
210
211         ln->prev = newln;
212
213         /* set list's first and last if necessary */
214
215         if (l->first == ln)
216                 l->first = newln;
217
218         if (l->last == ln)
219                 l->last = newln;
220
221         /* increase number of elements */
222
223         l->size++;
224
225         LOCK_MONITOR_EXIT(l);
226 }
227
228
229 /* list_remove ***************************************************************
230
231    Removes the element.
232
233 *******************************************************************************/
234
235 void list_remove(list_t *l, void *element)
236 {
237         LOCK_MONITOR_ENTER(l);
238
239         list_remove_unsynced(l, element);
240
241         LOCK_MONITOR_EXIT(l);
242 }
243
244
245 /* list_remove_unsynced ********************************************************
246
247    Removes the element but does NO locking!
248
249    ATTENTION: Use this function with care!!!
250
251 *******************************************************************************/
252
253 void list_remove_unsynced(list_t *l, void *element)
254 {
255         listnode_t *ln;
256
257         ln = (listnode_t *) (((u1 *) element) + l->nodeoffset);
258         
259         if (ln->next)
260                 ln->next->prev = ln->prev;
261         else
262                 l->last = ln->prev;
263
264         if (ln->prev)
265                 ln->prev->next = ln->next;
266         else
267                 l->first = ln->next;
268
269         ln->next = NULL;
270         ln->prev = NULL;
271
272         /* decrease number of elements */
273
274         l->size--;
275 }
276
277  
278 /* list_first ******************************************************************
279
280    Returns the first element of the list.
281
282 *******************************************************************************/
283
284 void *list_first(list_t *l)
285 {
286         void *el;
287
288         LOCK_MONITOR_ENTER(l);
289
290         el = list_first_unsynced(l);
291
292         LOCK_MONITOR_EXIT(l);
293
294         return el;
295 }
296
297
298 /* list_first_unsynced *********************************************************
299
300    Returns the first element of the list, but does NO locking!
301
302    ATTENTION: Use this function with care!!!
303
304 *******************************************************************************/
305
306 void *list_first_unsynced(list_t *l)
307 {
308         void *el;
309
310         if (l->first == NULL)
311                 el = NULL;
312         else
313                 el = ((u1 *) l->first) - l->nodeoffset;
314
315         return el;
316 }
317
318
319 /* list_last *******************************************************************
320
321    Returns the last element of the list.
322
323 *******************************************************************************/
324
325 void *list_last(list_t *l)
326 {
327         void *el;
328
329         LOCK_MONITOR_ENTER(l);
330
331         el = list_last_unsynced(l);
332
333         LOCK_MONITOR_EXIT(l);
334
335         return el;
336 }
337
338
339 /* list_last_unsynced **********************************************************
340
341    Returns the last element of the list, but does NO locking!
342
343    ATTENTION: Use this function with care!!!
344
345 *******************************************************************************/
346
347 void *list_last_unsynced(list_t *l)
348 {
349         void *el;
350
351         if (l->last == NULL)
352                 el = NULL;
353         else
354                 el = ((u1 *) l->last) - l->nodeoffset;
355
356         return el;
357 }
358
359
360 /* list_next *******************************************************************
361
362    Returns the next element of element from the list.
363
364 *******************************************************************************/
365
366 void *list_next(list_t *l, void *element)
367 {
368         void *el;
369
370         LOCK_MONITOR_ENTER(l);
371
372         el = list_next_unsynced(l, element);
373
374         LOCK_MONITOR_EXIT(l);
375
376         return el;
377 }
378
379
380 /* list_next_unsynced **********************************************************
381
382    Returns the next element of element from the list, but does NO
383    locking!
384
385    ATTENTION: Use this function with care!!!
386
387 *******************************************************************************/
388
389 void *list_next_unsynced(list_t *l, void *element)
390 {
391         listnode_t *ln;
392         void     *el;
393
394         ln = (listnode_t *) (((u1 *) element) + l->nodeoffset);
395
396         if (ln->next == NULL)
397                 el = NULL;
398         else
399                 el = ((u1 *) ln->next) - l->nodeoffset;
400
401         return el;
402 }
403
404         
405 /* list_prev *******************************************************************
406
407    Returns the previous element of element from the list.
408
409 *******************************************************************************/
410
411 void *list_prev(list_t *l, void *element)
412 {
413         void *el;
414
415         LOCK_MONITOR_ENTER(l);
416
417         el = list_prev_unsynced(l, element);
418
419         LOCK_MONITOR_EXIT(l);
420
421         return el;
422 }
423
424
425 /* list_prev_unsynced **********************************************************
426
427    Returns the previous element of element from the list, but does NO
428    locking!
429
430    ATTENTION: Use this function with care!!!
431
432 *******************************************************************************/
433
434 void *list_prev_unsynced(list_t *l, void *element)
435 {
436         listnode_t *ln;
437         void     *el;
438
439         ln = (listnode_t *) (((u1 *) element) + l->nodeoffset);
440
441         if (ln->prev == NULL)
442                 el = NULL;
443         else
444                 el = ((u1 *) ln->prev) - l->nodeoffset;
445
446         return el;
447 }
448
449
450 /*
451  * These are local overrides for various environment variables in Emacs.
452  * Please do not remove this and leave it at the end of the file, where
453  * Emacs will automagically detect them.
454  * ---------------------------------------------------------------------
455  * Local variables:
456  * mode: c
457  * indent-tabs-mode: t
458  * c-basic-offset: 4
459  * tab-width: 4
460  * End:
461  */