Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
for once, %zu->%lu
[simgrid.git] / include / xbt / swag.h
1 /* Copyright (c) 2004-2015. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 /* Warning, this module is done to be efficient and performs tons of cast and dirty things. So avoid using it unless
8  * you really know what you are doing. */
9
10 #ifndef _XBT_SWAG_H
11 #define _XBT_SWAG_H
12
13 #include "xbt/misc.h"
14 #include "xbt/sysdep.h"         /* size_t */
15
16 SG_BEGIN_DECL()
17
18 /** 
19  * @addtogroup XBT_swag
20  * @brief a O(1) set based on linked lists
21  * 
22  *  Warning, this module is done to be efficient and performs tons of cast and dirty things. So make sure you know what
23  *  you are doing while using it.
24  *  It is basically a fifo but with restrictions so that it can be used as a set. Any operation (add, remove, belongs)
25  *  is O(1) and no call to malloc/free is done.
26  *
27  */
28 /** @defgroup XBT_swag_type Swag types
29     @ingroup XBT_swag
30
31     Specific set. 
32
33     These typedefs are public so that the compiler can do his job but believe me, you don't want to try to play with
34     those structs directly. Use them as an abstract datatype.
35 */
36 /* @{ */
37 typedef struct xbt_swag_hookup {
38   void *next;
39   void *prev;
40 } s_xbt_swag_hookup_t;
41 /**< This type should be added to a type that is to be used in a swag. 
42  *
43  *  Whenever a new object with this struct is created, all fields have to be set to NULL
44  *
45  * Here is an example like that :
46
47 \code
48 typedef struct foo {
49   s_xbt_swag_hookup_t set1_hookup;
50   s_xbt_swag_hookup_t set2_hookup;
51
52   double value;
53 } s_foo_t, *foo_t;
54 ...
55 {
56   s_foo_t elem;
57   xbt_swag_t set1=NULL;
58   xbt_swag_t set2=NULL;
59
60   set1 = xbt_swag_new(xbt_swag_offset(elem, set1_hookup));
61   set2 = xbt_swag_new(xbt_swag_offset(elem, set2_hookup));
62
63 }
64 \endcode
65 */
66 typedef s_xbt_swag_hookup_t *xbt_swag_hookup_t;
67
68 typedef struct xbt_swag {
69   void *head;
70   void *tail;
71   size_t offset;
72   int count;
73 } s_xbt_swag_t, *xbt_swag_t;
74 /**< A typical swag */
75 /* @} */
76
77 /** @defgroup XBT_swag_func SWAG functions 
78  *  @ingroup XBT_swag
79  
80  *  @{
81  */
82
83 XBT_PUBLIC(xbt_swag_t) xbt_swag_new(size_t offset);
84 XBT_PUBLIC(void) xbt_swag_free(xbt_swag_t swag);
85 XBT_PUBLIC(void) xbt_swag_init(xbt_swag_t swag, size_t offset);
86
87 /**
88  * \brief Makes a swag empty.
89  * \param swag a swag
90  * @hideinitializer
91  */
92 #define xbt_swag_reset(swag) do {} while(xbt_swag_extract(swag))
93
94 /**
95  * \param obj the objet to insert in the swag
96  * \param swag a swag
97  * @hideinitializer
98  *
99  * insert \a obj in \a swag
100  */
101 #define xbt_swag_insert(obj, swag) xbt_swag_insert_at_tail(obj, swag)
102
103 XBT_PUBLIC(void) xbt_swag_insert_at_head(void *obj, xbt_swag_t swag);
104 XBT_PUBLIC(void) xbt_swag_insert_at_tail(void *obj, xbt_swag_t swag);
105 XBT_PUBLIC(void *) xbt_swag_remove(void *obj, xbt_swag_t swag);
106 XBT_PUBLIC(void *) xbt_swag_extract(xbt_swag_t swag);
107 XBT_PUBLIC(int) xbt_swag_size(xbt_swag_t swag);
108
109 #define xbt_swag_getPrev(obj, offset) (((xbt_swag_hookup_t)(((char *) (obj)) + (offset)))->prev)
110 #define xbt_swag_getNext(obj, offset) (((xbt_swag_hookup_t)(((char *) (obj)) + (offset)))->next)
111 #define xbt_swag_belongs(obj, swag) (xbt_swag_getNext((obj), (swag)->offset) || (swag)->tail == (obj))
112
113 static inline void *xbt_swag_getFirst(xbt_swag_t swag)
114 {
115   return (swag->head);
116 }
117
118 /**
119  * \brief Offset computation
120  * \arg var a variable of type <tt>struct</tt> something
121  * \arg field a field of <tt>struct</tt> something
122  * \return the offset of \a field in <tt>struct</tt> something.
123  * @hideinitializer
124  *
125  * It is very similar to offsetof except that is done at runtime and that you have to declare a variable. Why defining
126  * such a macro then ? Because it is portable...
127  */
128 #define xbt_swag_offset(var,field) ((char *)&( (var).field ) - (char *)&(var))
129 /* @} */
130
131 /**
132  * \defgroup XBT_swag_curs Swag cursor
133  * @ingroup XBT_swag
134
135  * Iterates over the whole swag. 
136  *
137  * @{ */
138
139  /** @brief A simple swag iterator
140   *  @param obj the indice of the loop
141   *  @param swag what to iterate over
142   *  @warning you cannot modify the \a swag while using this loop
143   *  @hideinitializer */
144 #ifndef __cplusplus
145 #define xbt_swag_foreach(obj,swag)                            \
146    for((obj)=xbt_swag_getFirst((swag));                       \
147        (obj)!=NULL;                                           \
148        (obj)=xbt_swag_getNext((obj),(swag)->offset))
149 #else
150 #define xbt_swag_foreach(obj,swag)                            \
151    for((obj)=(decltype(obj)) xbt_swag_getFirst((swag));         \
152        (obj)!=NULL;                                           \
153        (obj)=(decltype(obj)) xbt_swag_getNext((obj),(swag)->offset))
154 #endif
155 /**
156  * @brief A safe swag iterator 
157  * @param obj the indice of the loop
158  * @param obj_next the object that is right after (if any) \a obj in the swag
159  * @param swag what to iterate over
160  * @hideinitializer
161
162     You can safely modify the \a swag while using this loop. 
163     Well, safely... Err. You can remove \a obj without having any trouble at least.  */
164
165 #ifndef __cplusplus
166
167 #define xbt_swag_foreach_safe(obj,obj_next,swag)                  \
168    for((obj)=xbt_swag_getFirst((swag)),                           \
169        ((obj)?(obj_next=xbt_swag_getNext((obj),(swag)->offset)):  \
170            (obj_next=NULL));                                      \
171        (obj)!=NULL;                                               \
172        (obj)=obj_next,                                            \
173        ((obj)?(obj_next=xbt_swag_getNext((obj),(swag)->offset)):  \
174                  (obj_next=NULL))     )
175
176 #else
177
178 #define xbt_swag_foreach_safe(obj,obj_next,swag)                  \
179    for((obj) = (decltype(obj)) xbt_swag_getFirst((swag)),         \
180        ((obj)?(obj_next = (decltype(obj)) xbt_swag_getNext((obj),(swag)->offset)):  \
181            (obj_next=NULL));                                      \
182        (obj) != NULL;                                             \
183        (obj) = obj_next,                           \
184        ((obj)?(obj_next = (decltype(obj)) xbt_swag_getNext((obj),(swag)->offset)):  \
185                  (obj_next=NULL))     )
186
187 #endif
188
189 /* @} */
190
191 SG_END_DECL()
192
193 #ifdef __cplusplus
194 namespace simgrid {
195 namespace xbt {
196   inline void destroy(xbt_swag_t s)
197   {
198     xbt_swag_free(s);
199   }
200 }
201 }
202 #endif
203
204 #endif                          /* _XBT_SWAG_H */