Annotation of micropolis/src/tk/tkpresrv.c, revision 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.