Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals  

monitor.c

00001  /*
00002   * plint/misc/monitor.c : monitors
00003   * 
00004   * Time-stamp: <2003-01-07 20:10:44 gseba>
00005   * 
00006   * Copyright (C) Sebastian Glita, email: gseba@users.sourceforge.net
00007   * 
00008   * This file is part of plint.
00009   * 
00010   * plint is free software; you can  redistribute it and/or modify it under the
00011   * terms of the  GNU General Public License as published  by the Free Software
00012   * Foundation; either version 2, or (at your option) any later version.
00013   *
00014   * plint  is distributed  in the  hope  that it  will be  useful, but  WITHOUT
00015   * ANY  WARRANTY; without  even  the implied  warranty  of MERCHANTABILITY  or
00016   * FITNESS FOR A  PARTICULAR PURPOSE.  See the GNU  General Public License for
00017   * more details.
00018   * 
00019   * You should  have received a  copy of the  GNU General Public  License along
00020   * with  plint; see  the file  COPYING.  If  not, write  to the  Free Software
00021   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA USA.
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   /* MUST NOT trigger a free_event!
00243      because, if everything goes well in case of a fatal signal,
00244      the subscribers should have unsubscribed by know...
00245      ... not to mention the normal flow case.
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 }

Generated on Thu Jan 9 19:02:38 2003 for plint by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002