Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Bug fix and add a xbt_swag_foreach_safe where you can remove objects from
[simgrid.git] / src / xbt / swag.c
1 /* Authors: Arnaud Legrand                                                  */
2
3 /* This program is free software; you can redistribute it and/or modify it
4    under the terms of the license (GNU LGPL) which comes with this package. */
5
6 /* Warning, this module is done to be efficient and performs tons of
7    cast and dirty things. So avoid using it unless you really know
8    what you are doing. */
9
10 /* This type should be added to a type that is to be used in such a swag */
11
12 #include "xbt/sysdep.h"
13 #include "xbt/error.h"
14 #include "xbt/swag.h"
15
16 #define PREV(obj,offset) xbt_swag_getPrev(obj,offset)
17 #define NEXT(obj,offset) xbt_swag_getNext(obj,offset)
18
19 /*
20   Usage : xbt_swag_new(&obj.setA-&obj.setA);
21  */
22
23 xbt_swag_t xbt_swag_new(size_t offset)
24 {
25   xbt_swag_t swag = xbt_new0(s_xbt_swag_t, 1);
26
27   swag->offset = offset;
28
29   return swag;
30 }
31
32 void xbt_swag_init(xbt_swag_t swag, size_t offset)
33 {
34   swag->offset = offset;
35 }
36
37 void xbt_swag_insert(void *obj, xbt_swag_t swag)
38 {
39
40   if (xbt_swag_belongs(obj, swag))
41     return;
42
43   (swag->count)++;
44   if (swag->head == NULL) {
45     swag->head = obj;
46     swag->tail = obj;
47     return;
48   }
49
50   PREV(obj, swag->offset) = swag->tail;
51   NEXT(PREV(obj, swag->offset), swag->offset) = obj;
52
53   swag->tail = obj;
54 }
55
56 void *xbt_swag_extract(void *obj, xbt_swag_t swag)
57 {
58   size_t offset = swag->offset;
59
60   if ((!obj) || (!swag))
61     return NULL;
62   if(!xbt_swag_belongs(obj, swag)) /* Trying to remove an object that
63                                       was not in this swag */
64       return NULL;
65
66   if (swag->head == swag->tail) {       /* special case */
67     if (swag->head != obj)      /* Trying to remove an object that was not in this swag */
68       return NULL;
69     swag->head = NULL;
70     swag->tail = NULL;
71   } else if (obj == swag->head) {       /* It's the head */
72     swag->head = NEXT(obj, offset);
73     PREV(swag->head, offset) = NULL;
74     NEXT(obj, offset) = NULL;
75   } else if (obj == swag->tail) {       /* It's the tail */
76     swag->tail = PREV(obj, offset);
77     NEXT(swag->tail, offset) = NULL;
78     PREV(obj, offset) = NULL;
79   } else {                      /* It's in the middle */
80     NEXT(PREV(obj, offset), offset) = NEXT(obj, offset);
81     PREV(NEXT(obj, offset), offset) = PREV(obj, offset);
82     PREV(obj, offset) = NEXT(obj, offset) = NULL;
83   }
84   (swag->count)--;
85   return obj;
86 }
87
88 int xbt_swag_size(xbt_swag_t swag)
89 {
90   return (swag->count);
91 }
92
93 int xbt_swag_belongs(void *obj, xbt_swag_t swag)
94 {
95   return ((NEXT(obj, swag->offset)) || (PREV(obj, swag->offset))
96           || (swag->head == obj));
97 }