數據結構與算法:多任務下的垃圾收集[3] 數據庫設計
關鍵字:數據庫設計 /** 支持多任務的垃圾收集函數,遍歷哈希表,將所有引用計數為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);
}
注意:上面定義全局哈希表對象時使用了另外一個g_pMTable變量,主要是有別于支持單任務的哈希表對象,便于采取不同的策略進行管理。
3. 使用單獨任務進行垃圾收集
實現多任務支持之后,如何進行垃圾收集呢?可以看出在上面實現的MGC_Collect()函數中,只是簡單地加鎖,然后收集,再解鎖。這樣做的缺點是當分配的內存數量比較多時,需要耗費大量的時間進行收集,并且在收集的過程中其他的內存操作全部都會被掛起,直到收集完成解鎖后,其他的內存操作才能繼續,這就是目前實際應用中使用較多的收集方法。本書前面已經介紹了多任務下如何遍歷的問題,所以這里要利用本書的多任務算法來實現更好的垃圾收集功能,使得在進行垃圾收集時不影響其他的內存操作,使得應用程序繼續運行,讓用戶感覺不到垃圾收集在運行。
要實現收集時不影響內存操作,必須使用支持多任務的哈希表?紤]到程序效率,就不再像多任務鏈表那樣單獨寫一個多任務哈希表模塊,若寫成單獨模塊,多任務哈希表自己得有一個鎖,加上引用計數使用的鎖g_lock總共有兩個鎖,需要進行兩次加鎖解鎖操作。而鎖的操作相對于內存讀寫操作是非常耗費時間的,所以還是讓哈希表共用g_lock鎖變量。另外還得發揮多任務的優勢,特別是在使用多核CPU時,更應該發揮多任務的優勢,尤其需要將垃圾回收放到一個單獨的任務里運行。下面我們就來實現用單獨的垃圾收集任務收集垃圾。
要支持多任務,首先必須定義一個多任務變量如下。
MTASK g_pMTask;
還得在MGC_Init()函數里創建MTASK對象,修改后的編碼如下。
/** 多任務下的垃圾內存收集算法的初始化函數
@param INT nBucketCount——哈希表的bucket的數量
@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;
}
文章來源于領測軟件測試網 http://www.kjueaiud.com/