Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
These modules does not use logging anymore now that asserts dont
[simgrid.git] / src / xbt / swag.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 /* Warning, this module is done to be efficient and performs tons of
9    cast and dirty things. So avoid using it unless you really know
10    what you are doing. */
11
12 /* This type should be added to a type that is to be used in such a swag */
13
14 #include "xbt/sysdep.h"
15 #include "xbt/log.h"
16 #include "xbt/swag.h"
17
18 #define PREV(obj,offset) xbt_swag_getPrev(obj,offset)
19 #define NEXT(obj,offset) xbt_swag_getNext(obj,offset)
20
21
22 /** Creates a new swag.
23  * \param offset where the hookup is located in the structure
24  * \see xbt_swag_offset
25  *
26  * Usage : xbt_swag_new(&obj.setA-&obj); 
27  */
28 xbt_swag_t xbt_swag_new(size_t offset)
29 {
30   xbt_swag_t swag = xbt_new0(s_xbt_swag_t, 1);
31
32   swag->tail = NULL;
33   swag->head = NULL;
34   swag->offset = offset;
35   swag->count = 0;
36
37   return swag;
38 }
39
40 /** 
41  * \param swag poor victim
42  * 
43  * kilkil a swag but not it's content. If you do not understand why
44  * xbt_swag_free should not free its content, don't use swags.
45  */
46 void xbt_swag_free(xbt_swag_t swag)
47 {
48   free(swag);
49 }
50
51 /** Creates a new swag.
52  * \param swag the swag to initialize
53  * \param offset where the hookup is located in the structure
54  * \see xbt_swag_offset
55  *
56  * Usage : xbt_swag_init(swag,&obj.setA-&obj); 
57  */
58 void xbt_swag_init(xbt_swag_t swag, size_t offset)
59 {
60   swag->tail = NULL;
61   swag->head = NULL;
62   swag->offset = offset;
63   swag->count = 0;
64 }
65
66
67 /** 
68  * \param obj the objet to insert in the swag
69  * \param swag a swag
70  *
71  * insert \a obj in \a swag
72  */
73 void xbt_swag_insert(void *obj, xbt_swag_t swag)
74 {
75
76   if (xbt_swag_belongs(obj, swag))
77     return;
78
79   (swag->count)++;
80   if (swag->head == NULL) {
81     xbt_assert0(!(swag->tail), "Inconsistent swag.");
82     swag->head = obj;
83     swag->tail = obj;
84     return;
85   }
86
87   PREV(obj, swag->offset) = swag->tail;
88   NEXT(PREV(obj, swag->offset), swag->offset) = obj;
89
90   swag->tail = obj;
91 }
92
93 /** 
94  * \param obj the objet to insert in the swag
95  * \param swag a swag
96  *
97  * insert (at the head... you probably had a very good reason to do
98  * that, I hope you know what you're doing) \a obj in \a swag
99  */
100 void xbt_swag_insert_at_head(void *obj, xbt_swag_t swag)
101 {
102
103   if (xbt_swag_belongs(obj, swag))
104     return;
105
106   (swag->count)++;
107   if (swag->head == NULL) {
108     xbt_assert0(!(swag->tail), "Inconsistent swag.");
109     swag->head = obj;
110     swag->tail = obj;
111     return;
112   }
113
114   NEXT(obj, swag->offset) = swag->head;
115   PREV(NEXT(obj, swag->offset), swag->offset) = obj;
116
117   swag->head = obj;
118 }
119
120 /** 
121  * \param obj the objet to insert in the swag
122  * \param swag a swag
123  *
124  * insert (at the tail... you probably had a very good reason to do
125  * that, I hope you know what you're doing) \a obj in \a swag
126  */
127 void xbt_swag_insert_at_tail(void *obj, xbt_swag_t swag)
128 {
129
130   if (xbt_swag_belongs(obj, swag))
131     return;
132
133   (swag->count)++;
134   if (swag->head == NULL) {
135     xbt_assert0(!(swag->tail), "Inconsistent swag.");
136     swag->head = obj;
137     swag->tail = obj;
138     return;
139   }
140
141   PREV(obj, swag->offset) = swag->tail;
142   NEXT(PREV(obj, swag->offset), swag->offset) = obj;
143
144   swag->tail = obj;
145 }
146
147 /** 
148  * \param obj the objet to remove from the swag
149  * \param swag a swag
150  * \return \a obj if it was in the \a swag and NULL otherwise
151  *
152  * removes \a obj from \a swag
153  */
154 void *xbt_swag_remove(void *obj, xbt_swag_t swag)
155 {
156   size_t offset = swag->offset;
157
158   if ((!obj) || (!swag))
159     return NULL;
160   if(!xbt_swag_belongs(obj, swag)) /* Trying to remove an object that
161                                       was not in this swag */
162       return NULL;
163
164   if (swag->head == swag->tail) {       /* special case */
165     if (swag->head != obj)      /* Trying to remove an object that was not in this swag */
166       return NULL;
167     swag->head = NULL;
168     swag->tail = NULL;
169     NEXT(obj, offset) = PREV(obj, offset) = NULL;
170   } else if (obj == swag->head) {       /* It's the head */
171     swag->head = NEXT(obj, offset);
172     PREV(swag->head, offset) = NULL;
173     NEXT(obj, offset) = NULL;
174   } else if (obj == swag->tail) {       /* It's the tail */
175     swag->tail = PREV(obj, offset);
176     NEXT(swag->tail, offset) = NULL;
177     PREV(obj, offset) = NULL;
178   } else {                      /* It's in the middle */
179     NEXT(PREV(obj, offset), offset) = NEXT(obj, offset);
180     PREV(NEXT(obj, offset), offset) = PREV(obj, offset);
181     PREV(obj, offset) = NEXT(obj, offset) = NULL;
182   }
183   (swag->count)--;
184   return obj;
185 }
186
187 /** 
188  * \param swag a swag
189  * \return an object from the \a swag
190  */
191 void *xbt_swag_extract(xbt_swag_t swag)
192 {
193   size_t offset = swag->offset;
194   void *obj = NULL;
195
196   if ((!swag) || (!(swag->head)))
197     return NULL;
198
199   obj = swag->head;
200
201   if (swag->head == swag->tail) {       /* special case */
202     swag->head = swag->tail = NULL;
203     PREV(obj, offset) = NEXT(obj, offset) = NULL;
204   } else {
205     swag->head = NEXT(obj, offset);
206     PREV(swag->head, offset) = NULL;
207     NEXT(obj, offset) = NULL;
208   }
209   (swag->count)--;
210
211   return obj;
212 }
213 /** 
214  * \param swag a swag
215  * \return the number of objects in \a swag
216  */
217 int xbt_swag_size(xbt_swag_t swag)
218 {
219   return (swag->count);
220 }
221
222 /** 
223  * \param obj an object
224  * \param swag a swag
225  * \return 1 if \a obj is in the \a swag and 0 otherwise
226  */
227 int xbt_swag_belongs(void *obj, xbt_swag_t swag)
228 {
229   return ((NEXT(obj, swag->offset)) || (PREV(obj, swag->offset))
230           || (swag->head == obj));
231 }