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*/
293 link->propagate(link, args);
295 if(link->src.hub == hub){ /*check for correct hub relation*/
298 next=evc_tx_list_next(hub,next);
300 if(!evc_prop_link_skip(next)) {
301 evc_link_inc_refcnt(next); /*prevents dispose of the link*/
302 next->taken++; /*prevents delete of the link from the hub*/
307 /* link is already disconnected from the hub,
308 result of evc_tx_hub_done */
311 if(!(--link->taken)){
312 if(link->delete_pend)
313 evc_link_delete(link); /*process pending delete*/
315 evc_link_dec_refcnt(link); /*can lead to dispose of the link*/
320 * evc_tx_hub_emit - Emits Event to Hub
321 * @hub: pointer to the &evc_tx_hub_t type hub
323 * The function hands over arguments to evc_tx_hub_propagate()
326 void evc_tx_hub_emit(evc_tx_hub_t *hub, ...)
330 va_start (args, hub);
331 evc_tx_hub_propagate(hub, args);
335 int evc_tx_hub_eol_weakptr(evc_tx_hub_t *hub, void **weakptr)
337 evc_link_t *link, *next;
340 link=evc_tx_list_first(hub);
342 next=evc_tx_list_next(hub,link);
343 if(link->standalone && (link->dst.standalone.weakptr==weakptr)){
344 link->dst.standalone.weakptr=NULL;
345 evc_link_delete(link);
355 * evc_rx_hub_init - Initializes Event Receiption Hub
356 * @hub: pointer to the &evc_rx_hub_t type hub
357 * @rx_fnc: pointer to the function invoked by event reception
358 * @context: context for the rx_fnc() function invocation
360 * Return Value: negative return value indicates failure.
362 int evc_rx_hub_init(evc_rx_hub_t *hub, evc_rx_fnc_t *rx_fnc, void *context)
364 evc_rx_list_init_head(hub);
366 hub->context=context;
371 * evc_rx_hub_disconnect_all - Disconnect Receiption Hub from All Sources
372 * @hub: pointer to the &evc_rx_hub_t type hub
374 void evc_rx_hub_disconnect_all(evc_rx_hub_t *hub)
377 ul_list_for_each_cut(evc_rx_list, hub, link){
378 evc_link_inc_refcnt(link);
379 link->dst.multi.hub=NULL;
380 evc_link_delete(link);
381 evc_link_dec_refcnt(link);
386 * evc_rx_hub_done - Finalize Event Receiption Hub
387 * @hub: pointer to the &evc_rx_hub_t type hub
389 void evc_rx_hub_done(evc_rx_hub_t *hub)
391 evc_rx_hub_disconnect_all(hub);
394 /*===========================================================*/
395 /* arguments propagation functions */
397 typedef int evc_fnc_propagate_i_p_l(void *, long);
399 int evc_link_propagate_i_p_l(evc_link_t *link, va_list args)
402 evc_fnc_propagate_i_p_l *fnc;
405 if(link->standalone && link->dst.standalone.weakptr){
406 *link->dst.standalone.weakptr=NULL;
407 link->dst.standalone.weakptr=NULL;
411 if(link->standalone){
412 fnc=(evc_fnc_propagate_i_p_l*)link->dst.standalone.rx_fnc;
413 context=link->dst.standalone.context;
415 if(!link->dst.multi.hub) return 0;
416 fnc=(evc_fnc_propagate_i_p_l*)link->dst.multi.hub->rx_fnc;
417 context=link->dst.multi.hub->context;
420 fnc(context, va_arg(args, long));