Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
update the double extern declaration bis
[simgrid.git] / src / xbt / fifo.c
1 /*      $Id$     */
2
3 /* Copyright (c) 2004 Arnaud Legrand. All rights reserved.                  */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include "xbt/sysdep.h"
9 #include "xbt/log.h"
10 #include "xbt/mallocator.h"
11 #include "fifo_private.h"
12 #include "xbt_modinter.h"
13
14 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_fifo,xbt,"FIFO");
15
16 static void* fifo_item_mallocator_new_f(void);
17 static void fifo_item_mallocator_free_f(void* item);
18 static void fifo_item_mallocator_reset_f(void* item);
19
20 static xbt_mallocator_t item_mallocator = NULL;
21
22 /** Constructor
23  * \return a new fifo
24  */
25 xbt_fifo_t xbt_fifo_new(void)
26 {
27   xbt_fifo_t fifo;
28   fifo = xbt_new0(struct xbt_fifo,1);
29
30   if (item_mallocator == NULL) {
31     item_mallocator = xbt_mallocator_new(256,
32                                          fifo_item_mallocator_new_f,
33                                          fifo_item_mallocator_free_f,
34                                          fifo_item_mallocator_reset_f);
35   }
36   return fifo;
37 }
38
39 /** Destructor
40  * \param l poor victim
41  *
42  * Free the fifo structure. None of the objects that was in the fifo is however modified.
43  */
44 void xbt_fifo_free(xbt_fifo_t l)
45 {
46   xbt_fifo_item_t b, tmp;
47
48   for (b = xbt_fifo_get_first_item(l); b;
49        tmp = b, b = b->next, xbt_fifo_free_item(tmp));
50   xbt_free(l);
51   return;
52 }
53
54 /** Push
55  * \param l list
56  * \param t element
57  * \return the bucket that was just added
58  *
59  * Add an object at the tail of the list
60  */
61 xbt_fifo_item_t xbt_fifo_push(xbt_fifo_t l, void *t)
62 {
63   xbt_fifo_item_t new;
64
65   new = xbt_fifo_new_item();
66   new->content = t;
67
68   xbt_fifo_push_item(l,new);
69   return new;
70 }
71
72 /** Pop
73  * \param l list
74  * \returns the object stored at the tail of the list.
75  *
76  * Removes and returns the object stored at the tail of the list. 
77  * Returns NULL if the list is empty.
78  */
79 void *xbt_fifo_pop(xbt_fifo_t l)
80 {
81   xbt_fifo_item_t item;
82   void *content;
83
84   if(l==NULL) return NULL;
85   if(!(item = xbt_fifo_pop_item(l))) return NULL;
86
87   content = item->content;
88   xbt_fifo_free_item(item);
89   return content;
90 }
91
92 /**
93  * \param l list
94  * \param t element
95  * \return the bucket that was just added
96  *
97  * Add an object at the head of the list
98  */
99 xbt_fifo_item_t xbt_fifo_unshift(xbt_fifo_t l, void *t)
100 {
101   xbt_fifo_item_t new;
102
103   new = xbt_fifo_new_item();
104   new->content = t;
105   xbt_fifo_unshift_item(l,new);
106   return new;
107 }
108
109 /** Shift
110  * \param l list
111  * \returns the object stored at the head of the list.
112  *
113  * Removes and returns the object stored at the head of the list. 
114  * Returns NULL if the list is empty.
115  */
116 void *xbt_fifo_shift(xbt_fifo_t l)
117 {
118   xbt_fifo_item_t item;
119   void *content;
120
121   if(l==NULL) return NULL;
122   if(!(item = xbt_fifo_shift_item(l))) return NULL;
123   
124   content = item->content;
125   xbt_fifo_free_item(item);
126   return content;
127 }
128
129 /** Push a bucket
130  * \param l list
131  * \param new bucket
132  *
133  * Hook up this bucket at the tail of the list
134  */
135 void xbt_fifo_push_item(xbt_fifo_t l, xbt_fifo_item_t new)
136 {
137   xbt_assert0((new->next == NULL)&&(new->prev == NULL),"Invalid item!");
138   (l->count)++;
139   if (l->head == NULL) {
140     l->head = new;
141     l->tail = new;
142     return;
143   }
144   new->prev = l->tail;
145   new->prev->next = new;
146   l->tail = new;
147 }
148
149 /** Pop bucket
150  * \param l
151  * \returns the bucket that was at the tail of the list.
152  *
153  * Returns NULL if the list was empty.
154  */
155 xbt_fifo_item_t xbt_fifo_pop_item(xbt_fifo_t l)
156 {
157   xbt_fifo_item_t item;
158
159   if (l->tail == NULL)
160     return NULL;
161
162   item = l->tail;
163   
164   l->tail = item->prev;
165   if (l->tail == NULL)
166     l->head = NULL;
167   else
168     l->tail->next = NULL;
169
170   (l->count)--;
171
172   item->prev = NULL;
173
174   return item;
175 }
176
177 /** Push a bucket
178  * \param l list
179  * \param new bucket
180  *
181  * Hook up this bucket at the head of the list
182  */
183 void xbt_fifo_unshift_item(xbt_fifo_t l, xbt_fifo_item_t new)
184 {
185   xbt_assert0((new->next == NULL)&&(new->prev == NULL),"Invalid item!");
186   (l->count)++;
187   if (l->head == NULL) {
188     l->head = new;
189     l->tail = new;
190     return;
191   }
192   new->next = l->head;
193   new->next->prev = new;
194   l->head = new;
195   return;
196 }
197
198 /** Shift bucket
199  * \param l
200  * \returns the bucket that was at the head of the list.
201  *
202  * Returns NULL if the list was empty.
203  */
204 xbt_fifo_item_t xbt_fifo_shift_item(xbt_fifo_t l)
205 {
206   xbt_fifo_item_t item;
207
208   if (l->head == NULL)
209     return NULL;
210
211   item = l->head;
212
213   l->head = item->next;
214   if (l->head == NULL)
215     l->tail = NULL;
216   else
217     l->head->prev = NULL;
218
219   (l->count)--;
220
221   item->next = NULL;
222
223   return item;
224 }
225
226 /**
227  * \param l 
228  * \param t an objet
229  *
230  * removes the first occurence of \a t from \a l. 
231  * \warning it will not remove duplicates
232  */
233 void xbt_fifo_remove(xbt_fifo_t l, void *t)
234 {
235   xbt_fifo_item_t current, current_next;
236
237
238   for (current = l->head; current; current = current_next) {
239     current_next = current->next;
240     if (current->content != t)
241       continue;
242     /* remove the item */
243     xbt_fifo_remove_item(l, current);
244     xbt_fifo_free_item(current);
245     /* WILL NOT REMOVE DUPLICATES */
246     break;
247   }
248   return;
249 }
250
251 /**
252  * \param l a list
253  * \param current a bucket
254  *
255  * removes a bucket \a current from the list \a l. This function implicitely 
256  * assumes (and doesn't check!) that this item belongs to this list... 
257  */
258 void xbt_fifo_remove_item(xbt_fifo_t l, xbt_fifo_item_t current)
259 {
260   if (l->head == l->tail) {     /* special case */
261     xbt_assert0((current==l->head),"This item is not in the list!");
262     l->head = NULL;
263     l->tail = NULL;
264     (l->count)--;
265     current->prev = current->next = NULL;
266     return;
267   }
268
269   if (current == l->head) {     /* It's the head */
270     l->head = current->next;
271     l->head->prev = NULL;
272   } else if (current == l->tail) {      /* It's the tail */
273     l->tail = current->prev;
274     l->tail->next = NULL;
275   } else {                      /* It's in the middle */
276     current->prev->next = current->next;
277     current->next->prev = current->prev;
278   }
279   (l->count)--;
280   current->prev = current->next = NULL;
281 }
282
283 /**
284  * \param f a list
285  * \param content an object
286  * \return 1 if \a content is in \a f.
287  */
288 int xbt_fifo_is_in(xbt_fifo_t f, void *content)
289 {
290   xbt_fifo_item_t item = xbt_fifo_get_first_item(f);
291   while (item) {
292     if (item->content == content)
293       return 1;
294     item = item->next;
295   }
296   return 0;
297 }
298
299 /**
300  * \param f a list
301  * \return a table with the objects stored in \a f.
302  */
303 void **xbt_fifo_to_array(xbt_fifo_t f)
304 {
305   void **array;
306   xbt_fifo_item_t b;
307   int i;
308
309   if (f->count == 0)
310     return NULL;
311   else
312     array = xbt_new0(void *, f->count);
313
314   for (i = 0, b = xbt_fifo_get_first_item(f); b; i++, b = b->next) {
315     array[i] = b->content;
316   }
317   return array;
318 }
319
320 /**
321  * \param f a list
322  * \return a copy of \a f.
323  */
324 xbt_fifo_t xbt_fifo_copy(xbt_fifo_t f)
325 {
326   xbt_fifo_t copy = NULL;
327   xbt_fifo_item_t b;
328
329   copy = xbt_fifo_new();
330
331   for (b = xbt_fifo_get_first_item(f); b; b = b->next) {
332     xbt_fifo_push(copy, b->content);
333   }
334   return copy;
335 }
336
337 /* Functions passed to the mallocator constructor */
338 static void* fifo_item_mallocator_new_f(void) {
339   return xbt_new(s_xbt_fifo_item_t, 1);
340 }
341
342 static void fifo_item_mallocator_free_f(void* item) {
343   xbt_free(item);
344 }
345
346 static void fifo_item_mallocator_reset_f(void* item) {
347   /* memset to zero like calloc */
348   memset(item, 0, sizeof(s_xbt_fifo_item_t));
349 }
350
351 /** Constructor
352  * \return a new bucket
353  */
354 xbt_fifo_item_t xbt_fifo_new_item(void)
355 {
356   return xbt_mallocator_get(item_mallocator);
357 }
358
359 /** \deprecated Use #xbt_fifo_new_item instead.
360  */
361 xbt_fifo_item_t xbt_fifo_newitem(void)
362 {
363   WARN0("This function is deprecated. Use xbt_fifo_new_item.");
364   return xbt_fifo_new_item();
365 }
366
367 /**
368  * \param i a bucket
369  * \param v an object
370  *
371  * stores \a v in \a i.
372  */
373 void xbt_fifo_set_item_content(xbt_fifo_item_t i , void *v)
374 {
375   xbt_fifo_setItemcontent(i,v);
376 }
377
378 /**
379  * \param i a bucket
380  * \return the object stored \a i.
381  */
382 void *xbt_fifo_get_item_content(xbt_fifo_item_t i)
383 {
384   return xbt_fifo_getItemcontent(i);
385 }
386
387 /** Destructor
388  * \param b poor victim
389  *
390  * Free the bucket but does not modifies the object (if any) that was stored in it.
391  */
392 void xbt_fifo_free_item(xbt_fifo_item_t b)
393 {
394   xbt_mallocator_release(item_mallocator, b);
395   return;
396 }
397
398 /** Destructor
399  * \deprecated Use #xbt_fifo_free_item instead.
400  */
401 void xbt_fifo_freeitem(xbt_fifo_item_t b)
402 {
403   WARN0("This function is deprecated. Use xbt_fifo_free_item.");
404   xbt_fifo_free_item(b);
405   return;
406 }
407
408 /**
409  * \param f a list
410  * \return the number of buckets in \a f.
411  */
412 int xbt_fifo_size(xbt_fifo_t f)
413 {
414   return f->count;
415 }
416
417 /**
418  * \param l a list
419  * \return the head of \a l.
420  */
421 xbt_fifo_item_t xbt_fifo_get_first_item(xbt_fifo_t l)
422 {
423   return l->head;
424 }
425
426 /** \deprecated Use #xbt_fifo_get_first_item instead.
427  */
428 xbt_fifo_item_t xbt_fifo_getFirstItem(xbt_fifo_t l)
429 {
430   WARN0("This function is deprecated. Use xbt_fifo_get_first_item.");
431   return xbt_fifo_get_first_item(l);
432 }
433
434 /**
435  * \param i a bucket
436  * \return the bucket that comes next
437  */
438 xbt_fifo_item_t xbt_fifo_get_next_item(xbt_fifo_item_t i)
439 {
440   if(i) return i->next;
441   return NULL;
442 }
443
444 /** \deprecated Use #xbt_fifo_get_next_item instead.
445  */
446 xbt_fifo_item_t xbt_fifo_getNextItem(xbt_fifo_item_t i)
447 {
448   WARN0("This function is deprecated. Use xbt_fifo_get_next_item.");
449   return xbt_fifo_get_next_item(i);
450 }
451
452 /**
453  * \param i a bucket
454  * \return the bucket that is just before \a i.
455  */
456 xbt_fifo_item_t xbt_fifo_get_prev_item(xbt_fifo_item_t i)
457 {
458   if(i) return i->prev;
459   return NULL;
460 }
461
462 /** \deprecated Use #xbt_fifo_get_prev_item instead.
463  */
464 xbt_fifo_item_t xbt_fifo_getPrevItem(xbt_fifo_item_t i)
465 {
466   WARN0("This function is deprecated. Use xbt_fifo_get_prev_item.");
467   return xbt_fifo_get_prev_item(i);
468 }
469
470 /**
471  * Destroy the fifo item mallocator.
472  * This is an internal XBT function called by xbt_exit().
473  */
474 void xbt_fifo_exit(void) {
475   if (item_mallocator != NULL) {
476     xbt_mallocator_free(item_mallocator);
477   }
478 }
479
480 /* @} */
481
482