Annotation of micropolis/src/tk/tkpresrv.c, revision 1.1.1.1

1.1       root        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: 
                     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(clientData)
                     71:     ClientData clientData;     /* Pointer to malloc'ed block of memory. */
                     72: {
                     73:     register Reference *refPtr;
                     74:     int i;
                     75: 
                     76:     /*
                     77:      * See if there is already a reference for this pointer.  If so,
                     78:      * just increment its reference count.
                     79:      */
                     80: 
                     81:     for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {
                     82:        if (refPtr->clientData == clientData) {
                     83:            refPtr->refCount++;
                     84:            return;
                     85:        }
                     86:     }
                     87: 
                     88:     /*
                     89:      * Make a reference array if it doesn't already exist, or make it
                     90:      * bigger if it is full.
                     91:      */
                     92: 
                     93:     if (inUse == spaceAvl) {
                     94:        if (spaceAvl == 0) {
                     95:            refArray = (Reference *) ckalloc((unsigned)
                     96:                    (INITIAL_SIZE*sizeof(Reference)));
                     97:            spaceAvl = INITIAL_SIZE;
                     98:        } else {
                     99:            Reference *new;
                    100: 
                    101:            new = (Reference *) ckalloc((unsigned)
                    102:                    (2*spaceAvl*sizeof(Reference)));
                    103:            memcpy((VOID *) new, (VOID *) refArray, spaceAvl*sizeof(Reference));
                    104:            ckfree((char *) refArray);
                    105:            refArray = new;
                    106:            spaceAvl *= 2;
                    107:        }
                    108:     }
                    109: 
                    110:     /*
                    111:      * Make a new entry for the new reference.
                    112:      */
                    113: 
                    114:     refPtr = &refArray[inUse];
                    115:     refPtr->clientData = clientData;
                    116:     refPtr->refCount = 1;
                    117:     refPtr->mustFree = 0;
                    118:     inUse += 1;
                    119: }
                    120: 
                    121: /*
                    122:  *----------------------------------------------------------------------
                    123:  *
                    124:  * Tk_Release --
                    125:  *
                    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).
                    129:  *
                    130:  * Results:
                    131:  *     None.
                    132:  *
                    133:  * Side effects:
                    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
                    136:  *     memory is freed.
                    137:  *
                    138:  *----------------------------------------------------------------------
                    139:  */
                    140: 
                    141: void
                    142: Tk_Release(clientData)
                    143:     ClientData clientData;     /* Pointer to malloc'ed block of memory. */
                    144: {
                    145:     register Reference *refPtr;
                    146:     int i;
                    147: 
                    148:     for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {
                    149:        if (refPtr->clientData != clientData) {
                    150:            continue;
                    151:        }
                    152:        refPtr->refCount--;
                    153:        if (refPtr->refCount == 0) {
                    154:            if (refPtr->mustFree) {
                    155:                if (refPtr->freeProc == (Tk_FreeProc *) free) {
                    156:                    ckfree((char *) refPtr->clientData);
                    157:                } else {
                    158:                    (*refPtr->freeProc)(refPtr->clientData);
                    159:                }
                    160:            }
                    161: 
                    162:            /*
                    163:             * Copy down all of the trailing reference in the array
                    164:             * to cover up the hole left by the unused reference.
                    165:             */
                    166: 
                    167:            inUse--;
                    168:            if (i != inUse) {
                    169:                memcpy((VOID *) &refArray[i], (VOID *) &refArray[i+1],
                    170:                        (inUse-i)*sizeof(Reference));
                    171:            }
                    172:        }
                    173:        return;
                    174:     }
                    175: 
                    176:     /*
                    177:      * Reference not found.  This is a bug in the caller.
                    178:      */
                    179: 
                    180:     panic("Tk_Release couldn't find reference for 0x%x", clientData);
                    181: }
                    182: 
                    183: /*
                    184:  *----------------------------------------------------------------------
                    185:  *
                    186:  * Tk_EventuallyFree --
                    187:  *
                    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
                    191:  *     Tk_Release.
                    192:  *
                    193:  * Results:
                    194:  *     None.
                    195:  *
                    196:  * Side effects:
                    197:  *     Ptr may be released by calling free().
                    198:  *
                    199:  *----------------------------------------------------------------------
                    200:  */
                    201: 
                    202: void
                    203: Tk_EventuallyFree(clientData, freeProc)
                    204:     ClientData clientData;     /* Pointer to malloc'ed block of memory. */
                    205:     Tk_FreeProc *freeProc;     /* Procedure to actually do free. */
                    206: {
                    207:     register Reference *refPtr;
                    208:     int i;
                    209: 
                    210:     /*
                    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!).
                    213:      */
                    214: 
                    215:     for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {
                    216:        if (refPtr->clientData != clientData) {
                    217:            continue;
                    218:        }
                    219:        if (refPtr->mustFree) {
                    220:            panic("Tk_EventuallyFree called twice for 0x%x\n", clientData);
                    221:         }
                    222:         refPtr->mustFree = 1;
                    223:        refPtr->freeProc = freeProc;
                    224:         return;
                    225:     }
                    226: 
                    227:     /*
                    228:      * No reference for this block.  Free it now.
                    229:      */
                    230: 
                    231:     if (freeProc == (Tk_FreeProc *) free) {
                    232:        ckfree((char *) clientData);
                    233:     } else {
                    234:        (*freeProc)(clientData);
                    235:     }
                    236: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.