⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tclmacalloc.c

📁 tcl是工具命令语言
💻 C
字号:
/* * tclMacAlloc.c -- * *	This is a very fast storage allocator.  It allocates blocks of a *	small number of different sizes, and keeps free lists of each size. *	Blocks that don't exactly fit are passed up to the next larger size. *	Blocks over a certain size are directly allocated by calling NewPtr. * * Copyright (c) 1983 Regents of the University of California. * Copyright (c) 1996-1997 Sun Microsystems, Inc. * * Portions contributed by Chris Kingsley, Jack Jansen and Ray Johnson *. * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclMacAlloc.c,v 1.5 2001/11/23 01:27:09 das Exp $ */#include "tclInt.h"#include "tclMacInt.h"#include <Memory.h>#include <Gestalt.h>#include <stdlib.h>#include <string.h>/* * Flags that are used by ConfigureMemory to define how the allocator * should work.  They can be or'd together. */#define MEMORY_ALL_SYS 1	/* All memory should come from the systemheap. */#define MEMORY_DONT_USE_TEMPMEM 2	/* Don't use temporary memory but system memory. *//* * Amount of space to leave in the application heap for the Toolbox to work. */#define TOOLBOX_SPACE (512 * 1024)static int memoryFlags = 0;static Handle toolGuardHandle = NULL;				/* This handle must be around so that we don't				 * have NewGWorld failures. This handle is				 * purgeable. Before we allocate any blocks,				 * we see if this handle is still around.				 * If it is not, then we try to get it again.				 * If we can get it, we lock it and try				 * to do the normal allocation, unlocking on				 * the way out. If we can't, we go to the				 * system heap directly. */static int tclUseMemTracking = 0; /* Are we tracking memory allocations?								   * On recent versions of the MacOS this								   * is no longer necessary, as we can use								   * temporary memory which is freed by the								   * OS after a quit or crash. */								   static size_t tclExtraHdlSize = 0; /* Size of extra memory allocated at the start									* of each block when using memory tracking									* ( == 0 otherwise) *//* * The following typedef and variable are used to keep track of memory * blocks that are allocated directly from the System Heap.  These chunks * of memory must always be freed - even if we crash. */typedef struct listEl {    Handle		memoryHandle;    struct listEl *	next;    struct listEl *	prec;} ListEl;static ListEl * systemMemory = NULL;static ListEl * appMemory = NULL;/* * Prototypes for functions used only in this file. */static pascal void	CleanUpExitProc _ANSI_ARGS_((void));void 			ConfigureMemory _ANSI_ARGS_((int flags));void			FreeAllMemory _ANSI_ARGS_((void));/* *---------------------------------------------------------------------- * * TclpSysRealloc -- * *	This function reallocates a chunk of system memory.  If the *	chunk is already big enough to hold the new block, then no *	allocation happens. * * Results: *	Returns a pointer to the newly allocated block. * * Side effects: *	May copy the contents of the original block to the new block *	and deallocate the original block. * *---------------------------------------------------------------------- */VOID *TclpSysRealloc(    VOID *oldPtr,		/* Original block */    unsigned int size)		/* New size of block. */{    Handle hand;    void *newPtr;    int maxsize;    OSErr err;	if (tclUseMemTracking) {    hand = ((ListEl *) ((Ptr) oldPtr - tclExtraHdlSize))->memoryHandle;    } else {    hand = RecoverHandle((Ptr) oldPtr);	}    maxsize = GetHandleSize(hand) - sizeof(Handle);    if (maxsize < size) {    HUnlock(hand);    SetHandleSize(hand,size + tclExtraHdlSize);    err = MemError();    HLock(hand);    if(err==noErr){    	newPtr=(*hand + tclExtraHdlSize);    } else {	newPtr = TclpSysAlloc(size, 1);	if(newPtr!=NULL) {	memmove(newPtr, oldPtr, maxsize);	TclpSysFree(oldPtr);	}	}    } else {	newPtr = oldPtr;    }    return newPtr;}/* *---------------------------------------------------------------------- * * TclpSysAlloc -- * *	Allocate a new block of memory free from the System. * * Results: *	Returns a pointer to a new block of memory. * * Side effects: *	May obtain memory from app or sys space.  Info is added to *	overhead lists etc. * *---------------------------------------------------------------------- */VOID *TclpSysAlloc(    long size,		/* Size of block to allocate. */    int isBin)		/* Is this a bin allocation? */{    Handle hand = NULL;    ListEl * newMemoryRecord;	int isSysMem = 0;	static int initialized=0;		if (!initialized) {	long response = 0;	OSErr err = noErr;	int useTempMem = 0;		/* Check if we can use temporary memory */	initialized=1;	err = Gestalt(gestaltOSAttr, &response);	if (err == noErr) {    	useTempMem = response & (1 << gestaltRealTempMemory);	}	tclUseMemTracking = !useTempMem || (memoryFlags & MEMORY_DONT_USE_TEMPMEM);	if(tclUseMemTracking) {	    tclExtraHdlSize = sizeof(ListEl);	    /*	     * We are allocating memory directly from the system	     * heap. We need to install an exit handle 	     * to ensure the memory is cleaned up.	     */	    TclMacInstallExitToShellPatch(CleanUpExitProc);	}	}    if (!(memoryFlags & MEMORY_ALL_SYS)) {    	/*    	 * If the guard handle has been purged, throw it away and try    	 * to allocate it again.    	 */    	if ((toolGuardHandle != NULL) && (*toolGuardHandle == NULL)) {    	    DisposeHandle(toolGuardHandle);    	    toolGuardHandle = NULL;    	}    	/*    	 * If we have never allocated the guard handle, or it was purged    	 * and thrown away, then try to allocate it again.    	 */    	if (toolGuardHandle == NULL) {    	    toolGuardHandle = NewHandle(TOOLBOX_SPACE);    	    if (toolGuardHandle != NULL) {    	    	HLock(toolGuardHandle);    	    	HPurge(toolGuardHandle);    	    }    	}	/*	 * If we got the handle, lock it and do our allocation.	 */    	if (toolGuardHandle != NULL) {    	    HLock(toolGuardHandle);	    hand = NewHandle(size + tclExtraHdlSize);	    HUnlock(toolGuardHandle);	}    }    if (hand == NULL) {	/*	 * Ran out of memory in application space.  Lets try to get	 * more memory from system.  Otherwise, we return NULL to	 * denote failure.	 */	if(!tclUseMemTracking) {		/* Use Temporary Memory instead of System Heap when available */		OSErr err;		isBin = 1; /* always HLockHi TempMemHandles */		hand = TempNewHandle(size + tclExtraHdlSize,&err);		if(err!=noErr) { hand=NULL; }	} else {	/* Use system heap when tracking memory */	isSysMem=1;	isBin = 0;	hand = NewHandleSys(size + tclExtraHdlSize);	}	}	if (hand == NULL) {	    return NULL;	}    if (isBin) {	HLockHi(hand);    } else {	HLock(hand);    }	if(tclUseMemTracking) {	/* Only need to do this when tracking memory */	newMemoryRecord = (ListEl *) *hand;	newMemoryRecord->memoryHandle = hand;	newMemoryRecord->prec = NULL;	if(isSysMem) {	newMemoryRecord->next = systemMemory;	systemMemory = newMemoryRecord;	} else {	newMemoryRecord->next = appMemory;	appMemory = newMemoryRecord;	}	if(newMemoryRecord->next!=NULL) {	newMemoryRecord->next->prec=newMemoryRecord;	}	}	    return (*hand + tclExtraHdlSize);}/* *---------------------------------------------------------------------- * * TclpSysFree -- * *	Free memory that we allocated back to the system. * * Results: *	None. * * Side effects: *	Memory is freed. * *---------------------------------------------------------------------- */voidTclpSysFree(    void * ptr)		/* Free this system memory. */{	if(tclUseMemTracking) {    /* Only need to do this when tracking memory */    ListEl *memRecord;    memRecord = (ListEl *) ((Ptr) ptr - tclExtraHdlSize);    /* Remove current record from linked list */    if(memRecord->next!=NULL) {    	memRecord->next->prec=memRecord->prec;    }    if(memRecord->prec!=NULL) {    	memRecord->prec->next=memRecord->next;    }    if(memRecord==appMemory) {    	appMemory=memRecord->next;    } else if(memRecord==systemMemory) {    	systemMemory=memRecord->next;    }    DisposeHandle(memRecord->memoryHandle);	} else {    DisposeHandle(RecoverHandle((Ptr) ptr));	}}/* *---------------------------------------------------------------------- * * CleanUpExitProc -- * *	This procedure is invoked as an exit handler when ExitToShell *	is called.  It removes any memory that was allocated directly *	from the system heap.  This must be called when the application *	quits or the memory will never be freed. * * Results: *	None. * * Side effects: *	May free memory in the system heap. * *---------------------------------------------------------------------- */static pascal voidCleanUpExitProc(){    ListEl * memRecord;    if(tclUseMemTracking) {    /* Only need to do this when tracking memory */    while (systemMemory != NULL) {	memRecord = systemMemory;	systemMemory = memRecord->next;	DisposeHandle(memRecord->memoryHandle);    }    }}/* *---------------------------------------------------------------------- * * FreeAllMemory -- * *	This procedure frees all memory blocks allocated by the memory *	sub-system.  Make sure you don't have any code that references *	any malloced data! * * Results: *	None. * * Side effects: *	Frees all memory allocated by TclpAlloc. * *---------------------------------------------------------------------- */voidFreeAllMemory(){    ListEl * memRecord;	if(tclUseMemTracking) {	/* Only need to do this when tracking memory */    while (systemMemory != NULL) {	memRecord = systemMemory;	systemMemory = memRecord->next;	DisposeHandle(memRecord->memoryHandle);    }    while (appMemory != NULL) {	memRecord = appMemory;	appMemory = memRecord->next;	DisposeHandle(memRecord->memoryHandle);	}    }}/* *---------------------------------------------------------------------- * * ConfigureMemory -- * *	This procedure sets certain flags in this file that control *	how memory is allocated and managed.  This call must be made *	before any call to TclpAlloc is made. * * Results: *	None. * * Side effects: *	Certain state will be changed. * *---------------------------------------------------------------------- */voidConfigureMemory(    int flags)		/* Flags that control memory alloc scheme. */{    memoryFlags = flags;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -