00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "plint.h"
00026 #include "monitor.h"
00027
00028 #include "share/hash.h"
00029
00030 typedef struct _plint_subscriber_event * plint_subscriber_event_t;
00031 typedef struct _plint_subscriber_real * plint_subscriber_real_t;
00032 typedef struct _plint_subscriber_proxy * plint_subscriber_proxy_t;
00033 typedef struct _plint_event_real * plint_event_real_t;
00034
00035
00036 struct _plint_subscriber_event
00037 {
00038 plint_monitor_t monitor;
00039 plint_event_t event;
00040 bit_t enable:1;
00041
00042 void * data;
00043 plint_announce_t announce;
00044 };
00045
00046 struct _plint_subscriber_proxy
00047 {
00048 plint_subscriber_t subscriber;
00049 plint_subscriber_event_t event;
00050 };
00051
00052 struct _plint_subscriber_real
00053 {
00054 plint_monitor_t monitor;
00055 slot_key_t events;
00056 };
00057
00058 struct _plint_event_real
00059 {
00060 hashindex_t name;
00061 slot_key_t subs;
00062 plint_announce_t done;
00063 };
00064
00065
00066 plint_monitor_t plint_monitor_create()
00067 {
00068 return (plint_monitor_t)slot_register(plint->monitor.moni,
00069 slot_create(), slot_delete);
00070 }
00071
00072 void plint_monitor_delete(plint_monitor_t m)
00073 {
00074 slot_unregister(plint->monitor.moni, (int)m);
00075 }
00076
00077
00078 static void event_free(plint_event_real_t e)
00079 {
00080 hash_remstr(plint->monitor.evnt, e->name);
00081 slot_delete(e->subs);
00082 FREE(e);
00083 }
00084
00085 static void * done_ignore(plint_monitor_t m,
00086 plint_event_t r,
00087 plint_subscriber_t s, void * d,
00088 vargs_t a)
00089 {
00090 return 0;
00091 }
00092
00093 plint_event_t plint_monitor_event_register(plint_monitor_t m, plint_str_t s, plint_announce_t d)
00094 {
00095 plint_event_real_t e;
00096 NEW(e);
00097 e->name = hash_putstr(NS_GLOBAL(plint->monitor.evnt), plint_str_sn(s), 0);
00098 e->subs = slot_create();
00099 e->done = d ? : done_ignore;
00100 return (plint_event_t)slot_register((slot_key_t)slot_getdata(plint->monitor.moni, (int)m),
00101 e, (slot_ffree_t)event_free);
00102 }
00103
00104 void plint_monitor_event_unregister(plint_monitor_t m, plint_event_t e)
00105 {
00106 slot_unregister((slot_key_t)slot_getdata(plint->monitor.moni, (int)m), (int)e);
00107 }
00108
00109 plint_str_t plint_monitor_event_name(plint_monitor_t m, plint_event_t e)
00110 {
00111 plint_event_real_t r;
00112 plint_str_t s;
00113
00114 r = (plint_event_real_t)slot_getdata((slot_key_t)slot_getdata(plint->monitor.moni, (int)m), (int)e);
00115 plint_hash_str(plint->monitor.evnt, r->name, s);
00116
00117 return s;
00118 }
00119
00120 int plint_monitor_event_match(plint_monitor_t m, plint_event_t e, plint_str_t n)
00121 {
00122 plint_event_real_t r = (plint_event_real_t)slot_getdata((slot_key_t)slot_getdata(plint->monitor.moni,
00123 (int)m),
00124 (int)e);
00125
00126 return HASH_INDEX_EQU(r->name, hash_getindex(plint->monitor.evnt, plint_str_sn(n)));
00127 }
00128
00129 inline int plint_monitor_announce(plint_monitor_t m, plint_event_t e, ...)
00130 {
00131 int i;
00132 plint_event_real_t r;
00133 plint_subscriber_proxy_t p;
00134 vargs_t a;
00135 slot_key_t s;
00136
00137 s = (slot_key_t)slot_getdata(plint->monitor.moni, (int)m);
00138
00139 if (!slot_lock(s))
00140 return 0;
00141
00142 vargstart(a, e);
00143
00144 r = (plint_event_real_t)slot_getdata(s, (int)e);
00145 for (i = slot_first(r->subs); i; i = slot_next(r->subs, i))
00146 {
00147 p = (plint_subscriber_proxy_t)slot_getdata(r->subs, i);
00148 if (p->event->enable)
00149 (void)r->done(m, e, p->subscriber, p->event->announce(m, e, p->subscriber, p->event->data, a), a);
00150 }
00151
00152 vargsdone(a);
00153
00154 slot_unlock(s);
00155
00156 return !0;
00157 }
00158
00159 plint_subscriber_t plint_monitor_subscribe(plint_monitor_t m)
00160 {
00161 plint_subscriber_real_t r;
00162
00163 NEW(r);
00164 r->monitor = m;
00165 r->events = slot_create();
00166 return (plint_subscriber_t)r;
00167 }
00168
00172 void plint_monitor_unsubscribe(plint_subscriber_t s)
00173 {
00174 plint_subscriber_real_t r;
00175
00176 r = (plint_subscriber_real_t)s;
00177 slot_delete(r->events);
00178 FREE(r);
00179 }
00180
00181 int plint_monitor_subscribed(plint_monitor_t m, plint_subscriber_t s)
00182 {
00183 return ((plint_subscriber_real_t)s)->monitor == m;
00184 }
00185
00186 static void subscribe_xxxx(plint_subscriber_real_t s, bit_t x)
00187 {
00188 int i;
00189 plint_subscriber_event_t e;
00190
00191 for (i = slot_first(s->events); i; i = slot_next(s->events, i))
00192 {
00193 e = (plint_subscriber_event_t)slot_getdata(s->events, i);
00194 e->enable = x;
00195 }
00196 }
00197
00198 inline void plint_monitor_subscribe_none(plint_subscriber_t s)
00199 {
00200 subscribe_xxxx((plint_subscriber_real_t)s, 0);
00201 }
00202
00203 inline void plint_monitor_subscribe_each(plint_subscriber_t s)
00204 {
00205 subscribe_xxxx((plint_subscriber_real_t)s, 1);
00206 }
00207
00208 static int event_find_in_moni(plint_event_real_t l, plint_str_t *r)
00209 {
00210 plint_str_t s;
00211 int x;
00212
00213 plint_hash_str(plint->monitor.evnt, l->name, s);
00214 x = plint_str_equ(s, *r);
00215 plint_str_fre(s);
00216
00217 return x;
00218 }
00219
00220 static int lookup_event_in_moni(plint_subscriber_real_t s, plint_str_t e)
00221 {
00222 return slot_find((slot_key_t)slot_getdata(plint->monitor.moni, (int)s->monitor),
00223 (void *)&e,
00224 (slot_ffind_t)event_find_in_moni);
00225 }
00226
00227 static int proxy_find(plint_subscriber_proxy_t p, plint_event_t e)
00228 {
00229 return p->event == e;
00230 }
00231
00232 static void free_event(plint_subscriber_event_t e)
00233 {
00234 slot_key_t s = ((plint_event_real_t)slot_getdata((slot_key_t)slot_getdata(plint->monitor.moni, (int)e->monitor),
00235 (int)e->event))->subs;
00236 slot_unregister(s, slot_find(s, e->event, (slot_ffind_t)proxy_find));
00237 FREE(e);
00238 }
00239
00240 static void free_proxy(plint_subscriber_proxy_t p)
00241 {
00242
00243
00244
00245
00246
00247 FREE(p);
00248 }
00249
00250 static int event_find_in_subs(plint_subscriber_event_t e, plint_event_t i)
00251 {
00252 return (e->event == (plint_event_t)i);
00253 }
00254
00255 static int lookup_event_in_subs(plint_subscriber_real_t s, plint_event_t e)
00256 {
00257 return slot_find(s->events, e, (slot_ffind_t)event_find_in_subs);
00258 }
00259
00260 int plint_monitor_subscribe_event(plint_subscriber_t s, plint_str_t es, plint_announce_t a, void * d)
00261 {
00262 int i, j;
00263 plint_subscriber_event_t e;
00264 plint_subscriber_real_t r;
00265 plint_subscriber_proxy_t p;
00266
00267 r = (plint_subscriber_real_t)s;
00268
00269 i = lookup_event_in_moni(r, es);
00270 if (i == 0)
00271 return -1;
00272
00273 j = lookup_event_in_subs(r, (plint_event_t)i);
00274 if (j != 0)
00275 return +1;
00276
00277 NEW(e);
00278 e->monitor = r->monitor;
00279 e->event = (plint_event_t)i;
00280 e->enable = 1;
00281
00282 e->data = d;
00283 e->announce = a;
00284 slot_register(r->events, e, (slot_ffree_t)free_event);
00285
00286 NEW(p);
00287 p->subscriber = s;
00288 p->event = e;
00289 (void)slot_register(((plint_event_real_t)slot_getdata(
00290 (slot_key_t)slot_getdata(plint->monitor.moni, (int)r->monitor),
00291 i))->subs,
00292 p, (slot_ffree_t)free_proxy);
00293
00294 return 0;
00295 }
00296
00297 static int endis_event(plint_subscriber_real_t s, plint_str_t e, bit_t x)
00298 {
00299 int i;
00300
00301 i = lookup_event_in_moni(s, e);
00302 if (i == 0)
00303 return -1;
00304
00305 i = lookup_event_in_subs(s, (plint_event_t)i);
00306 if (i == 0)
00307 return +1;
00308
00309 ((plint_subscriber_event_t)slot_getdata(s->events, i))->enable = x;
00310
00311 return 0;
00312 }
00313
00314 inline int plint_monitor_disable_event(plint_subscriber_t s, plint_str_t e)
00315 {
00316 return endis_event((plint_subscriber_real_t)s, e, 0);
00317 }
00318
00319 inline int plint_monitor_enable_event(plint_subscriber_t s, plint_str_t e)
00320 {
00321 return endis_event((plint_subscriber_real_t)s, e, 1);
00322 }
00323
00324 int plint_monitor_event(plint_subscriber_t s, plint_str_t e)
00325 {
00326 int i;
00327 plint_subscriber_real_t r;
00328
00329 r = (plint_subscriber_real_t)s;
00330
00331 i = lookup_event_in_moni(r, e);
00332 if (i == 0)
00333 return -1;
00334
00335 i = lookup_event_in_subs(r, (plint_event_t)i);
00336 if (i == 0)
00337 return -1;
00338
00339 return ((plint_subscriber_event_t)slot_getdata(r->events, i))->enable ? 1 : 0;
00340 }
00341
00347 int plint_monitor_unsubscribe_event(plint_subscriber_t s, plint_str_t e, void ** p)
00348 {
00349 int i;
00350 plint_subscriber_real_t r;
00351
00352 r = (plint_subscriber_real_t)s;
00353
00354 i = lookup_event_in_moni(r, e);
00355 if (i == 0)
00356 return -1;
00357
00358 i = lookup_event_in_subs(r, (plint_event_t)i);
00359 if (i == 0)
00360 return +1;
00361
00362 if (p)
00363 *p = slot_getdata(r->events, i);
00364 slot_unregister(r->events, i);
00365
00366 return 0;
00367 }