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