Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
b9fb24ec833ce5c7bca3735f050ca2c19a708ec5
[simgrid.git] / src / xbt / mmalloc / swag.c
1 /* Copyright (c) 2004-2017. 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
8    cast and dirty things. So avoid using it unless you really know
9    what you are doing. */
10
11 /* This type should be added to a type that is to be used in such a swag */
12
13 #include "swag.h"
14 #include "xbt/asserts.h"
15
16 #define xbt_swag_getPrev(obj, offset) (((xbt_swag_hookup_t)(((char*)(obj)) + (offset)))->prev)
17 #define xbt_swag_getNext(obj, offset) (((xbt_swag_hookup_t)(((char*)(obj)) + (offset)))->next)
18 #define xbt_swag_belongs(obj, swag) (xbt_swag_getNext((obj), (swag)->offset) || (swag)->tail == (obj))
19
20 static inline void *xbt_swag_getFirst(const_xbt_swag_t swag)
21 {
22   return (swag->head);
23 }
24
25 /*
26  * \brief Offset computation
27  * \arg var a variable of type <tt>struct</tt> something
28  * \arg field a field of <tt>struct</tt> something
29  * \return the offset of \a field in <tt>struct</tt> something.
30  * @hideinitializer
31  *
32  * It is very similar to offsetof except that is done at runtime and that you have to declare a variable. Why defining
33  * such a macro then ? Because it is portable...
34  */
35 #define xbt_swag_offset(var, field) ((char*)&((var).field) - (char*)&(var))
36 /* @} */
37
38 /* Creates a new swag.
39  * \param swag the swag to initialize
40  * \param offset where the hookup is located in the structure
41  * \see xbt_swag_offset
42  *
43  * Usage : xbt_swag_init(swag,&obj.setA-&obj);
44  */
45 static inline void xbt_swag_init(xbt_swag_t swag, size_t offset)
46 {
47   swag->tail   = NULL;
48   swag->head   = NULL;
49   swag->offset = offset;
50   swag->count  = 0;
51 }
52
53 /*
54  * \param obj the objet to insert in the swag
55  * \param swag a swag
56  *
57  * insert (at the tail... you probably had a very good reason to do that, I hope you know what you're doing) \a obj in
58  * \a swag
59  */
60 static inline void xbt_swag_insert(void *obj, xbt_swag_t swag)
61 {
62   xbt_assert(!xbt_swag_belongs(obj, swag) || swag->tail,
63              "This object belongs to an empty swag! Did you correctly initialize the object's hookup?");
64
65   if (!swag->head) {
66     xbt_assert(!(swag->tail), "Inconsistent swag.");
67     swag->head = obj;
68     swag->tail = obj;
69     swag->count++;
70   } else if (obj != swag->tail && !xbt_swag_getNext(obj, swag->offset)) {
71     xbt_swag_getPrev(obj, swag->offset)        = swag->tail;
72     xbt_swag_getNext(swag->tail, swag->offset) = obj;
73     swag->tail = obj;
74     swag->count++;
75   }
76 }
77
78 /*
79  * \param obj the objet to remove from the swag
80  * \param swag a swag
81  * \return \a obj if it was in the \a swag and NULL otherwise
82  *
83  * removes \a obj from \a swag
84  */
85 static inline void *xbt_swag_remove(void *obj, xbt_swag_t swag)
86 {
87   if (!obj)
88     return NULL;
89
90   size_t offset = swag->offset;
91   void* prev    = xbt_swag_getPrev(obj, offset);
92   void* next    = xbt_swag_getNext(obj, offset);
93
94   if (prev) {
95     xbt_swag_getNext(prev, offset) = next;
96     xbt_swag_getPrev(obj, offset)  = NULL;
97     if (next) {
98       xbt_swag_getPrev(next, offset) = prev;
99       xbt_swag_getNext(obj, offset)  = NULL;
100     } else {
101       swag->tail = prev;
102     }
103     swag->count--;
104   } else if (next) {
105     xbt_swag_getPrev(next, offset) = NULL;
106     xbt_swag_getNext(obj, offset)  = NULL;
107     swag->head = next;
108     swag->count--;
109   } else if (obj == swag->head) {
110     swag->head = swag->tail = NULL;
111     swag->count--;
112   }
113
114   return obj;
115 }
116
117 /*
118  * \param swag a swag
119  * \return the number of objects in \a swag
120  */
121 static inline int xbt_swag_size(const_xbt_swag_t swag)
122 {
123   return (swag->count);
124 }