P99
p99_callback.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 authors and copyright holders for this work are as follows: */
5 /* (C) copyright 2012-2014 Jens Gustedt, INRIA, France */
6 /* (C) copyright 2012 William Morris */
7 /* */
8 /* This file is free software; it is part of the P99 project. */
9 /* */
10 /* Licensed under the Apache License, Version 2.0 (the "License"); */
11 /* you may not use this file except in compliance with the License. */
12 /* You may obtain a copy of the License at */
13 /* */
14 /* http://www.apache.org/licenses/LICENSE-2.0 */
15 /* */
16 /* Unless required by applicable law or agreed to in writing, software */
17 /* distributed under the License is distributed on an "AS IS" BASIS, */
18 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
19 /* See the License for the specific language governing permissions and */
20 /* limitations under the License. */
21 /* */
22 #ifndef P99_CALLBACK_H
23 #define P99_CALLBACK_H 1
24 
25 # include "p99_lifo.h"
26 
35 #ifndef P00_DOXYGEN
38 #else
39 int p00_doxygen_is_confused(void) {}
43 struct p99_callback_stack { };
45 #endif
46 
51 typedef void p99_callback_void_func(void);
52 
57 typedef void p99_callback_voidptr_func(void*);
58 
61  p99_callback_voidptr_func * p00_voidptr_func;
62  union {
63  p99_callback_void_func * p00_void_func;
64  void* p00_arg;
65  } p00_void;
66 };
67 
68 
71  p99_callback_voidptr_func* p00_voidptr_func,
72  p99_callback_void_func* p00_void_func,
73  void* p00_arg
74  ) {
75  if (p00_obj) {
76  if (p00_voidptr_func)
77  *p00_obj = (p99_callback_el) {
78  .p00_voidptr_func = p00_voidptr_func,
79  .p00_void = {
80  .p00_arg = p00_arg,
81  },
82  };
83  else
84  *p00_obj = (p99_callback_el) { .p00_void = { .p00_void_func = p00_void_func, }, };
85  }
86  return p00_obj;
87 }
88 
89 #define p99_callback_el_init_1(FUNC) \
90 P99_GENERIC((&*FUNC), \
91  , \
92  (p99_callback_voidptr_func*, (p99_callback_voidptr_func*)(FUNC)), \
93  (p99_callback_void_func*, (p99_callback_voidptr_func*)0) \
94  )
95 
96 
97 #define p99_callback_el_init_2(FUNC) \
98 P99_GENERIC((&*FUNC), \
99  , \
100  (p99_callback_void_func*, (p99_callback_void_func*)(FUNC)), \
101  (p99_callback_voidptr_func*, (p99_callback_void_func*)0) \
102  )
103 
104 #define p99_callback_el_init_(OBJ, FUNC, ARG) \
105 p99_callback_el_init((OBJ), p99_callback_el_init_1(FUNC), p99_callback_el_init_2(FUNC), ARG)
106 
107 
108 #define p99_callback_el_init(...) \
109 P99_IF_LT(P99_NARG(__VA_ARGS__), 3) \
110 (p99_callback_el_init_(__VA_ARGS__, 0)) \
111 (p99_callback_el_init_(__VA_ARGS__))
112 
113 
116  if (p00_el.p00_voidptr_func) p00_el.p00_voidptr_func(p00_el.p00_void.p00_arg);
117  else if (p00_el.p00_void.p00_void_func) p00_el.p00_void.p00_void_func();
118 }
119 
121 p99_callback_el* p00_callback_push(p99_callback_stack* p00_l, p99_callback_el* p00_el) {
122  if (p00_el) {
123  P99_LIFO_PUSH(p00_l, p00_el);
124  }
125  return p00_el;
126 }
127 
149 #define P99_CALLBACK_PUSH(STCK, ...) p00_callback_push((STCK), P99_NEW(p99_callback_el, __VA_ARGS__))
150 
151 
172  for (p99_callback_el *head = P99_LIFO_CLEAR(p00_stck), *p00_el = head; p00_el; p00_el = head) {
173  head = p00_el->p99_lifo;
174  p99_callback_el const p00_cb = *p00_el;
175  free(p00_el);
176  p99_callback_el_call(p00_cb);
177  }
178 }
179 
180 
185 #endif
P99_LIFO_PUSH
#define P99_LIFO_PUSH(L, EL)
Push element EL into an atomic LIFO L.
Definition: p99_lifo.h:68
p99_callback_stack::p99_callback_voidptr_func
void p99_callback_voidptr_func(void *)
Function type for a callback with void* argument.
Definition: p99_callback.h:57
p99_callback_el
Definition: p99_callback.h:59
P99_LIFO_DECLARE
#define P99_LIFO_DECLARE(T)
Definition: p99_lifo.h:45
p99_callback_el
struct p99_callback_el p99_callback_el
Definition: p99_callback.h:33
p99_inline
#define p99_inline
Try to force a function always to be inlined.
Definition: p99_compiler.h:496
p99_callback_el_call
void p99_callback_el_call(p99_callback_el const p00_el)
Definition: p99_callback.h:115
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_DECLARE_STRUCT
#define P99_DECLARE_STRUCT(NAME)
forward declaration of a struct NAME
Definition: p99_type.h:59
p99_lifo.h
p99_callback_stack::p99_callback
void p99_callback(p99_callback_stack *p00_stck)
Call all functions that have been registered with p00_stck in reverse order of their registration and...
Definition: p99_callback.h:171
P99_POINTER_TYPE
#define P99_POINTER_TYPE(T)
Declare derived pointer types with endings "_ptr" and "_cptr".
Definition: p99_type.h:132
P99_LIFO
#define P99_LIFO(T)
Definition: p99_lifo.h:42
p99_callback_stack
A data structure to register callbacks.
Definition: p99_callback.h:43
p99_callback_stack::p99_callback_void_func
void p99_callback_void_func(void)
Function type for a callback without arguments.
Definition: p99_callback.h:51
p99_callback_el::p99_lifo
p99_callback_el_ptr p99_lifo
Definition: p99_callback.h:60
p99_callback_stack
struct p99_callback_stack p99_callback_stack
Definition: p99_callback.h:44
p99_callback_el_init
#define p99_callback_el_init(...)
Definition: p99_callback.h:108