Logo AND Algorithmique Numérique Distribuée

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