1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
/* ISC license. */
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <skalibs/strerr2.h>
#include <skalibs/genalloc.h>
#include <skalibs/gensetdyn.h>
#include <skalibs/avltree.h>
#include <s6-rc/event.h>
#include "ep.h"
typedef struct epelem_s epelem_t, *epelem_t_ref ;
struct epelem_s
{
uint32_t owner ;
ep_func_t_ref f ;
void *aux ;
} ;
#define EPELEM_ZERO { .owner = 0, .f = 0, .aux = 0 }
typedef struct eplist_s eplist_t, *eplist_t_ref ;
struct eplist_s
{
char const *name ;
genalloc list ; /* epelem_t */
} ;
#define EPLIST_ZERO { .name = 0, .list = GENALLOC_ZERO }
typedef struct epset_s epset_t, *epset_t_ref ;
struct epset_s
{
gensetdyn data ; /* eplist_t */
avltree map ;
} ;
#define EPSET_ZERO { .data = GENSETDYN_ZERO, .map = AVLTREE_ZERO }
static void *epset_dtok (uint32_t d, void *x)
{
return (void *)&GENSETDYN_P(eplist_t, (gensetdyn *)x, d)->name ;
}
static int epset_cmp (void const *a, void const *b, void *x)
{
(void)x ;
return strcmp((char const *)a, (char const *)b) ;
}
static epset_t ep[EVENTTYPE_PHAIL] =
{
{ .data = GENSETDYN_ZERO, .map = AVLTREE_INIT(8, 3, 8, &epset_dtok, &epset_cmp, &ep[0].data) },
{ .data = GENSETDYN_ZERO, .map = AVLTREE_INIT(8, 3, 8, &epset_dtok, &epset_cmp, &ep[1].data) },
{ .data = GENSETDYN_ZERO, .map = AVLTREE_INIT(8, 3, 8, &epset_dtok, &epset_cmp, &ep[2].data) },
{ .data = GENSETDYN_ZERO, .map = AVLTREE_INIT(8, 3, 8, &epset_dtok, &epset_cmp, &ep[3].data) },
{ .data = GENSETDYN_ZERO, .map = AVLTREE_INIT(8, 3, 8, &epset_dtok, &epset_cmp, &ep[4].data) },
{ .data = GENSETDYN_ZERO, .map = AVLTREE_INIT(8, 3, 8, &epset_dtok, &epset_cmp, &ep[5].data) },
{ .data = GENSETDYN_ZERO, .map = AVLTREE_INIT(8, 3, 8, &epset_dtok, &epset_cmp, &ep[6].data) },
} ;
static void eplist_free (void *p)
{
eplist_t *x = p ;
genalloc_free(epelem_t, &x->list) ;
}
void ep_free ()
{
for (s6rc_eventtype_t i = 0 ; i < S6RC_EVENTTYPE_PHAIL ; i++)
{
avltree_free(&ep[i].map) ;
gensetdyn_deepfree(&ep[i].data, &eplist_free) ;
avltree_init(&ep[i].map, 8, 3, 8, &epset_dtok, &epset_cmp, &ep[i].data) ;
}
}
int ep_add (uint8_t type, char const *name, uint32_t owner, ep_func_t_ref f, void *aux)
{
epelem_t ee = { .owner = owner, .f = f, .aux = aux } ;
uint32_t d ;
if (!avltree_search(&ep[type].map, name, &d))
{
eplist_t newlist = { .name = name, .list = GENALLOC_ZERO } ;
if (!gensetdyn_new(&ep[type].data, &d)) return 0 ;
*GENSETDYN_P(eplist_t, &ep[type].data, d) = newlist ;
if (!avltree_insert(&ep[type].map, d))
{
gensetdyn_delete(&ep[type].data, d) ;
return 0 ;
}
}
return genalloc_catb(epelem_t, &GENSETDYN_P(eplist_t, &ep[type].data, d)->list, &ee) ;
}
void ep_delete (uint8_t type, char const *name, uint32_t owner, ep_func_t_ref f, void *aux)
{
uint32_t d ;
if (!avltree_search(&ep[type].map, name, &d)) return ;
epelem_t ee = { .owner = owner, .f = f, .aux = aux } ;
genalloc *g = &GENSETDYN_P(eplist_t, &ep[type].data, d)->list ;
epelem_t *list = genalloc_s(epelem_t, g) ;
size_t n = genalloc_len(epelem_t, g) ;
size_t i = 0 ;
for (; i < n ; i++) if (list == ee) break ;
if (i < n) list[i] = list[--n] ;
if (!n)
{
genalloc_free(epelem_t, g) ;
avltree_delete(&ep[type].map, name) ;
gensetdyn_delete(eplist_t, &ep[type].data, d) ;
}
}
void ep_run (s6rc_event_t const *ev)
{
uint32_t d ;
if (!avltree_search(&ep[ev->type].map, ev->name, &d)) return ;
genalloc *g = &GENSETDYN_P(eplist_t, &ep[ev->type].data, d)->list ;
epelem_t const *list = genalloc_s(epelem_t, g) ;
size_t n = genalloc_len(epelem_t, g) ;
for (size_t i = 0 ; i < n ; i++)
(*list[i].f)(ev, list[i].owner, list[i].aux) ;
}
|