1
1
#include "events.h"
2
2
3
3
#include <stdlib.h>
4
- #include <stddef .h>
4
+ #include <string .h>
5
5
6
6
7
- // internal callback callback
8
- struct ecallback {
9
- void (* cb )(void * );
10
- void * data ;
11
- };
12
-
13
- static void ecallback_dispatch (void * p ) {
14
- struct ecallback * e = (struct ecallback * )p ;
15
- e -> cb (e -> data );
16
- }
17
-
18
- // equeue functions
19
- static inline struct event * equeue_event (struct equeue * q , unsigned i ) {
20
- return (struct event * )((char * )q -> buffer + i * q -> size );
21
- }
22
-
23
- static inline unsigned equeue_size (unsigned size ) {
24
- if (size < sizeof (struct ecallback )) {
25
- size = sizeof (struct ecallback );
26
- }
27
-
28
- unsigned alignment = offsetof(struct { char c ; struct event e ; }, e );
29
- size += sizeof (struct event );
30
- return (size + alignment - 1 ) & ~(alignment - 1 );
31
- }
32
-
33
- int equeue_create (struct equeue * q , unsigned count , unsigned size ) {
34
- void * buffer = malloc (count * equeue_size (size ));
7
+ int equeue_create (struct equeue * q , unsigned size ) {
8
+ void * buffer = malloc (size );
35
9
if (!buffer ) {
36
10
return -1 ;
37
11
}
38
12
39
- return equeue_create_inplace (q , count , size , buffer );
13
+ int err = equeue_create_inplace (q , size , buffer );
14
+ q -> buffer = buffer ;
15
+ return err ;
40
16
}
41
17
42
- int equeue_create_inplace (struct equeue * q ,
43
- unsigned count , unsigned size , void * buffer ) {
44
- q -> size = equeue_size (size );
45
- q -> buffer = buffer ;
46
- q -> free = (struct event * )buffer ;
18
+ int equeue_create_inplace (struct equeue * q , unsigned size , void * buffer ) {
19
+ q -> slab .size = size ;
20
+ q -> slab .data = buffer ;
21
+ q -> chunks = 0 ;
22
+ q -> buffer = 0 ;
23
+
47
24
q -> queue = 0 ;
48
25
q -> next_id = 42 ;
49
26
q -> break_ = (struct event ){
50
27
.id = 0 ,
51
28
.period = -1 ,
52
29
};
53
30
54
- if (q -> free ) {
55
- for (unsigned i = 0 ; i < count - 1 ; i ++ ) {
56
- equeue_event (q , i )-> next = equeue_event (q , i + 1 );
57
- }
58
- equeue_event (q , count - 1 )-> next = 0 ;
59
- }
60
-
61
31
int err ;
62
32
err = events_sema_create (& q -> eventsema );
63
33
if (err < 0 ) {
@@ -84,56 +54,108 @@ void equeue_destroy(struct equeue *q) {
84
54
free (q -> buffer );
85
55
}
86
56
87
- // equeue mem functions
88
- static int equeue_next_id (struct equeue * q ) {
57
+ // equeue allocation functions
58
+ static void * equeue_alloc (struct equeue * q , unsigned size ) {
59
+ size = size + sizeof (unsigned );
60
+ size = (size + sizeof (unsigned )-1 ) & ~(sizeof (unsigned )-1 );
61
+ if (size < sizeof (struct equeue_chunk )) {
62
+ size = sizeof (struct equeue_chunk );
63
+ }
64
+
65
+ events_mutex_lock (& q -> freelock );
66
+
67
+ for (struct equeue_chunk * * p = & q -> chunks ; * p ; p = & (* p )-> nchunk ) {
68
+ if ((* p )-> size >= size ) {
69
+ struct equeue_chunk * c = * p ;
70
+ if (c -> next ) {
71
+ * p = c -> next ;
72
+ (* p )-> nchunk = c -> nchunk ;
73
+ } else {
74
+ * p = c -> nchunk ;
75
+ }
76
+ events_mutex_unlock (& q -> freelock );
77
+ return (unsigned * )c + 1 ;
78
+ }
79
+ }
80
+
81
+ if (q -> slab .size >= size ) {
82
+ struct equeue_chunk * c = (struct equeue_chunk * )q -> slab .data ;
83
+ q -> slab .data += size ;
84
+ q -> slab .size -= size ;
85
+ c -> size = size ;
86
+ events_mutex_unlock (& q -> freelock );
87
+ return (unsigned * )c + 1 ;
88
+ }
89
+
90
+ events_mutex_unlock (& q -> freelock );
91
+ return 0 ;
92
+ }
93
+
94
+ static void equeue_dealloc (struct equeue * q , void * e ) {
95
+ struct equeue_chunk * c = (struct equeue_chunk * )((unsigned * )e - 1 );
96
+
97
+ events_mutex_lock (& q -> freelock );
98
+
99
+ struct equeue_chunk * * p = & q -> chunks ;
100
+ while (* p && (* p )-> size < c -> size ) {
101
+ p = & (* p )-> nchunk ;
102
+ }
103
+
104
+ if (* p && (* p )-> size == c -> size ) {
105
+ c -> next = * p ;
106
+ c -> nchunk = (* p )-> nchunk ;
107
+ } else {
108
+ c -> next = 0 ;
109
+ c -> nchunk = * p ;
110
+ }
111
+ * p = c ;
112
+
113
+ events_mutex_unlock (& q -> freelock );
114
+ }
115
+
116
+ // event allocation functions
117
+ static inline int event_next_id (struct equeue * q ) {
89
118
int id = q -> next_id ++ ;
90
119
if (q -> next_id < 0 ) {
91
120
q -> next_id = 42 ;
92
121
}
93
122
return id ;
94
123
}
95
124
96
- static struct event * equeue_alloc (struct equeue * q ) {
97
- struct event * e = 0 ;
98
-
99
- events_mutex_lock (& q -> freelock );
100
- if (!q -> free ) {
101
- events_mutex_unlock (& q -> freelock );
125
+ void * event_alloc (struct equeue * q , unsigned size ) {
126
+ struct event * e = equeue_alloc (q , sizeof (struct event ) + size );
127
+ if (!e ) {
102
128
return 0 ;
103
129
}
104
130
105
- e = q -> free ;
106
- q -> free = e -> next ;
107
- events_mutex_unlock (& q -> freelock );
108
-
109
- e -> id = equeue_next_id (q );
131
+ e -> id = event_next_id (q );
110
132
e -> target = 0 ;
111
133
e -> period = -1 ;
112
134
e -> dtor = 0 ;
113
- return e ;
135
+
136
+ return e + 1 ;
114
137
}
115
138
116
- static void equeue_dealloc (struct equeue * q , struct event * e ) {
139
+ void event_dealloc (struct equeue * q , void * p ) {
140
+ struct event * e = (struct event * )p - 1 ;
141
+
117
142
if (e -> dtor ) {
118
143
e -> dtor (e + 1 );
119
144
}
120
145
121
- events_mutex_lock (& q -> freelock );
122
- e -> next = q -> free ;
123
- q -> free = e ;
124
- events_mutex_unlock (& q -> freelock );
146
+ equeue_dealloc (q , e );
125
147
}
126
148
127
149
// equeue scheduling functions
128
- static inline int tickdiff (unsigned a , unsigned b ) {
150
+ static inline int equeue_tickdiff (unsigned a , unsigned b ) {
129
151
return (int )(a - b );
130
152
}
131
153
132
154
static int equeue_enqueue (struct equeue * q , struct event * e , int ms ) {
133
155
e -> target = events_tick () + (unsigned )ms ;
134
156
135
157
struct event * * p = & q -> queue ;
136
- while (* p && tickdiff ((* p )-> target , e -> target ) <= 0 ) {
158
+ while (* p && equeue_tickdiff ((* p )-> target , e -> target ) <= 0 ) {
137
159
p = & (* p )-> next ;
138
160
}
139
161
@@ -169,7 +191,7 @@ static void equeue_cancel(struct equeue *q, int id) {
169
191
events_mutex_unlock (& q -> queuelock );
170
192
171
193
if (e ) {
172
- equeue_dealloc (q , e );
194
+ event_dealloc (q , e + 1 );
173
195
}
174
196
}
175
197
@@ -194,7 +216,7 @@ void equeue_dispatch(struct equeue *q, int ms) {
194
216
break ;
195
217
}
196
218
197
- deadline = tickdiff (q -> queue -> target , events_tick ());
219
+ deadline = equeue_tickdiff (q -> queue -> target , events_tick ());
198
220
if (deadline > 0 ) {
199
221
events_mutex_unlock (& q -> queuelock );
200
222
break ;
@@ -218,7 +240,7 @@ void equeue_dispatch(struct equeue *q, int ms) {
218
240
e -> cb (e + 1 );
219
241
220
242
if (e -> period < 0 ) {
221
- equeue_dealloc (q , e );
243
+ event_dealloc (q , e + 1 );
222
244
}
223
245
}
224
246
@@ -227,25 +249,6 @@ void equeue_dispatch(struct equeue *q, int ms) {
227
249
}
228
250
229
251
// event functions
230
- void * event_alloc (struct equeue * q , unsigned size ) {
231
- if (size > q -> size - sizeof (struct event )) {
232
- return 0 ;
233
- }
234
-
235
- struct event * e = equeue_alloc (q );
236
- if (!e ) {
237
- return 0 ;
238
- }
239
-
240
- return e + 1 ;
241
- }
242
-
243
- void event_dealloc (struct equeue * q , void * p ) {
244
- struct event * e = (struct event * )p - 1 ;
245
- equeue_dealloc (q , e );
246
- }
247
-
248
- // configuring events
249
252
void event_delay (void * p , int ms ) {
250
253
struct event * e = (struct event * )p - 1 ;
251
254
e -> target = ms ;
@@ -273,7 +276,17 @@ void event_cancel(struct equeue *q, int id) {
273
276
return equeue_cancel (q , id );
274
277
}
275
278
276
- // event helper functions
279
+ // simple callbacks
280
+ struct ecallback {
281
+ void (* cb )(void * );
282
+ void * data ;
283
+ };
284
+
285
+ static void ecallback_dispatch (void * p ) {
286
+ struct ecallback * e = (struct ecallback * )p ;
287
+ e -> cb (e -> data );
288
+ }
289
+
277
290
int event_call (struct equeue * q , void (* cb )(void * ), void * data ) {
278
291
struct ecallback * e = event_alloc (q , sizeof (struct ecallback ));
279
292
if (!e ) {
0 commit comments