3 /* Copyright (c) 2004 Arnaud Legrand. All rights reserved. */
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. */
8 #include "xbt/sysdep.h"
10 #include "xbt/mallocator.h"
11 #include "fifo_private.h"
12 #include "xbt_modinter.h"
14 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_fifo,xbt,"FIFO");
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);
20 static xbt_mallocator_t item_mallocator = NULL;
25 xbt_fifo_t xbt_fifo_new(void)
28 fifo = xbt_new0(struct xbt_fifo,1);
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);
40 * \param l poor victim
42 * Free the fifo structure. None of the objects that was in the fifo is however modified.
44 void xbt_fifo_free(xbt_fifo_t l)
46 xbt_fifo_item_t b, tmp;
48 for (b = xbt_fifo_get_first_item(l); b;
49 tmp = b, b = b->next, xbt_fifo_free_item(tmp));
57 * \return the bucket that was just added
59 * Add an object at the tail of the list
61 xbt_fifo_item_t xbt_fifo_push(xbt_fifo_t l, void *t)
65 new = xbt_fifo_new_item();
68 xbt_fifo_push_item(l,new);
74 * \returns the object stored at the tail of the list.
76 * Removes and returns the object stored at the tail of the list.
77 * Returns NULL if the list is empty.
79 void *xbt_fifo_pop(xbt_fifo_t l)
84 if(l==NULL) return NULL;
85 if(!(item = xbt_fifo_pop_item(l))) return NULL;
87 content = item->content;
88 xbt_fifo_free_item(item);
95 * \return the bucket that was just added
97 * Add an object at the head of the list
99 xbt_fifo_item_t xbt_fifo_unshift(xbt_fifo_t l, void *t)
103 new = xbt_fifo_new_item();
105 xbt_fifo_unshift_item(l,new);
111 * \returns the object stored at the head of the list.
113 * Removes and returns the object stored at the head of the list.
114 * Returns NULL if the list is empty.
116 void *xbt_fifo_shift(xbt_fifo_t l)
118 xbt_fifo_item_t item;
121 if(l==NULL) return NULL;
122 if(!(item = xbt_fifo_shift_item(l))) return NULL;
124 content = item->content;
125 xbt_fifo_free_item(item);
133 * Hook up this bucket at the tail of the list
135 void xbt_fifo_push_item(xbt_fifo_t l, xbt_fifo_item_t new)
137 xbt_assert0((new->next == NULL)&&(new->prev == NULL),"Invalid item!");
139 if (l->head == NULL) {
145 new->prev->next = new;
151 * \returns the bucket that was at the tail of the list.
153 * Returns NULL if the list was empty.
155 xbt_fifo_item_t xbt_fifo_pop_item(xbt_fifo_t l)
157 xbt_fifo_item_t item;
164 l->tail = item->prev;
168 l->tail->next = NULL;
181 * Hook up this bucket at the head of the list
183 void xbt_fifo_unshift_item(xbt_fifo_t l, xbt_fifo_item_t new)
185 xbt_assert0((new->next == NULL)&&(new->prev == NULL),"Invalid item!");
187 if (l->head == NULL) {
193 new->next->prev = new;
200 * \returns the bucket that was at the head of the list.
202 * Returns NULL if the list was empty.
204 xbt_fifo_item_t xbt_fifo_shift_item(xbt_fifo_t l)
206 xbt_fifo_item_t item;
213 l->head = item->next;
217 l->head->prev = NULL;
230 * removes the first occurence of \a t from \a l.
231 * \warning it will not remove duplicates
232 * \return 1 if an item was removed and 0 otherwise.
234 int xbt_fifo_remove(xbt_fifo_t l, void *t)
236 xbt_fifo_item_t current, current_next;
239 for (current = l->head; current; current = current_next) {
240 current_next = current->next;
241 if (current->content != t)
243 /* remove the item */
244 xbt_fifo_remove_item(l, current);
245 xbt_fifo_free_item(current);
246 /* WILL NOT REMOVE DUPLICATES */
257 * removes all occurences of \a t from \a l.
258 * \return 1 if an item was removed and 0 otherwise.
260 int xbt_fifo_remove_all(xbt_fifo_t l, void *t)
262 xbt_fifo_item_t current, current_next;
265 for (current = l->head; current; current = current_next) {
266 current_next = current->next;
267 if (current->content != t)
269 /* remove the item */
270 xbt_fifo_remove_item(l, current);
271 xbt_fifo_free_item(current);
279 * \param current a bucket
281 * removes a bucket \a current from the list \a l. This function implicitely
282 * assumes (and doesn't check!) that this item belongs to this list...
284 void xbt_fifo_remove_item(xbt_fifo_t l, xbt_fifo_item_t current)
286 if (l->head == l->tail) { /* special case */
287 xbt_assert0((current==l->head),"This item is not in the list!");
291 current->prev = current->next = NULL;
295 if (current == l->head) { /* It's the head */
296 l->head = current->next;
297 l->head->prev = NULL;
298 } else if (current == l->tail) { /* It's the tail */
299 l->tail = current->prev;
300 l->tail->next = NULL;
301 } else { /* It's in the middle */
302 current->prev->next = current->next;
303 current->next->prev = current->prev;
306 current->prev = current->next = NULL;
311 * \param content an object
312 * \return 1 if \a content is in \a f.
314 int xbt_fifo_is_in(xbt_fifo_t f, void *content)
316 xbt_fifo_item_t item = xbt_fifo_get_first_item(f);
318 if (item->content == content)
327 * \return a table with the objects stored in \a f.
329 void **xbt_fifo_to_array(xbt_fifo_t f)
338 array = xbt_new0(void *, f->count);
340 for (i = 0, b = xbt_fifo_get_first_item(f); b; i++, b = b->next) {
341 array[i] = b->content;
348 * \return a copy of \a f.
350 xbt_fifo_t xbt_fifo_copy(xbt_fifo_t f)
352 xbt_fifo_t copy = NULL;
355 copy = xbt_fifo_new();
357 for (b = xbt_fifo_get_first_item(f); b; b = b->next) {
358 xbt_fifo_push(copy, b->content);
363 /* Functions passed to the mallocator constructor */
364 static void* fifo_item_mallocator_new_f(void) {
365 return xbt_new(s_xbt_fifo_item_t, 1);
368 static void fifo_item_mallocator_free_f(void* item) {
372 static void fifo_item_mallocator_reset_f(void* item) {
373 /* memset to zero like calloc */
374 memset(item, 0, sizeof(s_xbt_fifo_item_t));
378 * \return a new bucket
380 xbt_fifo_item_t xbt_fifo_new_item(void)
382 return xbt_mallocator_get(item_mallocator);
385 /** \deprecated Use #xbt_fifo_new_item instead.
387 xbt_fifo_item_t xbt_fifo_newitem(void)
389 WARN0("This function is deprecated. Use xbt_fifo_new_item.");
390 return xbt_fifo_new_item();
397 * stores \a v in \a i.
399 void xbt_fifo_set_item_content(xbt_fifo_item_t i , void *v)
401 xbt_fifo_setItemcontent(i,v);
406 * \return the object stored \a i.
408 void *xbt_fifo_get_item_content(xbt_fifo_item_t i)
410 return xbt_fifo_getItemcontent(i);
414 * \param b poor victim
416 * Free the bucket but does not modifies the object (if any) that was stored in it.
418 void xbt_fifo_free_item(xbt_fifo_item_t b)
420 xbt_mallocator_release(item_mallocator, b);
425 * \deprecated Use #xbt_fifo_free_item instead.
427 void xbt_fifo_freeitem(xbt_fifo_item_t b)
429 WARN0("This function is deprecated. Use xbt_fifo_free_item.");
430 xbt_fifo_free_item(b);
436 * \return the number of buckets in \a f.
438 int xbt_fifo_size(xbt_fifo_t f)
445 * \return the head of \a l.
447 xbt_fifo_item_t xbt_fifo_get_first_item(xbt_fifo_t l)
452 /** \deprecated Use #xbt_fifo_get_first_item instead.
454 xbt_fifo_item_t xbt_fifo_getFirstItem(xbt_fifo_t l)
456 WARN0("This function is deprecated. Use xbt_fifo_get_first_item.");
457 return xbt_fifo_get_first_item(l);
462 * \return the bucket that comes next
464 xbt_fifo_item_t xbt_fifo_get_next_item(xbt_fifo_item_t i)
466 if(i) return i->next;
470 /** \deprecated Use #xbt_fifo_get_next_item instead.
472 xbt_fifo_item_t xbt_fifo_getNextItem(xbt_fifo_item_t i)
474 WARN0("This function is deprecated. Use xbt_fifo_get_next_item.");
475 return xbt_fifo_get_next_item(i);
480 * \return the bucket that is just before \a i.
482 xbt_fifo_item_t xbt_fifo_get_prev_item(xbt_fifo_item_t i)
484 if(i) return i->prev;
488 /** \deprecated Use #xbt_fifo_get_prev_item instead.
490 xbt_fifo_item_t xbt_fifo_getPrevItem(xbt_fifo_item_t i)
492 WARN0("This function is deprecated. Use xbt_fifo_get_prev_item.");
493 return xbt_fifo_get_prev_item(i);
497 * Destroy the fifo item mallocator.
498 * This is an internal XBT function called by xbt_exit().
500 void xbt_fifo_exit(void) {
501 if (item_mallocator != NULL) {
502 xbt_mallocator_free(item_mallocator);
503 item_mallocator = NULL;