P99
p99_lifo.h
Go to the documentation of this file.
1 /* This may look like nonsense, but it really is -*- mode: C; coding: utf-8 -*- */
2 /* */
3 /* Except for parts copied from previous work and as explicitly stated below, */
4 /* the author and copyright holder for this work is */
5 /* (C) copyright 2012-2013 Jens Gustedt, INRIA, France */
6 /* */
7 /* This file is free software; it is part of the P99 project. */
8 /* */
9 /* Licensed under the Apache License, Version 2.0 (the "License"); */
10 /* you may not use this file except in compliance with the License. */
11 /* You may obtain a copy of the License at */
12 /* */
13 /* http://www.apache.org/licenses/LICENSE-2.0 */
14 /* */
15 /* Unless required by applicable law or agreed to in writing, software */
16 /* distributed under the License is distributed on an "AS IS" BASIS, */
17 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
18 /* See the License for the specific language governing permissions and */
19 /* limitations under the License. */
20 /* */
21 #ifndef P99_LIFO_H
22 #define P99_LIFO_H 1
23 
24 #include "p99_enum.h"
25 #include "p99_generic.h"
26 
27 /* Additions by C11 */
28 # if __STDC_VERSION__ < 201100L
29 # include "p99_atomic.h"
30 # endif
31 
32 
38 #if defined(P99_DECLARE_ATOMIC) || P00_DOXYGEN
39 
40 #include "p99_tp.h"
41 
42 # define P99_LIFO(T) P99_TP(T)
43 
44 P00_DOCUMENT_TYPE_ARGUMENT(P99_LIFO_DECLARE, 0)
45 # define P99_LIFO_DECLARE(T) P99_TP_DECLARE(T)
46 # define P99_LIFO_INITIALIZER(VAL) P99_TP_INITIALIZER(VAL)
47 
48 # define p99_lifo_init(EL, VAL) p99_tp_init((EL), (VAL))
49 
56 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_LIFO_TOP, 0)
57 #define P99_LIFO_TOP(L) P99_TP_GET(L)
58 
59 
66 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_LIFO_PUSH, 0)
67 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_LIFO_PUSH, 1)
68 #define P99_LIFO_PUSH(L, EL) \
69 p99_extension \
70 ({ \
71  register const P99_MACRO_VAR(p00_l, (L)); \
72  register P99_TP_TYPE(p00_l)*const p00_rr = (EL); \
73  P99_TP_TYPE_STATE(p00_l) p00_state = P99_TP_STATE_INITIALIZER(p00_l, p00_rr); \
74  do { \
75  p00_rr->p99_lifo = P99_TP_STATE_GET(&p00_state); \
76  } while (!P99_TP_STATE_COMMIT(&p00_state)); \
77 })
78 
119 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_LIFO_POP, 0)
120 #define P99_LIFO_POP(L) \
121 p99_extension \
122 ({ \
123  register const P99_MACRO_VAR(p00_l, (L)); \
124  P99_TP_TYPE_STATE(p00_l) p00_state = P99_TP_STATE_INITIALIZER(p00_l, 0); \
125  /* be sure that the result can not be used as an lvalue */ \
126  register P99_TP_TYPE(p00_l)* p00_r = P99_TP_STATE_GET(&p00_state); \
127  for (; p00_r; p00_r = P99_TP_STATE_GET(&p00_state)) { \
128  P99_TP_STATE_SET(&p00_state, p00_r->p99_lifo); \
129  if (P99_TP_STATE_COMMIT(&p00_state)) \
130  break; \
131  } \
132  if (p00_r) p00_r->p99_lifo = 0; \
133  p00_r; \
134 })
135 
136 #define P00_LIFO_REVERT(L) \
137 p99_extension \
138 ({ \
139  register P99_MACRO_VAR(p00_h, (L)); \
140  register P99_MACRO_VAR(p00_t, P99_PROMOTE_0(p00_h)); \
141  while (p00_h) { \
142  register P99_MACRO_VAR(p00_n, p00_h->p99_lifo); \
143  p00_h->p99_lifo = p00_t; \
144  p00_h = p00_n; \
145  } \
146  /* make sure that the result can not be used as an lvalue */ \
147  register const __typeof__(p00_t = p00_t) p00_r = p00_t; \
148  p00_r; \
149 })
150 
160 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_LIFO_CLEAR, 0)
161 #define P99_LIFO_CLEAR(L) \
162 p99_extension \
163 ({ \
164  register const P99_MACRO_VAR(p00_l, (L)); \
165  P99_TP_TYPE_STATE(p00_l) p00_state = P99_TP_STATE_INITIALIZER(p00_l, 0); \
166  /* be sure that the result can not be used as an lvalue */ \
167  register P99_TP_TYPE(p00_l)* p00_r = P99_TP_STATE_GET(&p00_state); \
168  for (; p00_r; p00_r = P99_TP_STATE_GET(&p00_state)) { \
169  if (P99_TP_STATE_COMMIT(&p00_state)) \
170  break; \
171  } \
172  p00_r; \
173 })
174 
175 #else
176 
177 /* A fall back implementation for the case that there are no atomic
178  operations available */
179 
180 # define P99_LIFO(T) P99_PASTE2(p00_lifo_, T)
181 # define P99_LIFO_DECLARE(T) typedef T P99_LIFO(T)
182 # define P99_LIFO_INITIALIZER(VAL) ((void*)VAL)
183 
184 #define P99_LIFO_TOP(L) (*(L))
185 
186 #define P99_LIFO_PUSH(L, EL) \
187 p99_extension \
188 ({ \
189  P99_MACRO_VAR(p00_l, (L)); \
190  P99_MACRO_VAR(p00_el, (EL)); \
191  p00_el->p99_lifo = *p00_l; \
192  *p00_l = p00_el; \
193 })
194 
195 #define P99_LIFO_POP(L) \
196 p99_extension \
197 ({ \
198  P99_MACRO_VAR(p00_l, (L)); \
199  P99_MACRO_VAR(p00_el, *p00_l); \
200  *p00_l = p00_el->p99_lifo; \
201  if (p00_el) p00_el->p99_lifo = 0; \
202  /* be sure that the result can not be used as an lvalue */ \
203  register __typeof__(p00_el = p00_el) p00_r = p00_el; \
204  p00_r; \
205 })
206 
215 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_LIFO_CLEAR, 0)
216 #define P99_LIFO_CLEAR(L) \
217 ({ \
218  P99_MACRO_VAR(p00_l, (L)); \
219  register P99_MACRO_VAR(p00_ret, *p00_l); \
220  *p00_l = 0; \
221  p00_ret; \
222 })
223 
224 #endif
225 
226 P00_DOCUMENT_TYPE_ARGUMENT(P99_LIFO_TABULATE, 0)
227 P00_DOCUMENT_IDENTIFIER_ARGUMENT(P99_LIFO_TABULATE, 1)
228 P00_DOCUMENT_PERMITTED_ARGUMENT(P99_LIFO_TABULATE, 2)
229 #define P99_LIFO_TABULATE(TYPE, TAB, L) P00_LIFO_TABULATE(TYPE, TAB, P99_UNIQ(TAB), L)
230 
231 #define P00_LIFO_TABULATE(TYPE, TAB, ID, L) \
232 size_t P99_PASTE2(ID, _cnt) = 0; \
233 TYPE * P99_PASTE2(ID, _head) = P99_LIFO_CLEAR(L); \
234 for (TYPE * p00_e = P99_PASTE2(ID, _head); \
235  p00_e; \
236  p00_e = p00_e->p99_lifo) \
237  ++P99_PASTE2(ID, _cnt); \
238 TYPE * TAB[P99_PASTE2(ID, _cnt)]; \
239 for (TYPE ** p00_t = &(TAB[0]), \
240  * p00_e = P99_PASTE2(ID, _head); \
241  p00_e; \
242  p00_e = p00_e->p99_lifo, \
243  ++p00_t) \
244  *p00_t = p00_e
245 
250 #endif
P99_LIFO_PUSH
#define P99_LIFO_PUSH(L, EL)
Push element EL into an atomic LIFO L.
Definition: p99_lifo.h:68
P99_LIFO_DECLARE
#define P99_LIFO_DECLARE(T)
Definition: p99_lifo.h:45
P99_LIFO_TOP
#define P99_LIFO_TOP(L)
Return a pointer to the top element of an atomic LIFO L.
Definition: p99_lifo.h:57
P99_LIFO_CLEAR
#define P99_LIFO_CLEAR(L)
Atomically clear an atomic LIFO L and return a pointer to the start of the list that it previously co...
Definition: p99_lifo.h:161
p99_enum.h
p99_atomic.h
p99_tp.h
P99_LIFO_TABULATE
#define P99_LIFO_TABULATE(TYPE, TAB, L)
Definition: p99_lifo.h:229
P99_LIFO_POP
#define P99_LIFO_POP(L)
Pop the top element from an atomic LIFO L.
Definition: p99_lifo.h:120
p99_generic.h