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
124 * @rx_fnc: callback function invoked if event is delivered
125 * @context: context provided to the callback function
127 * Link reference count is set to 1 by this function
128 * Return Value: pointer to the new link or %NULL.
130 evc_link_t *evc_link_new_standalone(evc_rx_fnc_t *rx_fnc, void *context)
134 link=malloc(sizeof(evc_link_t));
135 if(link==NULL) return NULL;
137 evc_link_init_standalone(link, rx_fnc, context);
143 * evc_link_connect_standalone - Connects Standalone Link to Source Hubs
144 * @link: pointer to the non-connected initialized link
145 * @src: pointer to the source hub of type &evc_tx_hub_t
146 * @prop: propagation function corresponding to hub source
147 * and standalone rx_fnc() expected event arguments
149 * If ready flag is not set, link state is set to ready
150 * and reference count is increased.
151 * Return Value: negative return value indicates failure.
153 int evc_link_connect_standalone(evc_link_t *link, evc_tx_hub_t *src,
154 evc_prop_fnc_t *prop)
158 if(!link || !src || !prop) return -1;
159 if(!link->standalone) return -1;
160 evc_link_inc_refcnt(link);
162 link->propagate=prop;
164 evc_tx_list_insert(src,link);
165 link_ready=link->ready;
168 evc_link_dec_refcnt(link);
176 void evc_link_do_delete(evc_link_t *link)
178 evc_tx_list_del_item(link);
180 if(!link->standalone){
181 evc_rx_list_del_item(link);
182 link->dst.multi.hub=NULL;
189 * evc_link_delete - Deletes Link from Hubs Lists
190 * @link: pointer to the possibly connected initialized link
192 * If ready flag is set, link ready flag is cleared and reference count
193 * is decreased. This could lead to link disappear, if nobody is holding
195 * Return Value: positive return value indicates immediate delete,
196 * zero return value informs about delayed delete.
198 int evc_link_delete(evc_link_t *link)
203 evc_link_do_delete(link);
210 evc_link_dec_refcnt(link);
216 * evc_link_dispose - Disposes Link
217 * @link: pointer to the possibly connected initialized link
219 * Deletes link from hubs, marks it as dead, calls final death propagate()
220 * for the link and if link is @malloced, releases link occupied memory.
222 void evc_link_dispose(evc_link_t *link)
226 if(!link->propagate(link,0)){
227 evc_link_inc_refcnt(link);
228 evc_link_delete(link);
229 if(link->malloced) free(link);
230 else if(link->refcnt>0) link->refcnt--;
236 * evc_tx_hub_init - Initializes Event Transmition Hub
237 * @hub: pointer to the &evc_tx_hub_t type hub
239 * Return Value: negative return value indicates failure.
241 int evc_tx_hub_init(evc_tx_hub_t *hub)
243 evc_tx_list_init_head(hub);
248 * evc_tx_hub_done - Finalize Event Transmition Hub
249 * @hub: pointer to the &evc_tx_hub_t type hub
251 void evc_tx_hub_done(evc_tx_hub_t *hub)
254 ul_list_for_each_cut(evc_tx_list, hub, link){
255 evc_link_inc_refcnt(link);
257 evc_link_delete(link);
258 evc_link_dec_refcnt(link);
263 int evc_prop_link_skip(evc_link_t *link)
265 if(link->dead || link->blocked || link->delete_pend) return 1;
266 if(!link->recursive && link->taken) return 1;
271 * evc_tx_hub_propagate - Propagate Event to Links Destinations
272 * @hub: pointer to the &evc_tx_hub_t type hub
273 * @args: pointer to the variable arguments list
275 * The function propagates event to the connected links,
276 * it skips links marked as @dead, @blocked or @delete_pend.
277 * If the link is not marked as @recursive, it ensures, that
278 * link is not called twice.
280 void evc_tx_hub_propagate(evc_tx_hub_t *hub, va_list args)
282 evc_link_t *link, *next;
284 link=evc_tx_list_first(hub);
287 if(!evc_prop_link_skip(link)) break;
288 link=evc_tx_list_next(hub,link);
290 evc_link_inc_refcnt(link); /*prevents dispose of the link*/
291 link->taken++; /*prevents delete of the link from the hub*/
294 va_copy(args_copy, args);
295 link->propagate(link, args_copy);
298 if(link->src.hub == hub){ /*check for correct hub relation*/
301 next=evc_tx_list_next(hub,next);
303 if(!evc_prop_link_skip(next)) {
304 evc_link_inc_refcnt(next); /*prevents dispose of the link*/
305 next->taken++; /*prevents delete of the link from the hub*/
310 /* link is already disconnected from the hub,
311 result of evc_tx_hub_done */
314 if(!(--link->taken)){
315 if(link->delete_pend)
316 evc_link_delete(link); /*process pending delete*/
318 evc_link_dec_refcnt(link); /*can lead to dispose of the link*/
323 * evc_tx_hub_emit - Emits Event to Hub
324 * @hub: pointer to the &evc_tx_hub_t type hub
326 * The function hands over arguments to evc_tx_hub_propagate()
329 void evc_tx_hub_emit(evc_tx_hub_t *hub, ...)
333 va_start (args, hub);
334 evc_tx_hub_propagate(hub, args);
338 int evc_tx_hub_eol_weakptr(evc_tx_hub_t *hub, void **weakptr)
340 evc_link_t *link, *next;
343 link=evc_tx_list_first(hub);
345 next=evc_tx_list_next(hub,link);
346 if(link->standalone && (link->dst.standalone.weakptr==weakptr)){
347 link->dst.standalone.weakptr=NULL;
348 evc_link_delete(link);
358 * evc_rx_hub_init - Initializes Event Receiption Hub
359 * @hub: pointer to the &evc_rx_hub_t type hub
360 * @rx_fnc: pointer to the function invoked by event reception
361 * @context: context for the rx_fnc() function invocation
363 * Return Value: negative return value indicates failure.
365 int evc_rx_hub_init(evc_rx_hub_t *hub, evc_rx_fnc_t *rx_fnc, void *context)
367 evc_rx_list_init_head(hub);
369 hub->context=context;
374 * evc_rx_hub_disconnect_all - Disconnect Receiption Hub from All Sources
375 * @hub: pointer to the &evc_rx_hub_t type hub
377 void evc_rx_hub_disconnect_all(evc_rx_hub_t *hub)
380 ul_list_for_each_cut(evc_rx_list, hub, link){
381 evc_link_inc_refcnt(link);
382 link->dst.multi.hub=NULL;
383 evc_link_delete(link);
384 evc_link_dec_refcnt(link);
389 * evc_rx_hub_done - Finalize Event Receiption Hub
390 * @hub: pointer to the &evc_rx_hub_t type hub
392 void evc_rx_hub_done(evc_rx_hub_t *hub)
394 evc_rx_hub_disconnect_all(hub);
397 /*===========================================================*/
398 /* arguments propagation functions */
400 typedef int evc_fnc_propagate_i_p_l(void *, long);
402 int evc_link_propagate_i_p_l(evc_link_t *link, va_list args)
405 evc_fnc_propagate_i_p_l *fnc;
408 if(link->standalone && link->dst.standalone.weakptr){
409 *link->dst.standalone.weakptr=NULL;
410 link->dst.standalone.weakptr=NULL;
414 if(link->standalone){
415 fnc=(evc_fnc_propagate_i_p_l*)link->dst.standalone.rx_fnc;
416 context=link->dst.standalone.context;
418 if(!link->dst.multi.hub) return 0;
419 fnc=(evc_fnc_propagate_i_p_l*)link->dst.multi.hub->rx_fnc;
420 context=link->dst.multi.hub->context;
423 fnc(context, va_arg(args, long));