1 /*******************************************************************
2 uLan Utilities Library - C library of basic reusable constructions
4 ul_evcbase.c - event connectors
6 (C) Copyright 2001-2003 by Pavel Pisa - Originator
8 The uLan utilities library can be used, copied and modified under
10 - GPL - GNU General Public License
11 - LGPL - GNU Lesser General Public License
12 - MPL - Mozilla Public License
13 - and other licenses added by project originators
14 Code can be modified and re-distributed under any combination
15 of the above listed licenses. If contributor does not agree with
16 some of the licenses, he/she can delete appropriate line.
17 Warning, if you delete all lines, you are not allowed to
18 distribute source code and/or binaries utilizing code.
20 See files COPYING and README for details.
22 *******************************************************************/
26 #include "ul_utmalloc.h"
28 #include "ul_evcbase.h"
30 UL_LIST_CUST_DEC(evc_tx_list, evc_tx_hub_t, evc_link_t, links, src.peers)
31 UL_LIST_CUST_DEC(evc_rx_list, evc_rx_hub_t, evc_link_t, links, dst.multi.peers)
34 * evc_link_init - Initialize Event Connector Link
35 * @link: pointer to the link
37 * Link reference count is set to 1 by this function
38 * Return Value: negative value informs about failure.
40 int evc_link_init(evc_link_t *link)
42 memset(link,0,sizeof(evc_link_t));
43 evc_rx_list_init_detached(link);
44 evc_tx_list_init_detached(link);
45 evc_link_inc_refcnt(link);
50 * evc_link_new - Allocates New Event Connector Link
52 * Link reference count is set to 1 by this function
53 * Return Value: pointer to the new link or %NULL.
55 evc_link_t *evc_link_new(void)
59 link=malloc(sizeof(evc_link_t));
60 if(link==NULL) return NULL;
68 * evc_link_connect - Connects Link between Two Hubs
69 * @link: pointer to the non-connected initialized link
70 * @src: pointer to the source hub of type &evc_tx_hub_t
71 * @dst: pointer to the destination hub of type &evc_rx_hub_t
72 * @prop: propagation function corresponding to source and destination
73 * expected event arguments
75 * If ready flag is not set, link state is set to ready
76 * and reference count is increased.
77 * Return Value: negative return value indicates fail.
79 int evc_link_connect(evc_link_t *link, evc_tx_hub_t *src, evc_rx_hub_t *dst,
84 if(!link || !src || !dst || !prop) return -1;
85 if(link->standalone) return -1;
86 evc_link_inc_refcnt(link);
90 evc_tx_list_insert(src,link);
91 link->dst.multi.hub=dst;
92 evc_rx_list_insert(dst,link);
93 link_ready=link->ready;
96 evc_link_dec_refcnt(link);
103 * evc_link_init_standalone - Initialize Standalone Link
104 * @link: pointer to the link
105 * @rx_fnc: pointer to the function invoked by event reception
106 * @context: context for the rx_fnc() function invocation
108 * Link reference count is set to 1 by this function
109 * Return Value: negative value informs about failure.
111 int evc_link_init_standalone(evc_link_t *link, evc_rx_fnc_t *rx_fnc, void *context)
113 memset(link,0,sizeof(evc_link_t));
114 evc_rx_list_init_detached(link);
116 link->dst.standalone.rx_fnc=rx_fnc;
117 link->dst.standalone.context=context;
118 evc_link_inc_refcnt(link);
123 * evc_link_new_standalone - Allocates New Standalone Link
125 * Link reference count is set to 1 by this function
126 * Return Value: pointer to the new link or %NULL.
128 evc_link_t *evc_link_new_standalone(evc_rx_fnc_t *rx_fnc, void *context)
132 link=malloc(sizeof(evc_link_t));
133 if(link==NULL) return NULL;
135 evc_link_init_standalone(link, rx_fnc, context);
141 * evc_link_connect_standalone - Connects Standalone Link to Source Hubs
142 * @link: pointer to the non-connected initialized link
143 * @src: pointer to the source hub of type &evc_tx_hub_t
144 * @prop: propagation function corresponding to hub source
145 * and standalone rx_fnc() expected event arguments
147 * If ready flag is not set, link state is set to ready
148 * and reference count is increased.
149 * Return Value: negative return value indicates failure.
151 int evc_link_connect_standalone(evc_link_t *link, evc_tx_hub_t *src,
152 evc_prop_fnc_t *prop)
156 if(!link || !src || !prop) return -1;
157 if(!link->standalone) return -1;
158 evc_link_inc_refcnt(link);
160 link->propagate=prop;
162 evc_tx_list_insert(src,link);
163 link_ready=link->ready;
166 evc_link_dec_refcnt(link);
174 void evc_link_do_delete(evc_link_t *link)
176 evc_tx_list_del_item(link);
178 if(!link->standalone){
179 evc_rx_list_del_item(link);
180 link->dst.multi.hub=NULL;
187 * evc_link_delete - Deletes Link from Hubs Lists
188 * @link: pointer to the possibly connected initialized link
190 * If ready flag is set, link ready flag is cleared and reference count
191 * is decreased. This could lead to link disappear, if nobody is holding
193 * Return Value: positive return value indicates immediate delete,
194 * zero return value informs about delayed delete.
196 int evc_link_delete(evc_link_t *link)
201 evc_link_do_delete(link);
208 evc_link_dec_refcnt(link);
214 * evc_link_dispose - Disposes Link
215 * @link: pointer to the possibly connected initialized link
217 * Deletes link from hubs, marks it as dead, calls final death propagate()
218 * for the link and if link is @malloced, releases link occupied memory.
220 void evc_link_dispose(evc_link_t *link)
224 if(!link->propagate(link,0)){
225 evc_link_inc_refcnt(link);
226 evc_link_delete(link);
227 if(link->malloced) free(link);
228 else if(link->refcnt>0) link->refcnt--;
234 * evc_tx_hub_init - Initializes Event Transmition Hub
235 * @hub: pointer to the &evc_tx_hub_t type hub
237 * Return Value: negative return value indicates failure.
239 int evc_tx_hub_init(evc_tx_hub_t *hub)
241 evc_tx_list_init_head(hub);
246 * evc_tx_hub_done - Initializes Event Transmition Hub
247 * @hub: pointer to the &evc_tx_hub_t type hub
249 void evc_tx_hub_done(evc_tx_hub_t *hub)
252 ul_list_for_each_cut(evc_tx_list, hub, link){
253 evc_link_inc_refcnt(link);
255 evc_link_delete(link);
256 evc_link_dec_refcnt(link);
261 int evc_prop_link_skip(evc_link_t *link)
263 if(link->dead || link->blocked || link->delete_pend) return 1;
264 if(!link->recursive && link->taken) return 1;
269 * evc_tx_hub_propagate - Propagate Event to Links Destinations
270 * @hub: pointer to the &evc_tx_hub_t type hub
271 * @args: pointer to the variable arguments list
273 * The function propagates event to the connected links,
274 * it skips links marked as @dead, @blocked or @delete_pend.
275 * If the link is not marked as @recursive, it ensures, that
276 * link is not called twice.
278 void evc_tx_hub_propagate(evc_tx_hub_t *hub, va_list args)
280 evc_link_t *link, *next;
282 link=evc_tx_list_first(hub);
285 if(!evc_prop_link_skip(link)) break;
286 link=evc_tx_list_next(hub,link);
288 evc_link_inc_refcnt(link); /*prevents dispose of the link*/
289 link->taken++; /*prevents delete of the link from the hub*/
291 link->propagate(link, args);
293 if(link->src.hub == hub){ /*check for correct hub relation*/
296 next=evc_tx_list_next(hub,next);
298 if(!evc_prop_link_skip(next)) {
299 evc_link_inc_refcnt(next); /*prevents dispose of the link*/
300 next->taken++; /*prevents delete of the link from the hub*/
305 /* link is already disconnected from the hub,
306 result of evc_tx_hub_done */
309 if(!(--link->taken)){
310 if(link->delete_pend)
311 evc_link_delete(link); /*process pending delete*/
313 evc_link_dec_refcnt(link); /*can lead to dispose of the link*/
318 * evc_tx_hub_emit - Emits Event to Hub
319 * @hub: pointer to the &evc_tx_hub_t type hub
321 * The function hands over arguments to evc_tx_hub_propagate()
324 void evc_tx_hub_emit(evc_tx_hub_t *hub, ...)
328 va_start (args, hub);
329 evc_tx_hub_propagate(hub, args);
333 int evc_tx_hub_eol_weakptr(evc_tx_hub_t *hub, void **weakptr)
335 evc_link_t *link, *next;
338 link=evc_tx_list_first(hub);
340 next=evc_tx_list_next(hub,link);
341 if(link->standalone && (link->dst.standalone.weakptr==weakptr)){
342 link->dst.standalone.weakptr=NULL;
343 evc_link_delete(link);
353 * evc_rx_hub_init - Initializes Event Receiption Hub
354 * @hub: pointer to the &evc_rx_hub_t type hub
355 * @rx_fnc: pointer to the function invoked by event reception
356 * @context: context for the rx_fnc() function invocation
358 * Return Value: negative return value indicates failure.
360 int evc_rx_hub_init(evc_rx_hub_t *hub, evc_rx_fnc_t *rx_fnc, void *context)
362 evc_rx_list_init_head(hub);
364 hub->context=context;
369 * evc_rx_hub_done - Finalize Event Receiption Hub
370 * @hub: pointer to the &evc_rx_hub_t type hub
372 void evc_rx_hub_done(evc_rx_hub_t *hub)
375 ul_list_for_each_cut(evc_rx_list, hub, link){
376 evc_link_inc_refcnt(link);
377 link->dst.multi.hub=NULL;
378 evc_link_delete(link);
379 evc_link_dec_refcnt(link);
383 /*===========================================================*/
384 /* arguments propagation functions */
386 typedef int evc_fnc_propagate_i_p_l(void *, long);
388 int evc_link_propagate_i_p_l(evc_link_t *link, va_list args)
391 evc_fnc_propagate_i_p_l *fnc;
394 if(link->standalone && link->dst.standalone.weakptr){
395 *link->dst.standalone.weakptr=NULL;
396 link->dst.standalone.weakptr=NULL;
400 if(link->standalone){
401 fnc=(evc_fnc_propagate_i_p_l*)link->dst.standalone.rx_fnc;
402 context=link->dst.standalone.context;
404 if(!link->dst.multi.hub) return 0;
405 fnc=(evc_fnc_propagate_i_p_l*)link->dst.multi.hub->rx_fnc;
406 context=link->dst.multi.hub->context;
409 fnc(context, va_arg(args, long));