xref: /plan9/sys/src/cmd/gs/src/gsnotify.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gsnotify.c,v 1.5 2002/06/16 05:48:55 lpd Exp $ */
18 /* Notification machinery implementation */
19 #include "gx.h"
20 #include "gserrors.h"
21 #include "gsstruct.h"
22 #include "gsnotify.h"
23 
24 /* GC descriptors */
25 private_st_gs_notify_registration();
26 public_st_gs_notify_list();
27 
28 /* Initialize a notification list. */
29 void
gs_notify_init(gs_notify_list_t * nlist,gs_memory_t * mem)30 gs_notify_init(gs_notify_list_t *nlist, gs_memory_t *mem)
31 {
32     nlist->first = 0;
33     nlist->memory = mem;
34 }
35 
36 /* Register a client. */
37 int
gs_notify_register(gs_notify_list_t * nlist,gs_notify_proc_t proc,void * proc_data)38 gs_notify_register(gs_notify_list_t *nlist, gs_notify_proc_t proc,
39 		   void *proc_data)
40 {
41     gs_notify_registration_t *nreg =
42 	gs_alloc_struct(nlist->memory, gs_notify_registration_t,
43 			&st_gs_notify_registration, "gs_notify_register");
44 
45     if (nreg == 0)
46 	return_error(gs_error_VMerror);
47     nreg->proc = proc;
48     nreg->proc_data = proc_data;
49     nreg->next = nlist->first;
50     nlist->first = nreg;
51     return 0;
52 }
53 
54 /*
55  * Unregister a client.  Return 1 if the client was registered, 0 if not.
56  * If proc_data is 0, unregister all registrations of that proc; otherwise,
57  * unregister only the registration of that procedure with that proc_data.
58  */
59 private void
no_unreg_proc(void * pdata)60 no_unreg_proc(void *pdata)
61 {
62 }
63 int
gs_notify_unregister_calling(gs_notify_list_t * nlist,gs_notify_proc_t proc,void * proc_data,void (* unreg_proc)(void * pdata))64 gs_notify_unregister_calling(gs_notify_list_t *nlist, gs_notify_proc_t proc,
65 			     void *proc_data,
66 			     void (*unreg_proc)(void *pdata))
67 {
68     gs_notify_registration_t **prev = &nlist->first;
69     gs_notify_registration_t *cur;
70     bool found = 0;
71 
72     while ((cur = *prev) != 0)
73 	if (cur->proc == proc &&
74 	    (proc_data == 0 || cur->proc_data == proc_data)
75 	    ) {
76 	    *prev = cur->next;
77 	    unreg_proc(cur->proc_data);
78 	    gs_free_object(nlist->memory, cur, "gs_notify_unregister");
79 	    found = 1;
80 	} else
81 	    prev = &cur->next;
82     return found;
83 }
84 int
gs_notify_unregister(gs_notify_list_t * nlist,gs_notify_proc_t proc,void * proc_data)85 gs_notify_unregister(gs_notify_list_t *nlist, gs_notify_proc_t proc,
86 		     void *proc_data)
87 {
88     return gs_notify_unregister_calling(nlist, proc, proc_data, no_unreg_proc);
89 }
90 
91 /*
92  * Notify the clients on a list.  If an error occurs, return the first
93  * error code, but notify all clients regardless.
94  */
95 int
gs_notify_all(gs_notify_list_t * nlist,void * event_data)96 gs_notify_all(gs_notify_list_t *nlist, void *event_data)
97 {
98     gs_notify_registration_t *cur;
99     gs_notify_registration_t *next;
100     int ecode = 0;
101 
102     for (next = nlist->first; (cur = next) != 0;) {
103 	int code;
104 
105 	next = cur->next;
106 	code = cur->proc(cur->proc_data, event_data);
107 	if (code < 0 && ecode == 0)
108 	    ecode = code;
109     }
110     return ecode;
111 }
112 
113 /* Release a notification list. */
114 void
gs_notify_release(gs_notify_list_t * nlist)115 gs_notify_release(gs_notify_list_t *nlist)
116 {
117     gs_memory_t *mem = nlist->memory;
118 
119     while (nlist->first) {
120 	gs_notify_registration_t *next = nlist->first->next;
121 
122 	gs_free_object(mem, nlist->first, "gs_notify_release");
123 	nlist->first = next;
124     }
125 }
126