]>
cvs.zerfleddert.de Git - micropolis/blob - src/tk/tkpresrv.c
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 *----------------------------------------------------------------------
71 ClientData clientData
/* Pointer to malloc'ed block of memory. */
74 register Reference
*refPtr
;
78 * See if there is already a reference for this pointer. If so,
79 * just increment its reference count.
82 for (i
= 0, refPtr
= refArray
; i
< inUse
; i
++, refPtr
++) {
83 if (refPtr
->clientData
== clientData
) {
90 * Make a reference array if it doesn't already exist, or make it
91 * bigger if it is full.
94 if (inUse
== spaceAvl
) {
96 refArray
= (Reference
*) ckalloc((unsigned)
97 (INITIAL_SIZE
*sizeof(Reference
)));
98 spaceAvl
= INITIAL_SIZE
;
102 new = (Reference
*) ckalloc((unsigned)
103 (2*spaceAvl
*sizeof(Reference
)));
104 memcpy((VOID
*) new, (VOID
*) refArray
, spaceAvl
*sizeof(Reference
));
105 ckfree((char *) refArray
);
112 * Make a new entry for the new reference.
115 refPtr
= &refArray
[inUse
];
116 refPtr
->clientData
= clientData
;
117 refPtr
->refCount
= 1;
118 refPtr
->mustFree
= 0;
123 *----------------------------------------------------------------------
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).
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
139 *----------------------------------------------------------------------
144 ClientData clientData
/* Pointer to malloc'ed block of memory. */
147 register Reference
*refPtr
;
150 for (i
= 0, refPtr
= refArray
; i
< inUse
; i
++, refPtr
++) {
151 if (refPtr
->clientData
!= clientData
) {
155 if (refPtr
->refCount
== 0) {
156 if (refPtr
->mustFree
) {
157 if (refPtr
->freeProc
== (Tk_FreeProc
*) free
) {
158 ckfree((char *) refPtr
->clientData
);
160 (*refPtr
->freeProc
)(refPtr
->clientData
);
165 * Copy down all of the trailing reference in the array
166 * to cover up the hole left by the unused reference.
171 memcpy((VOID
*) &refArray
[i
], (VOID
*) &refArray
[i
+1],
172 (inUse
-i
)*sizeof(Reference
));
179 * Reference not found. This is a bug in the caller.
182 panic("Tk_Release couldn't find reference for 0x%x", clientData
);
186 *----------------------------------------------------------------------
188 * Tk_EventuallyFree --
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
199 * Ptr may be released by calling free().
201 *----------------------------------------------------------------------
206 ClientData clientData
, /* Pointer to malloc'ed block of memory. */
207 Tk_FreeProc
*freeProc
/* Procedure to actually do free. */
210 register Reference
*refPtr
;
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!).
218 for (i
= 0, refPtr
= refArray
; i
< inUse
; i
++, refPtr
++) {
219 if (refPtr
->clientData
!= clientData
) {
222 if (refPtr
->mustFree
) {
223 panic("Tk_EventuallyFree called twice for 0x%x\n", clientData
);
225 refPtr
->mustFree
= 1;
226 refPtr
->freeProc
= freeProc
;
231 * No reference for this block. Free it now.
234 if (freeProc
== (Tk_FreeProc
*) free
) {
235 ckfree((char *) clientData
);
237 (*freeProc
)(clientData
);