]>
git.zerfleddert.de Git - micropolis/blob - src/tk/tkpresrv.c
a7e0c053a459326b2ef19272975478bedba38baa
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.
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.
20 static char rcsid
[] = "$Header: /user6/ouster/wish/RCS/tkPreserve.c,v 1.6 92/06/15 13:44:51 ouster Exp $ SPRITE (Berkeley)";
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.
33 ClientData clientData
; /* Address of preserved block. */
34 int refCount
; /* Number of Tk_Preserve calls in effect
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. */
43 static Reference
*refArray
; /* First in array of references. */
44 static int spaceAvl
= 0; /* Total number of structures available
46 static int inUse
= 0; /* Count of structures currently in use
48 #define INITIAL_SIZE 2
51 *----------------------------------------------------------------------
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.
63 * Information is retained so that the block of memory will
64 * not be freed until at least the matching call to Tk_Release.
66 *----------------------------------------------------------------------
70 Tk_Preserve(clientData
)
71 ClientData clientData
; /* Pointer to malloc'ed block of memory. */
73 register Reference
*refPtr
;
77 * See if there is already a reference for this pointer. If so,
78 * just increment its reference count.
81 for (i
= 0, refPtr
= refArray
; i
< inUse
; i
++, refPtr
++) {
82 if (refPtr
->clientData
== clientData
) {
89 * Make a reference array if it doesn't already exist, or make it
90 * bigger if it is full.
93 if (inUse
== spaceAvl
) {
95 refArray
= (Reference
*) ckalloc((unsigned)
96 (INITIAL_SIZE
*sizeof(Reference
)));
97 spaceAvl
= INITIAL_SIZE
;
101 new = (Reference
*) ckalloc((unsigned)
102 (2*spaceAvl
*sizeof(Reference
)));
103 memcpy((VOID
*) new, (VOID
*) refArray
, spaceAvl
*sizeof(Reference
));
104 ckfree((char *) refArray
);
111 * Make a new entry for the new reference.
114 refPtr
= &refArray
[inUse
];
115 refPtr
->clientData
= clientData
;
116 refPtr
->refCount
= 1;
117 refPtr
->mustFree
= 0;
122 *----------------------------------------------------------------------
126 * This procedure is called to cancel a previous call to
127 * Tk_Preserve, thereby allowing a block of memory to be
128 * freed (if no one else cares about it).
134 * If Tk_EventuallyFree has been called for clientData, and if
135 * no other call to Tk_Preserve is still in effect, the block of
138 *----------------------------------------------------------------------
142 Tk_Release(clientData
)
143 ClientData clientData
; /* Pointer to malloc'ed block of memory. */
145 register Reference
*refPtr
;
148 for (i
= 0, refPtr
= refArray
; i
< inUse
; i
++, refPtr
++) {
149 if (refPtr
->clientData
!= clientData
) {
153 if (refPtr
->refCount
== 0) {
154 if (refPtr
->mustFree
) {
155 if (refPtr
->freeProc
== (Tk_FreeProc
*) free
) {
156 ckfree((char *) refPtr
->clientData
);
158 (*refPtr
->freeProc
)(refPtr
->clientData
);
163 * Copy down all of the trailing reference in the array
164 * to cover up the hole left by the unused reference.
169 memcpy((VOID
*) &refArray
[i
], (VOID
*) &refArray
[i
+1],
170 (inUse
-i
)*sizeof(Reference
));
177 * Reference not found. This is a bug in the caller.
180 panic("Tk_Release couldn't find reference for 0x%x", clientData
);
184 *----------------------------------------------------------------------
186 * Tk_EventuallyFree --
188 * Free up a block of memory, unless a call to Tk_Preserve is in
189 * effect for that block. In this case, defer the free until all
190 * calls to Tk_Preserve have been undone by matching calls to
197 * Ptr may be released by calling free().
199 *----------------------------------------------------------------------
203 Tk_EventuallyFree(clientData
, freeProc
)
204 ClientData clientData
; /* Pointer to malloc'ed block of memory. */
205 Tk_FreeProc
*freeProc
; /* Procedure to actually do free. */
207 register Reference
*refPtr
;
211 * See if there is a reference for this pointer. If so, set its
212 * "mustFree" flag (the flag had better not be set already!).
215 for (i
= 0, refPtr
= refArray
; i
< inUse
; i
++, refPtr
++) {
216 if (refPtr
->clientData
!= clientData
) {
219 if (refPtr
->mustFree
) {
220 panic("Tk_EventuallyFree called twice for 0x%x\n", clientData
);
222 refPtr
->mustFree
= 1;
223 refPtr
->freeProc
= freeProc
;
228 * No reference for this block. Free it now.
231 if (freeProc
== (Tk_FreeProc
*) free
) {
232 ckfree((char *) clientData
);
234 (*freeProc
)(clientData
);