]> cvs.zerfleddert.de Git - micropolis/blob - src/tk/tkpresrv.c
Fixes for compilation with gcc 15
[micropolis] / src / tk / tkpresrv.c
1 /*
2 * tkPreserve.c --
3 *
4 * This file contains a collection of procedures that are used
5 * to make sure that widget records and other data structures
6 * aren't reallocated when there are nested procedures that
7 * depend on their existence.
8 *
9 * Copyright 1991 Regents of the University of California
10 * Permission to use, copy, modify, and distribute this
11 * software and its documentation for any purpose and without
12 * fee is hereby granted, provided that this copyright
13 * notice appears in all copies. The University of California
14 * makes no representations about the suitability of this
15 * software for any purpose. It is provided "as is" without
16 * express or implied warranty.
17 */
18
19 #ifndef lint
20 static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkPreserve.c,v 1.6 92/06/15 13:44:51 ouster Exp $ SPRITE (Berkeley)";
21 #endif /* not lint */
22
23 #include "tkconfig.h"
24 #include "tk.h"
25
26 /*
27 * The following data structure is used to keep track of all the
28 * Tk_Preserve calls that are still in effect. It grows as needed
29 * to accommodate any number of calls in effect.
30 */
31
32 typedef struct {
33 ClientData clientData; /* Address of preserved block. */
34 int refCount; /* Number of Tk_Preserve calls in effect
35 * for block. */
36 int mustFree; /* Non-zero means Tk_EventuallyFree was
37 * called while a Tk_Preserve call was in
38 * effect, so the structure must be freed
39 * when refCount becomes zero. */
40 Tk_FreeProc *freeProc; /* Procedure to call to free. */
41 } Reference;
42
43 static Reference *refArray; /* First in array of references. */
44 static int spaceAvl = 0; /* Total number of structures available
45 * at *firstRefPtr. */
46 static int inUse = 0; /* Count of structures currently in use
47 * in refArray. */
48 #define INITIAL_SIZE 2
49 \f
50 /*
51 *----------------------------------------------------------------------
52 *
53 * Tk_Preserve --
54 *
55 * This procedure is used by a procedure to declare its interest
56 * in a particular block of memory, so that the block will not be
57 * reallocated until a matching call to Tk_Release has been made.
58 *
59 * Results:
60 * None.
61 *
62 * Side effects:
63 * Information is retained so that the block of memory will
64 * not be freed until at least the matching call to Tk_Release.
65 *
66 *----------------------------------------------------------------------
67 */
68
69 void
70 Tk_Preserve(
71 ClientData clientData /* Pointer to malloc'ed block of memory. */
72 )
73 {
74 register Reference *refPtr;
75 int i;
76
77 /*
78 * See if there is already a reference for this pointer. If so,
79 * just increment its reference count.
80 */
81
82 for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {
83 if (refPtr->clientData == clientData) {
84 refPtr->refCount++;
85 return;
86 }
87 }
88
89 /*
90 * Make a reference array if it doesn't already exist, or make it
91 * bigger if it is full.
92 */
93
94 if (inUse == spaceAvl) {
95 if (spaceAvl == 0) {
96 refArray = (Reference *) ckalloc((unsigned)
97 (INITIAL_SIZE*sizeof(Reference)));
98 spaceAvl = INITIAL_SIZE;
99 } else {
100 Reference *new;
101
102 new = (Reference *) ckalloc((unsigned)
103 (2*spaceAvl*sizeof(Reference)));
104 memcpy((VOID *) new, (VOID *) refArray, spaceAvl*sizeof(Reference));
105 ckfree((char *) refArray);
106 refArray = new;
107 spaceAvl *= 2;
108 }
109 }
110
111 /*
112 * Make a new entry for the new reference.
113 */
114
115 refPtr = &refArray[inUse];
116 refPtr->clientData = clientData;
117 refPtr->refCount = 1;
118 refPtr->mustFree = 0;
119 inUse += 1;
120 }
121 \f
122 /*
123 *----------------------------------------------------------------------
124 *
125 * Tk_Release --
126 *
127 * This procedure is called to cancel a previous call to
128 * Tk_Preserve, thereby allowing a block of memory to be
129 * freed (if no one else cares about it).
130 *
131 * Results:
132 * None.
133 *
134 * Side effects:
135 * If Tk_EventuallyFree has been called for clientData, and if
136 * no other call to Tk_Preserve is still in effect, the block of
137 * memory is freed.
138 *
139 *----------------------------------------------------------------------
140 */
141
142 void
143 Tk_Release(
144 ClientData clientData /* Pointer to malloc'ed block of memory. */
145 )
146 {
147 register Reference *refPtr;
148 int i;
149
150 for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {
151 if (refPtr->clientData != clientData) {
152 continue;
153 }
154 refPtr->refCount--;
155 if (refPtr->refCount == 0) {
156 if (refPtr->mustFree) {
157 if (refPtr->freeProc == (Tk_FreeProc *) free) {
158 ckfree((char *) refPtr->clientData);
159 } else {
160 (*refPtr->freeProc)(refPtr->clientData);
161 }
162 }
163
164 /*
165 * Copy down all of the trailing reference in the array
166 * to cover up the hole left by the unused reference.
167 */
168
169 inUse--;
170 if (i != inUse) {
171 memcpy((VOID *) &refArray[i], (VOID *) &refArray[i+1],
172 (inUse-i)*sizeof(Reference));
173 }
174 }
175 return;
176 }
177
178 /*
179 * Reference not found. This is a bug in the caller.
180 */
181
182 panic("Tk_Release couldn't find reference for 0x%x", clientData);
183 }
184 \f
185 /*
186 *----------------------------------------------------------------------
187 *
188 * Tk_EventuallyFree --
189 *
190 * Free up a block of memory, unless a call to Tk_Preserve is in
191 * effect for that block. In this case, defer the free until all
192 * calls to Tk_Preserve have been undone by matching calls to
193 * Tk_Release.
194 *
195 * Results:
196 * None.
197 *
198 * Side effects:
199 * Ptr may be released by calling free().
200 *
201 *----------------------------------------------------------------------
202 */
203
204 void
205 Tk_EventuallyFree(
206 ClientData clientData, /* Pointer to malloc'ed block of memory. */
207 Tk_FreeProc *freeProc /* Procedure to actually do free. */
208 )
209 {
210 register Reference *refPtr;
211 int i;
212
213 /*
214 * See if there is a reference for this pointer. If so, set its
215 * "mustFree" flag (the flag had better not be set already!).
216 */
217
218 for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {
219 if (refPtr->clientData != clientData) {
220 continue;
221 }
222 if (refPtr->mustFree) {
223 panic("Tk_EventuallyFree called twice for 0x%x\n", clientData);
224 }
225 refPtr->mustFree = 1;
226 refPtr->freeProc = freeProc;
227 return;
228 }
229
230 /*
231 * No reference for this block. Free it now.
232 */
233
234 if (freeProc == (Tk_FreeProc *) free) {
235 ckfree((char *) clientData);
236 } else {
237 (*freeProc)(clientData);
238 }
239 }
Impressum, Datenschutz