file: ring.h
1
/*
2
* Copyright (C) 2008-2009 by Emmanuel Azencot under the GNU LGPL
3
* license version 2.0 or 2.1. You should have received a copy of the
4
* LGPL license along with this library if you did not you can find it
5
* at http://www.gnu.org/.
6
*/
7
/*
8
* Azencot : Wed Nov 12 21:45:57 CET 2008
9
* Creation
10
* Azencot : Tue Nov 18 21:31:30 CET 2008
11
* Add doc++ comments
12
* Azencot : Sat Dec 13 00:20:02 CET 2008
13
* f_ring_off_xxx -> f_ring_xxx
14
*/
15
#ifndef _RING_H_ /* [ */
16
#define /*X*/ _RING_H_
17
18
#include <stddef.h> /* offsetof */
19
#include <stdbool.h>
20
21
/**@name Structures
22
* @doc
23
* The easiest way to use rings is to include a ring structure in your C object
24
* structure :
25
* <pre>
26
struct s_your_object {
27
type member;
28
...
29
struct s_ring sibling;
30
type member;
31
....
32
};</pre>
33
* The set of macros use the ring structure member name to find the offset of
34
* the ring structure in yours.
35
* These macros try to keep type informations as far as possible for the compiler
36
* to be able to check them.
37
*/
38
//@{
39
/** @memo The ring structure
40
* @doc
41
* You must include in your own structure at the same offset, for all nodes
42
* of the same ring.
43
* It is recommended to include the ring structure directly in the node one.
44
* The macros need a member reference to find the ring part.
45
*/
46
struct /*X*/ s_ring { struct /*X*/ s_ring *next; };
47
/** @memo double linked object
48
* @doc
49
* These kind of rings provides 2 extar methodes : previous and move..
50
*/
51
struct /*X*/ s_dring { struct /*X*/ s_dring *next; struct /*X*/ s_dring *prev; };
52
/** @memo Include this structure for named object
53
* @doc
54
* The node name is a null terminated string pointer. Caller is responsible
55
* of memory management for the name.
56
* Name must be less than 1000 characters.
57
*/
58
struct /*X*/ s_nring { struct /*X*/ s_nring *next; const char *name; };
59
/** @memo Double linked named object
60
* @doc
61
* The node name is a null terminated string pointer. Caller is responsible
62
* of memory management for the name.
63
* Name must be less than 1000 characters.
64
*/
65
struct /*X*/ s_ndring { struct /*X*/ s_ndring *next; struct /*X*/ s_ndring *prev; char *name; };
66
//@}
67
/**@name Selftest (macro)
68
* @memo The ring integrity routine.
69
* @doc
70
* These macros call the same routine that is it used when check_opt is set.
71
* Feel free to call it in case you have disabled this check.
72
* @param p_ring (IN) A holding pointer to a node's ring
73
* @param field (IN) Field member name of ring structure
74
* @return 0 is failled
75
* @exception EMLINK null pointer found in ring link.
76
*/
77
//@{
78
/// ring
79
#define /*X*/ m_ring_selftest(p_ring, field) ( \
80
(typeof(p_ring))f_ring_selftest(&((p_ring)->field), offsetof(typeof(*(p_ring)), field) ) )
81
/// nring
82
#define /*X*/ m_nring_selftest(p_ring, field) ( \
83
(typeof(p_ring))f_nring_selftest(&((p_ring)->field), offsetof(typeof(*(p_ring)), field) ) )
84
/// dring
85
#define /*X*/ m_dring_selftest(p_ring, field) ( \
86
(typeof(p_ring))f_dring_selftest(&((p_ring)->field), offsetof(typeof(*(p_ring)), field) ) )
87
/// ndring
88
#define /*X*/ m_ndring_selftest(p_ring, field) ( \
89
(typeof(p_ring))f_ndring_selftest(&((p_ring)->field), offsetof(typeof(*(p_ring)), field) ) )
90
//@}
91
/**@name Test node is in a ring (macro)
92
* @memo Is this node in the this ring ?.
93
* @doc
94
* Lost your ring ? Just try all you have with this method.
95
* + missing macro.
96
* @param is (IN) this node is
97
* @param in (IN) this ring
98
* @return 0 if not
99
* @exception EFAULT is is nil.
100
* @exception EMLINK null pointer found in ring link.
101
*/
102
//@{
103
/// ring
104
#define /*X*/ m_ring_is_in(is, in, field) (f_ring_is_in(&((is)->field), &((in)->field), offsetof(typeof(*(in)), field) ) )
105
/// nring
106
#define /*X*/ m_nring_is_in(is, in, field) (f_nring_is_in(&((is)->field), &((in)->field), offsetof(typeof(*(in)), field) ) )
107
/// dring
108
#define /*X*/ m_dring_is_in(is, in, field) (f_dring_is_in(&((is)->field), &((in)->field), offsetof(typeof(*(in)), field) ) )
109
/// ndring
110
#define /*X*/ m_ndring_is_in(is, in, field) (f_ndring_is_in(&((is)->field), &((in)->field), offsetof(typeof(*(in)), field) ) )
111
//@}
112
/**@name Link (macro)
113
* @memo Hold a new node in the ring.
114
* @doc
115
* if ring reference is nul, the operation succed. To avoid side effect on empty rings,
116
* always set the ring holding pointer with the result of the call :
117
* <pre>ring_ptr = m_ring_link(ring_ptr, field, node);</pre>
118
* @param p_ring (IN) a pointer to your structure node
119
* @param field (IN) the ring structure field name in the node structure.
120
* @param node (IN) the node
121
* @return node in the now in ring.
122
* @exception ENOTNAM, Name is nil (nring, ndring).
123
* @exception ENAMETOOLONG, Name is too long (nring, ndring).
124
* @exception EEXIST, node is already in ring.
125
* @exception EFAULT node is nil.
126
* @exception EMLINK null pointer found in ring link.
127
*/
128
//@{
129
/// ring
130
#define /*X*/ m_ring_link(p_ring, field, node) ( (typeof(p_ring))f_ring_link(&((p_ring)->field), &((node)->field), offsetof(typeof(*(p_ring)), field) ) )
131
/// nring
132
#define /*X*/ m_nring_link(p_ring, field, node) ( (typeof(p_ring))f_nring_link(&((p_ring)->field), &((node)->field), offsetof(typeof(*(p_ring)), field) ) )
133
/// dring
134
#define /*X*/ m_dring_link(p_ring, field, node) ( (typeof(p_ring))f_dring_link(&((p_ring)->field), &((node)->field), offsetof(typeof(*(p_ring)), field) ) )
135
/// ndring
136
#define /*X*/ m_ndring_link(p_ring, field, node) ( (typeof(p_ring))f_ndring_link(&((p_ring)->field), &((node)->field), offsetof(typeof(*(p_ring)), field) ) )
137
//@}
138
/**@name Unlink (macro)
139
* @memo Remove reference from this node.
140
* @doc
141
* Because the holding pointer may reference the unlinked node, always set the ring
142
* holding pointer with the result of the call :
143
* <pre>ring_ptr = m_ring_unlink(node, field);</pre>
144
* It is highly recomanded to ensure that the node belongs to ring_ptr before calling
145
* the macro.
146
* @param p_ring (IN) The node you want to unlink.
147
* @param field (IN) the ring structure field name in the node structure.
148
* @return 0 the ring is empty, or the next node in the ring.
149
* @exception EMLINK null pointer found in ring link.
150
*/
151
//@{
152
/// ring
153
#define /*X*/ m_ring_unlink(p_ring, field) ( (typeof(p_ring))f_ring_unlink(&((p_ring)->field), offsetof(typeof(*(p_ring)), field) ) )
154
/// nring
155
#define /*X*/ m_nring_unlink(p_ring, field) ( (typeof(p_ring))f_nring_unlink(&((p_ring)->field), offsetof(typeof(*(p_ring)), field) ) )
156
/// dring
157
#define /*X*/ m_dring_unlink(p_ring, field) ( (typeof(p_ring))f_dring_unlink(&((p_ring)->field), offsetof(typeof(*(p_ring)), field) ) )
158
/// ndring
159
#define /*X*/ m_ndring_unlink(p_ring, field) ( (typeof(p_ring))f_ndring_unlink(&((p_ring)->field), offsetof(typeof(*(p_ring)), field) ) )
160
//@}
161
162
/**@name Next (macro)
163
* @memo the next node.
164
* @doc
165
* The macro expand as the next node of a node, allowing you to jump each node.
166
* Note that you have to provide a stop condition yourself when you loop around the ring.
167
* @param p_ring (IN) a pointer to structure node
168
* @param field (IN) the ring structure field name in the node structure.
169
* @return 0 the ring is empty, or the next node in the ring.
170
*/
171
//@{
172
/// ring
173
#define /*X*/ m_ring_next(p_ring, field) ((typeof(p_ring))((p_ring)?((char *)((p_ring)->field.next) - offsetof(typeof(*(p_ring)), field) ) :0))
174
/// nring
175
#define /*X*/ m_nring_next(p_ring, field) ((typeof(p_ring))((p_ring)?((char *)((p_ring)->field.next) - offsetof(typeof(*(p_ring)), field) ) :0))
176
/// dring
177
#define /*X*/ m_dring_next(p_ring, field) ((typeof(p_ring))((p_ring)?((char *)((p_ring)->field.next) - offsetof(typeof(*(p_ring)), field) ) :0))
178
/// ndring
179
#define /*X*/ m_ndring_next(p_ring, field) ((typeof(p_ring))((p_ring)?((char *)((p_ring)->field.next) - offsetof(typeof(*(p_ring)), field) ) :0))
180
//@}
181
182
/**@name List (macro)
183
* @memo the next node, with loop detection.
184
* @doc
185
* The macro expand as the next node of a node, allowing you to jump each node.
186
* If next node is ring parameter, it returns 0. This macro is switable for loops :
187
*
188
* for (node = ring; !node; node = m_ring_list(list, node, brother) ) { ... }
189
*
190
* @param p_ring (IN) a pointer to structure node
191
* @param field (IN) the ring structure field name in the node structure.
192
* @return 0 the ring is empty, or the next node in the ring.
193
*/
194
//@{
195
/// ring
196
#define /*X*/ m_ring_list(ring, node, field) ( (((node) = m_ring_next(node, field)) == (ring))?0:(node) )
197
/// nring
198
#define /*X*/ m_nring_list(ring, node, field) ( (((node) = m_nring_next(node, field)) == (ring))?0:(node) )
199
/// dring
200
#define /*X*/ m_dring_list(ring, node, field) ( (((node) = m_dring_next(node, field)) == (ring))?0:(node) )
201
/// ndring
202
#define /*X*/ m_ndring_list(ring, node, field) ( (((node) = m_ndring_next(node, field)) == (ring))?0:(node) )
203
//@}
204
/**@name Do, done (macro)
205
* @memo A loop macro construction helper.
206
* @doc
207
* These to macros construct begin and end of loops to evry node in a ring :
208
* <pre>m_ring_do(ring, node) ++i; m_ring_done(ring, node, field);</pre>
209
* count how many node there is in the ring.
210
* @param ring (IN) a pointer the ring ring
211
* @param var (IN) a variable pointer node beeing listed.
212
* @param field (IN) the ring structure field name in the node structure.
213
* @return 0 the ring is empty, or the next node in the ring.
214
*/
215
//@{
216
/// ring, start loop
217
#define /*X*/ m_ring_do(ring, var) if ( ((var) = (ring)) ) do
218
/// ring, end loop
219
#define /*X*/ m_ring_done(ring, var, field) while ( (var) = m_ring_next((var), field), (var) != (ring) )
220
/// nring, start loop
221
#define /*X*/ m_nring_do(ring, var) if ( ((var) = (ring)) ) do
222
/// nring, end loop
223
#define /*X*/ m_nring_done(ring, var, field) while ( (var) = m_nring_next((var), field), (var) != (ring) )
224
/// dring, start loop
225
#define /*X*/ m_dring_do(ring, var) if ( ((var) = (ring)) ) do
226
/// dring, end loop
227
#define /*X*/ m_dring_done(ring, var, field) while ( (var) = m_dring_next((var), field), (var) != (ring) )
228
/// ndring, start loop
229
#define /*X*/ m_ndring_do(ring, var) if ( ((var) = (ring)) ) do
230
/// ndring, end loop
231
#define /*X*/ m_ndring_done(ring, var, field) while ( (var) = m_ndring_next((var), field), (var) != (ring) )
232
//@}
233
/**@name Find by name (macro)
234
* @memo For named ring, find a node with his name.
235
* @doc
236
* @param p_ring (IN) a pointer to your structure node
237
* @param field (IN) the ring structure field name in the node structure.
238
* @param name (IN) the node name.
239
* @return 0 the name is not found, the node if it is.
240
* @exception EMLINK null pointer found in ring link.
241
*/
242
//@{
243
/// nring
244
#define /*X*/ m_nring_find(p_ring, field, name) ( \
245
(typeof(p_ring))f_nring_find(&((p_ring)->field), (name), offsetof(typeof(*(p_ring)), field) ) )
246
/// ndring
247
#define /*X*/ m_ndring_find(p_ring, field, name) ( \
248
(typeof(p_ring))f_ndring_find(&((p_ring)->field), (name), offsetof(typeof(*(p_ring)), field) ) )
249
//@}
250
/**@name Previous (macro)
251
* @memo For double ring, expand to previous node.
252
* @doc
253
* @param p_ring (IN) a pointer to your structure node
254
* @param field (IN) the ring structure field name in the node structure.
255
* @return 0 the ring is empty, or the previous node in the ring.
256
*/
257
//@{
258
/// dring
259
#define /*X*/ m_dring_prev(p_ring, field) ((typeof(p_ring))((p_ring)?((char *)((p_ring)->field.prev) - offsetof(typeof(*(p_ring)), field) ) :0))
260
/// ndring
261
#define /*X*/ m_ndring_prev(p_ring, field) ((typeof(p_ring))((p_ring)?((char *)((p_ring)->field.prev) - offsetof(typeof(*(p_ring)), field) ) :0))
262
//@}
263
/**@name Move (macro)
264
* @memo For double ring,jump n nodes back or force.
265
* @doc
266
* @param p_ring (IN) a pointer to your structure node
267
* @param hops (IN) Number of jumps.
268
* @param check (IN) if true, a loop detection.
269
* @param field (IN) the ring structure field name in the node structure.
270
* @return 0 the ring is empty, or the previous node in the ring.
271
* @exception ELOOP Move made a complete loop
272
* @exception EMLINK null pointer found in ring link.
273
*/
274
//@{
275
/// nring
276
#define /*X*/ m_dring_move(p_ring, hops, check, field) ( \
277
(typeof(p_ring))f_dring_move(&((p_ring)->field), hops, check, offsetof(typeof(*(p_ring)), field) ) )
278
/// ndring
279
#define /*X*/ m_ndring_move(p_ring, hops, check, field) ( \
280
(typeof(p_ring))f_ndring_move(&((p_ring)->field), hops, check, offsetof(typeof(*(p_ring)), field) ) )
281
//@}
282
/**@name Errors
283
* @doc
284
* When an error is detected, errno is used to give a minimal feed back. Errno values
285
* are given in each macro and function in there respectives manual entries at
286
* paragraphs "throws".
287
* It is possible to customise error signaling by rewriting raise and relay macros
288
* in "config.h" file. This way, you could get textual reason.
289
* See \URL[exception_stderr.h]{./src/exception_stderr.h.html}
290
* or \URL[exception_errno.h]{./src/exception_errno.h.html} for examples.
291
* @exception ELOOP Move made a complete loop (dring, ndring)
292
* @exception ENOTNAM Name is nil (nring, ndring).
293
* @exception ENAMETOOLONG Name is too long (nring, ndring).
294
* @exception EEXIST node is already in ring.
295
* @exception EMLINK null pointer found in ring link.
296
* @exception EFAULT node is nil.
297
*/
298
//@{
299
//@}
300
/**@name Maintenance
301
*/
302
//@{
303
/** @memo Set or get the check bit control on
304
* @doc
305
* When check is on, the linkage integrity is checked each time a member
306
* function is called.
307
* To get the curent check level, call with level at -1.
308
* @param level (IN) Only two levels : 0 or 1. -1 for read.
309
* @return curent check level.
310
*/
311
int f_ring_check_opt(int level);
312
//@}
313
/**@name C API
314
* @memo The C fonctions set that implement rings
315
* @doc
316
* The C API is less "friend user" than macros because more code have to be writen
317
* to call them properly.
318
* In some situations where no member name can be provided to the macros for the ring
319
* datas they may be usefull.
320
* See \Ref{Implementation}
321
*/
322
//@{
323
bool f_ring_selftest(struct s_ring *ring, size_t offset);
324
bool f_dring_selftest(struct s_dring *ring, size_t offset);
325
bool f_nring_selftest(struct s_nring *ring, size_t offset);
326
bool f_ndring_selftest(struct s_ndring *ring, size_t offset);
327
328
bool f_ring_is_in(struct s_ring *is, struct s_ring *in, size_t offset);
329
bool f_nring_is_in(struct s_nring *is, struct s_nring *in, size_t offset);
330
bool f_dring_is_in(struct s_dring *is, struct s_dring *in, size_t offset);
331
bool f_ndring_is_in(struct s_ndring *is, struct s_ndring *in, size_t offset);
332
333
void *f_ring_unlink(struct s_ring *node, size_t offset);
334
void *f_nring_unlink(struct s_nring *node, size_t offset);
335
void *f_dring_unlink(struct s_dring *node, size_t offset);
336
void *f_ndring_unlink(struct s_ndring *node, size_t offset);
337
338
void *f_ring_link(struct s_ring *ring, struct s_ring *_new, size_t offset);
339
void *f_nring_link(struct s_nring *ring, struct s_nring *_new, size_t offset);
340
void *f_dring_link(struct s_dring *ring, struct s_dring *_new, size_t offset);
341
void *f_ndring_link(struct s_ndring *ring, struct s_ndring *_new, size_t offset);
342
343
void *f_nring_find(struct s_nring *ring, const char *name, size_t offset);
344
void *f_ndring_find(struct s_ndring *ring, const char *name, size_t offset);
345
346
void *f_dring_move(struct s_dring *ring, int hops, bool check, size_t offset);
347
void *f_ndring_move(struct s_ndring *ring, int hops, bool check, size_t offset);
348
//@}
349
350
/*
351
struct s_ring *f_ring_next(struct s_ring *node);
352
struct s_ring *f_ring_link(struct s_ring *ring, struct s_ring *node);
353
struct s_ring *f_ring_unlink(struct s_ring *node);
354
355
struct s_nring *f_nring_next(struct s_nring *ring);
356
struct s_nring *f_nring_link(struct s_nring *ring, struct s_nring *new);
357
struct s_nring *f_nring_unlink(struct s_nring *node);
358
struct s_nring *f_nring_find(struct s_nring *ring, const char *name);
359
360
struct s_dring *f_dring_next(struct s_dring *ring);
361
struct s_dring *f_dring_prev(struct s_dring *ring);
362
struct s_dring *f_dring_move(struct s_dring *ring, int hops, bool check);
363
364
struct s_dring *f_dring_link(struct s_dring *ring, struct s_dring *new);
365
struct s_dring *f_dring_unlink(struct s_dring *node);
366
** @memo Internal, expand to the ring structure adresse of a node.
367
* @doc
368
* The macro expand as the next node of a node, allowing you to jump each node.
369
* Note that you have to provide a stop condition yourself when you loop around the ring.
370
* @param p_ring (IN) a pointer to structure node
371
* @param field (IN) the ring structure field name in the node structure.
372
* @return 0 the ring is empty, or the next node in the ring.
373
*
374
#define /*X*/ m_ring_to_container(p_ring, field) ((typeof(p_ring))((p_ring)?((char *)(p_ring) - offsetof(typeof(*(p_ring)), field) ) :0))
375
376
377
*/
378
379
#endif /* ] _RING_H_ */
C to HTML Conversion by ctoohtml