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
233 void xbt_fifo_remove(xbt_fifo_t l, void *t)
235 xbt_fifo_item_t current, current_next;
238 for (current = l->head; current; current = current_next) {
239 current_next = current->next;
240 if (current->content != t)
242 /* remove the item */
243 xbt_fifo_remove_item(l, current);
244 xbt_fifo_free_item(current);
245 /* WILL NOT REMOVE DUPLICATES */
253 * \param current a bucket
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...
258 void xbt_fifo_remove_item(xbt_fifo_t l, xbt_fifo_item_t current)
260 if (l->head == l->tail) { /* special case */
261 xbt_assert0((current==l->head),"This item is not in the list!");
265 current->prev = current->next = NULL;
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;
280 current->prev = current->next = NULL;
285 * \param content an object
286 * \return 1 if \a content is in \a f.
288 int xbt_fifo_is_in(xbt_fifo_t f, void *content)
290 xbt_fifo_item_t item = xbt_fifo_get_first_item(f);
292 if (item->content == content)
301 * \return a table with the objects stored in \a f.
303 void **xbt_fifo_to_array(xbt_fifo_t f)
312 array = xbt_new0(void *, f->count);
314 for (i = 0, b = xbt_fifo_get_first_item(f); b; i++, b = b->next) {
315 array[i] = b->content;
322 * \return a copy of \a f.
324 xbt_fifo_t xbt_fifo_copy(xbt_fifo_t f)
326 xbt_fifo_t copy = NULL;
329 copy = xbt_fifo_new();
331 for (b = xbt_fifo_get_first_item(f); b; b = b->next) {
332 xbt_fifo_push(copy, b->content);
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);
342 static void fifo_item_mallocator_free_f(void* item) {
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));
352 * \return a new bucket
354 xbt_fifo_item_t xbt_fifo_new_item(void)
356 return xbt_mallocator_get(item_mallocator);
359 /** \deprecated Use #xbt_fifo_new_item instead.
361 xbt_fifo_item_t xbt_fifo_newitem(void)
363 WARN0("This function is deprecated. Use xbt_fifo_new_item.");
364 return xbt_fifo_new_item();
371 * stores \a v in \a i.
373 void xbt_fifo_set_item_content(xbt_fifo_item_t i , void *v)
375 xbt_fifo_setItemcontent(i,v);
380 * \return the object stored \a i.
382 void *xbt_fifo_get_item_content(xbt_fifo_item_t i)
384 return xbt_fifo_getItemcontent(i);
388 * \param b poor victim
390 * Free the bucket but does not modifies the object (if any) that was stored in it.
392 void xbt_fifo_free_item(xbt_fifo_item_t b)
394 xbt_mallocator_release(item_mallocator, b);
399 * \deprecated Use #xbt_fifo_free_item instead.
401 void xbt_fifo_freeitem(xbt_fifo_item_t b)
403 WARN0("This function is deprecated. Use xbt_fifo_free_item.");
404 xbt_fifo_free_item(b);
410 * \return the number of buckets in \a f.
412 int xbt_fifo_size(xbt_fifo_t f)
419 * \return the head of \a l.
421 xbt_fifo_item_t xbt_fifo_get_first_item(xbt_fifo_t l)
426 /** \deprecated Use #xbt_fifo_get_first_item instead.
428 xbt_fifo_item_t xbt_fifo_getFirstItem(xbt_fifo_t l)
430 WARN0("This function is deprecated. Use xbt_fifo_get_first_item.");
431 return xbt_fifo_get_first_item(l);
436 * \return the bucket that comes next
438 xbt_fifo_item_t xbt_fifo_get_next_item(xbt_fifo_item_t i)
440 if(i) return i->next;
444 /** \deprecated Use #xbt_fifo_get_next_item instead.
446 xbt_fifo_item_t xbt_fifo_getNextItem(xbt_fifo_item_t i)
448 WARN0("This function is deprecated. Use xbt_fifo_get_next_item.");
449 return xbt_fifo_get_next_item(i);
454 * \return the bucket that is just before \a i.
456 xbt_fifo_item_t xbt_fifo_get_prev_item(xbt_fifo_item_t i)
458 if(i) return i->prev;
462 /** \deprecated Use #xbt_fifo_get_prev_item instead.
464 xbt_fifo_item_t xbt_fifo_getPrevItem(xbt_fifo_item_t i)
466 WARN0("This function is deprecated. Use xbt_fifo_get_prev_item.");
467 return xbt_fifo_get_prev_item(i);
471 * Destroy the fifo item mallocator.
472 * This is an internal XBT function called by xbt_exit().
474 void xbt_fifo_exit(void) {
475 if (item_mallocator != NULL) {
476 xbt_mallocator_free(item_mallocator);