📄 utility.c
字号:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.05 04/09/97 */ /* */ /* UTILITY MODULE */ /*******************************************************//*************************************************************//* Purpose: Provides a set of utility functions useful to *//* other modules. Primarily these are the functions for *//* handling periodic garbage collection and appending *//* string data. *//* *//* Principal Programmer(s): *//* Gary D. Riley *//* *//* Contributing Programmer(s): *//* Brian Donnell *//* *//* Revision History: *//* *//*************************************************************/#define _UTILITY_SOURCE_#include "setup.h"#if ANSI_COMPILER#include <ctype.h>#include <stdlib.h>#endif#include <stdio.h>#define _CLIPS_STDIO_#include <string.h>#include <math.h>#include "clipsmem.h"#include "evaluatn.h"#include "multifld.h"#include "utility.h"#define MAX_EPHEMERAL_COUNT 1000L#define MAX_EPHEMERAL_SIZE 10240L#define COUNT_INCREMENT 1000L#define SIZE_INCREMENT 10240Lstruct cleanupFunction { char *name;#if ANSI_COMPILER VOID (*ip)(void);#else VOID (*ip)();#endif int priority; struct cleanupFunction *next; };/***************************************//* LOCAL INTERNAL FUNCTION DEFINITIONS *//***************************************/#if ANSI_COMPILER static BOOLEAN AddCPFunction(char *,VOID (*)(void),int,struct cleanupFunction **); static BOOLEAN RemoveCPFunction(char *,struct cleanupFunction **);#else static BOOLEAN AddCPFunction(); static BOOLEAN RemoveCPFunction();#endif/***************************************//* LOCAL INTERNAL VARIABLE DEFINITIONS *//***************************************/ static struct cleanupFunction *ListOfCleanupFunctions = NULL; static struct cleanupFunction *ListOfPeriodicFunctions = NULL;/****************************************//* GLOBAL INTERNAL VARIABLE DEFINITIONS *//****************************************/ globle unsigned long EphemeralItemCount = 0; globle unsigned long EphemeralItemSize = 0; globle unsigned long CurrentEphemeralCountMax = MAX_EPHEMERAL_COUNT; globle unsigned long CurrentEphemeralSizeMax = MAX_EPHEMERAL_SIZE; #if ANSI_COMPILER VOID (*YieldTimeFunction)(void) = NULL;#else VOID (*YieldTimeFunction)() = NULL;#endif/*************************************************************//* PeriodicCleanup: Returns garbage created during execution *//* that has not been returned to the memory pool yet. The *//* cleanup is normally deferred so that an executing rule *//* can still access these data structures. Always calls a *//* series of functions that should be called periodically. *//* Usually used by interfaces to update displays. *//*************************************************************/globle VOID PeriodicCleanup(cleanupAllDepths,useHeuristics) BOOLEAN cleanupAllDepths; BOOLEAN useHeuristics; { int oldDepth = -1; struct cleanupFunction *cleanupPtr,*periodPtr; static int lastEvaluationDepth = -1; /*=============================================*/ /* Call functions for handling periodic tasks. */ /*=============================================*/ for (periodPtr = ListOfPeriodicFunctions; periodPtr != NULL; periodPtr = periodPtr->next) { (*periodPtr->ip)(); } /*===================================================*/ /* If the last level we performed cleanup was deeper */ /* than the current level, reset the values used by */ /* the heuristics to determine if garbage collection */ /* should be performed. If the heuristic values had */ /* to be incremented because there was no garbage */ /* that could be cleaned up, we don't want to keep */ /* those same high values permanently so we reset */ /* them when we go back to a lower evaluation depth. */ /*===================================================*/ if (lastEvaluationDepth > CurrentEvaluationDepth) { lastEvaluationDepth = CurrentEvaluationDepth; CurrentEphemeralCountMax = MAX_EPHEMERAL_COUNT; CurrentEphemeralSizeMax = MAX_EPHEMERAL_SIZE; } /*======================================================*/ /* If we're using heuristics to determine if garbage */ /* collection to occur, then check to see if enough */ /* garbage has been created to make cleanup worthwhile. */ /*======================================================*/ if (useHeuristics && (EphemeralItemCount < CurrentEphemeralCountMax) && (EphemeralItemSize < CurrentEphemeralSizeMax)) { return; } /*==========================================================*/ /* If cleanup is being performed at all depths, rather than */ /* just the current evaluation depth, then temporarily set */ /* the evaluation depth to a level that will force cleanup */ /* at all depths. */ /*==========================================================*/ if (cleanupAllDepths) { oldDepth = CurrentEvaluationDepth; CurrentEvaluationDepth = -1; } /*=============================================*/ /* Free up multifield values no longer in use. */ /*=============================================*/ FlushMultifields(); /*=====================================*/ /* Call the list of cleanup functions. */ /*=====================================*/ for (cleanupPtr = ListOfCleanupFunctions; cleanupPtr != NULL; cleanupPtr = cleanupPtr->next) { (*cleanupPtr->ip)(); } /*================================================*/ /* Free up atomic values that are no longer used. */ /*================================================*/ RemoveEphemeralAtoms(); /*=========================================*/ /* Restore the evaluation depth if cleanup */ /* was performed on all depths. */ /*=========================================*/ if (cleanupAllDepths) CurrentEvaluationDepth = oldDepth; /*============================================================*/ /* If very little memory was freed up, then increment the */ /* values used by the heuristics so that we don't continually */ /* try to free up memory that isn't being released. */ /*============================================================*/ if ((EphemeralItemCount + COUNT_INCREMENT) > CurrentEphemeralCountMax) { CurrentEphemeralCountMax = EphemeralItemCount + COUNT_INCREMENT; } if ((EphemeralItemSize + SIZE_INCREMENT) > CurrentEphemeralSizeMax) { CurrentEphemeralSizeMax = EphemeralItemSize + SIZE_INCREMENT; } /*===============================================================*/ /* Remember the evaluation depth at which garbage collection was */ /* last performed. This information is used for resetting the */ /* ephemeral count and size numbers used by the heuristics. */ /*===============================================================*/ lastEvaluationDepth = CurrentEvaluationDepth; }/***************************************************//* AddCleanupFunction: Adds a function to the list *//* of functions called to perform cleanup such *//* as returning free memory to the memory pool. *//***************************************************/globle BOOLEAN AddCleanupFunction(name,theFunction,priority) char *name; VOID (*theFunction)(VOID_ARG); int priority; { return(AddCPFunction(name,theFunction,priority,&ListOfCleanupFunctions)); }/****************************************************//* AddPeriodicFunction: Adds a function to the list *//* of functions called to handle periodic tasks. *//****************************************************/globle BOOLEAN AddPeriodicFunction(name,theFunction,priority) char *name; VOID (*theFunction)(VOID_ARG); int priority; { return(AddCPFunction(name,theFunction,priority,&ListOfPeriodicFunctions)); }/**********************************//* AddCPFunction: Adds a function *//* to a list of functions. *//**********************************/static BOOLEAN AddCPFunction(name,theFunction,priority,head) char *name; VOID (*theFunction)(VOID_ARG); int priority; struct cleanupFunction **head; { struct cleanupFunction *newPtr, *currentPtr, *lastPtr = NULL; newPtr = get_struct(cleanupFunction); newPtr->name = name; newPtr->ip = theFunction; newPtr->priority = priority; if (*head == NULL) { newPtr->next = NULL; *head = newPtr; return(1); } currentPtr = *head; while ((currentPtr != NULL) ? (priority < currentPtr->priority) : CLIPS_FALSE) { lastPtr = currentPtr; currentPtr = currentPtr->next; } if (lastPtr == NULL) { newPtr->next = *head; *head = newPtr; } else { newPtr->next = currentPtr; lastPtr->next = newPtr; } return(1); }/*******************************************************//* RemoveCleanupFunction: Removes a function from the *//* list of functions called to perform cleanup such *//* as returning free memory to the memory pool. *//*******************************************************/globle BOOLEAN RemoveCleanupFunction(name) char *name; { return(RemoveCPFunction(name,&ListOfCleanupFunctions)); }/********************************************************//* RemovePeriodicFunction: Removes a function from the *//* list of functions called to handle periodic tasks. *//********************************************************/globle BOOLEAN RemovePeriodicFunction(name) char *name; { return(RemoveCPFunction(name,&ListOfPeriodicFunctions)); }/****************************************//* RemoveCPFunction: Removes a function *//* from a list of functions. *//****************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -