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

📄 gcptr.cpp

📁 操作系统中的一个例子
💻 CPP
字号:
/*
 * Copyright (c) 2000-2008
 * Author: Weiming Zhou
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  
 */

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "CapiGlobal.h"
#include "HashTable.h"
#include "MTask.h"
#include "GCPtr.h"

#define     GC_COLLECT_ENUM_COUNT  1024
HASHTABLE   *g_pTable; //哈希表指针
HASHTABLE   *g_pMTable; //多任务哈希表指针
LOCK        g_lock; ////用来保护引用计数读写及哈希表操作的锁
MTASK       *g_pMTask;


INT IntCompare(void *p1, void *p2)
{
    if ( (INT)p1 > (INT)p2 )
    {
        return 1;
    }
    else if ( (INT)p1 < (INT)p2 )
    {
        return -1;
    }
    else
    {
        return 0;
    }
}

/**	垃圾内存收集算法的初始化函数

	@param	INT nBucketCount - 哈希表的桶的数量	
	@return	INT - CAPI_SUCCESS表示成功,CAPI_FAILED表示失败	
*/
INT GC_Init(INT nBucketCount)
{
    g_pTable = HashTable_Create(nBucketCount);
    if ( g_pTable != NULL )
    {
        return CAPI_SUCCESS;
    }
    return CAPI_FAILED;
}

#ifdef _DEBUG

/**	垃圾内存收集算法的内存分配函数

	@param	size - 要分派的内存大小,以字节为单位	
	@return	成功返回分配到的内存地址,失败返回NULL	
*/
#define GC_Malloc(size)\
{\
    void *p;\
    INT  *q;\
    char *psz;\
    \
    p = malloc( size + DOUBLE_INT_LEN + INT_LEN + strlen(__FILE__) + 1);\
    if ( p == NULL )\
{\
    GC_Collect();\
    p = malloc( size + DOUBLE_INT_LEN + INT_LEN + strlen(__FILE__) + 1);\
    if ( p == NULL )\
{\
    return NULL;\
}\
}\
    \
    HashTable_Insert( g_pTable, p, HashInt);\
    \
    *((INT *)p) = 0;\
    *((INT *)p + 1) = size;\
    \
    q = (INT *)((char *p) + size + DOUBLE_INT_LEN);\
    *q = __LINE__;\
    psz = (char *)p + size + DOUBLE_INT_LEN + INT_LEN;\
    strcpy(psz, __FILE__);\
    \
    return (void *)((char *)p + DOUBLE_INT_LEN);\
}

/**	垃圾内存收集算法的内存释放函数

	@param	void *p - 要释放的内存地址	
	@return	void - 无	
*/
void GC_Free(void *p)
{
    void *pFree = (void *)((char *)p - DOUBLE_INT_LEN);
    free(pFree);
}

/**	垃圾内存收集算法的内存泄漏检查函数

	@return	void -无	
*/
void GC_CheckMemoryLeak()
{
    void *p;
    
    HashTable_EnumBegin(g_pTable);
    
    while ( (p = HashTable_EnumNext(g_pTable)) != NULL )
    {
        INT *pRef;  
        INT *pSize;
        INT *pLine;
        char *pszFile;
        
        pRef = (INT *)p;
        pSize = pRef + 1;
        if ( *pRef  != 0 ) //判断引用计数是否为0
        {
            pLine = (INT *)((char *)p + *pSize + DOUBLE_INT_LEN);
            pszFile = (char *)pLine + INT_LEN;
            printf("File: %s, Line: %d have memory leak.\n", pszFile, *pLine);
        }
    }
}

#else

/**	垃圾内存收集算法的内存分配函数

	@param	size - 要分派的内存大小,以字节为单位	
	@return	成功返回分配到的内存地址,失败返回NULL	
*/
void *GC_Malloc(size_t size)
{
    void *p = malloc( size + INT_LEN );
    if ( p == NULL )
    {
        GC_Collect();
        p = malloc( size + INT_LEN );
        if ( p == NULL )
        {
            return NULL;
        }
    }

    HashTable_Insert( g_pTable, p, HashInt);

    *((INT *)p) = 0;

    return (void *)((char *)p+INT_LEN);
}

/**	垃圾内存收集算法的内存释放函数

	@param	void *p - 要释放的内存地址	
	@return	void - 无	
*/
void GC_Free(void *p)
{
    void *pFree = (void *)((char *)p - INT_LEN);
    free(pFree);
}
#endif 

/**	垃圾内存收集算法的手工释放内存函数

	@param	void *p - 要释放的内存地址	
	@return	void - 无	
*/
void GC_ManualFree(void *p)
{
    void *pFree = (void *)((char *)p - INT_LEN);
    
    HashTable_Delete(g_pTable, pFree, HashInt, IntCompare, NULL);

    free(pFree);
}

/**	垃圾收集函数
        遍历哈希表,将所有引用计数为0的内存释放掉

	@return	void -无	
*/
void GC_Collect()
{
    void *p;
    HashTable_EnumBegin(g_pTable);
    while ( (p = HashTable_EnumNext(g_pTable)) != NULL )
    {
        INT *pRef = (INT *)p - 1;
        if ( *pRef == 0 )
        {
            HashTable_Delete(g_pTable, p, HashInt, IntCompare, NULL);
            GC_Free(p);
        }
    }
}



/**	多任务下的垃圾内存收集算法的初始化函数

	@param	INT nBucketCount - 哈希表的桶的数量	
	@return	INT - 成功返回CAPI_SUCCESS,失败返回CAPI_FAILED.	
*/
INT MGC_Init(INT nBucketCount)
{
    g_lock = LockCreate();
    if ( g_lock != NULL )
    {
        g_pMTable = HashTable_Create(nBucketCount);
        if ( g_pMTable != NULL )
        {
            g_pMTask = MTask_Create();
            if ( g_pMTask != NULL )
            {
                return CAPI_SUCCESS;
            }
            else
            {
                HashTable_Destroy(g_pMTable, NULL);
                LockClose(g_lock);
            }
        }
        else
        {
            LockClose(g_lock);
        }
    }

    return CAPI_FAILED;
}

/**	多任务下的垃圾内存收集算法的内存分配函数

	@param	size_t size - 要分配的内存大小,以字节为单位	
	@return	void * - 成功返回分配到的内存地址,失败返回NULL	
*/
void *MGC_Malloc(size_t size)
{
    void *p = malloc( size + INT_LEN );
    if ( p == NULL )
    {
        MGC_Collect();
        p = malloc( size + INT_LEN );
        if ( p == NULL )
        {
            return NULL;
        }
    }
    Lock(g_lock);

    HashTable_Insert( g_pMTable, p, HashInt);
    
    *((INT *)p) = 0;

    Unlock(g_lock);
    
    return (void *)((char *)p + INT_LEN );
}


/**	多任务下的垃圾内存收集算法的内存释放函数

	@param	void *p - 要释放的内存地址	
	@return	void - 无	
*/
void MGC_Free(void *p)
{
    void *pFree = (void *)((char *)p - INT_LEN);
    free(pFree);
}

/**	多任务下的垃圾内存收集算法的手工释放内存函数

	@param	void *p - 要释放的内存地址	
	@return	void - 无	
*/
void MGC_ManualFree(void *p)
{
    void *pFree = (void *)((char *)p - INT_LEN);

    Lock(g_lock);
    HashTable_Delete(g_pMTable, pFree, HashInt, IntCompare, NULL);
    Unlock(g_lock);
    
    free(pFree);
}

/**	支持多任务的垃圾收集函数
        遍历哈希表,将所有引用计数为0的内存释放掉

	@return	void -无	
*/
void MGC_Collect()
{
    void *p;

    Lock(g_lock);
    HashTable_EnumBegin(g_pMTable);
    while ( (p = HashTable_EnumNext(g_pMTable)) != NULL )
    {
        INT *pRef = (INT *)((char *)p - INT_LEN);
        if ( *pRef == 0 )
        {
            HashTable_Delete(g_pMTable, p, HashInt, IntCompare, NULL);
            MGC_Free(p);
        }
    }
    Unlock(g_lock);
}

/**	支持多任务的垃圾收集函数
        遍历哈希表,将所有引用计数为0的内存释放掉

	@return	void -无	
*/
void MGC_CollectTask()
{
    void *p;
    UINT i;

    MTask_EnterTask(g_pMTask);

    Lock(g_lock);
    HashTable_EnumBegin(g_pMTable);
    Unlock(g_lock);

    while (MTask_GetExitFlag(g_pMTask) == MTASK_NO_EXIT) 
    {
        Lock(g_lock);
        
        /* 为提高效率减少解锁次数,每次上锁后循环一定次数 */
        for ( i = 0; i < GC_COLLECT_ENUM_COUNT; i++ )
        {
            p = HashTable_EnumNext(g_pMTable);
            if ( p != NULL )
            {
                INT *pRef = (INT *)((char *)p - INT_LEN);
                if ( *pRef == 0 )
                {
                    HashTable_Delete(g_pMTable, p, HashInt, IntCompare, NULL);
                    MGC_Free(p);
                }
            }
            else
            {
                break;
            }
        }

        Unlock(g_lock);
        Sleep(100);
    }

    MTask_LeaveTask(g_pMTask);
    
    return;
}

/**	垃圾收集的关闭函数,必须在程序运行的最后面执行,建议调用atexit()
        函数来执行这个函数

	@return	void -无	
*/
void MGC_Shutdown()
{

    MTask_Destroy(g_pMTask);

    Lock(g_lock);

    HashTable_Destroy(g_pTable, free);
    HashTable_Destroy(g_pMTable, free);

    LockClose(g_lock);
}

⌨️ 快捷键说明

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