event_manager.c
3.92 KB
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include <scot/event_sink.h>
#include <scot/event_source.h>
#include <scot/event.h>
#include <scot/exception.h>
#define GEN_LOCAL
#include <scot/queue.h>
#include <scot/list.h>
#undef GEN_LOCAL
/*
struct scot_event_sink_event_wrapper
{
struct scot_event_source es;
union scot_event_u e;
};
typedef struct scot_event_sink_event_wrapper scot_esew_t;
GEN_QUEUE (scot_esew_t);
*/
typedef struct scot_event_sink scot_event_sink_t;
GEN_LIST (scot_event_sink_t);
typedef struct scot_event_source scot_event_source_t;
GEN_LIST (scot_event_source_t);
struct scot_event_manager
{
list_scot_event_sink_t_node_t * sinks;
list_scot_event_source_t_node_t * sources;
};
static
int
scot_event_source_compare_by_group_no (
const struct scot_event_source * a,
const struct scot_event_source * b)
{
return (a->group_no==b->group_no)?0:(a->group_no<b->group_no)?-1:1;
};
void
scot_event_manager_register_source (
struct scot_event_manager * m,
struct scot_event_source * es)
{
struct scot_event_manager_src_cb_map * s_cb_map;
if (scot_event_source_set_manager (es, m) != 0)
THROW (EXC (EXC_ERROR, 1, "source already registered within other "
"manager."));
if (list_scot_event_source_t_find (m->sources, es))
/* well, this source is already registered within this manager */
{
THROW (EXC (EXC_WARNING, 1, "event source already registered within "
"this manager."));
return 0;
}
list_scot_event_source_t_node_t_set_cmp (
scot_event_source_compare_by_group_no);
if (list_scot_event_source_t_find (m->sources, es))
/* an event source of the same group is already registered within
* this manager */
{
THROW (EXC (EXC_WARNING, 1, "another event source of the same group "
"is already registered within this "
"manager."));
return 0;
}
list_scot_event_source_t_node_t_set_cmp (
list_scot_event_source_t_default_cmp);
list_scot_event_source_t_add (m->sources, es);
}
void
scot_event_manager_register_sink (
struct scot_event_manager * m,
struct scot_event_sink * es)
{
if (scot_event_sink_set_manager (es, m) != 0)
THROW (EXC (EXC_ERROR, 2, "Sink already registered within other "
"manager."));
list_scot_event_sink_t_add (m->sinks, s_cb_map);
}
void
scot_event_manager_call_cb (
struct scot_event_manager * m,
struct scot_event_source * es,
struct scot_event * e)
{
list_scot_emscm_t_node_t * emscm_node = m->src_cb;
while (! list_scot_emscm_t_eol (m->src_cb, emscm_node))
{
struct scot_event_manager_src_cb_map * scbm;
emscm_node = list_scot_emscm_t_next (emscm_node);
scbm = list_scot_emscm_t_retrive (emscm_node);
if (scbm->source == es)
{
scbm->cb (e);
return;
}
}
}
void
scot_event_manager_dispatch_event (
struct scot_event_manager * m,
struct scot_event * e,
struct scot_event_source * src,
int mask)
{
list_event_sink_t_node_t * es_node = m->sinks;
int dipatched = 0;
while (! list_scot_event_sink_t_node_t_eol (m->sinks, es_node))
{
struct scot_event_sink * es;
int i;
es_node = list_scot_event_sink_t_next (es_node);
es = list_scot_event_sink_t_retrive (es_node);
for (i=0; i<MAX_EVENT_GROUP && es->src[i]!=0; i++)
{
if (es->src[i] == scot_event_get_src (e) &&
es->mask[i] & scot_event_get_mask (e) != 0)
{
/* Im folgenden sollte das nicht e sondern halt irgend eine
* art wrapper sein aus dem auch die gruppe und maske
* des events hervorgeht.
* sonst wird es unmöglich eine brauchbare Notice zu schicken
* wenn das event abgearbeitet wurde. */
scot_event_sink_put_event (es, e);
dispatched = 1;
}
}
}
/* wenn sich keine sink für das event interessiert hat. */
if (dispatched == 0)
{
/* einen etwaigen callback aufrufen... */
scot_event_manager_call_bc (m, get_source from event(e), e);
/* resourcen des events freigeben... */
scot_event_free (e);
}
}