標籤:efi 推斷 簡單 ext 3.0.0 style 清除 sim 使用
--------------------------------------------------------------------------------
標題: 固定尺寸記憶體塊的緩衝隊列類及實現原始碼
作者: 葉飛虎
日期: 2014.10.21
--------------------------------------------------------------------------------
在一般的線性操作應用中(如: 接收緩衝區), 可能須要頻繁分配和釋放記憶體塊, 頻繁操
作會給系統帶來非常大開銷, 怎樣降低系統開銷? 通過拉大分配和釋放之間間距來降低操作的
頻度, 從而達到降低系統開銷。
拉大分配和釋放之間間距的方法有非常多, 能夠通過大記憶體塊自己管理, 也能夠通過記憶體
塊緩衝隊列。
本文著重講記憶體塊緩衝隊列, 涉及隊列就會考慮到無鎖進出隊列, 即進隊列和
出隊列在二個線程中能夠同一時候操作。
無鎖隊列的實現方法有非常多, 有數組方式的環形無鎖隊
列, 也有連結方式的無鎖隊列。
數組方式在隊列容量確定時比較適合, 而連結方式更適合於
隊列容量可變情況, 適用性更好。
數組方式無鎖隊列見我的博文 <在一讀一寫限制下,無鎖環形隊列怎樣實現?>
連結方式無鎖隊列見我的博文 <一讀一寫情況下。無鎖隊列怎樣實現?>
本文講的緩衝隊列為連結方式, 連結方式一般通過預分配一個結點作為接力點來實現無
鎖隊列, 長處是實現簡單, 缺點是浪費一個結點的記憶體, 當結點記憶體塊尺寸較大時浪費就大
了。怎樣不浪費一個結點記憶體的連結方式無鎖隊列? 當隊列中僅僅有一個結點時, 本緩衝隊列
中使用了原子鎖進行操作, 這是一種平衡策略, 若讀者有更好方法最好還是告之中的一個下!
固定尺寸記憶體塊的緩衝隊列類(TKYCache)原始碼例如以下:
// =======================================// Unit : 固定尺寸的記憶體塊緩衝// Version: 3.0.0.0 (build 2014.10.21)// Author : Kyee Ye// Email : kyee_ye(at)126.com// Copyright (C) Kyee workroom// =======================================#ifndef _KYCache_H_#define _KYCache_H_#include "KYObject.h"// KYLib 2.0 開始使用 KYLib 命名空間namespace KYLib{// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/* TKYCache - 固定尺寸的記憶體塊緩衝類 */// 注:// 1. 為了多線程存取安全, New 和 Delete 分屬二個線程時能夠同一時候操作而不須要加鎖,// 但多線程 New 時必須用鎖控制, 多線程 Delete 時必須用鎖控制!// 2. 此緩衝類一般應用於線性操作的類中, 以降低頻繁分配和釋放記憶體的緩衝使用.class TKYCache{private: // 記憶體塊的連結 typedef struct { void* Self; // 記憶體塊所屬對象 void* Next; // 下一塊 } TLink, *PLink;public: // 建構函式 // 1. ABlockSize 記憶體塊的固定尺寸, 取值範圍: [0x40..0x40000000] // 2. AMaxCount 記憶體塊緩衝的最大個數 TKYCache(long ABlockSize = 1024, long AMaxCount = 256); virtual ~TKYCache(); // 屬性 long Count() const { return FPushCount - FPopCount; } long MaxCount() const { return FMaxCount; } // default: AMaxCount long BlockSize() const { return FBlockSize; } // default: ABlockSize // 設定記憶體塊緩衝的最大個數 void SetMaxCount(long AMaxCount) { FMaxCount = (AMaxCount >= 0) ? AMaxCount : 0; } // 分配固定尺寸的記憶體塊 void* New() { TLink* pItem = DoNew(); return (pItem != NULL) ? (char*)pItem + sizeof(TLink) : NULL; } // 釋放固定尺寸的記憶體塊 void Delete(void* ABlock) { if (ABlock != NULL) { TLink* pItem = (TLink*)((char*)ABlock - sizeof(TLink)); if (pItem->Self == this) DoDelete(pItem); } }private: // 運行分配/釋放帶連結的記憶體塊 TLink* DoNew(); void DoDelete(TLink* ALink); // 運行清除緩衝隊列 void DoClear(TLink* AHead);private: TLink* FHead; // 緩衝的頭連結 TLink* FTail; // 緩衝的尾連結 long FFlag; // 緩衝隊列標誌 long FMaxCount; // 緩衝最大個數 long FBlockSize; // 記憶體塊的尺寸 Longword FPushCount; // 壓入緩衝計數 Longword FPopCount; // 彈出緩衝計數};}#endif
// =======================================// Unit : 固定尺寸的記憶體塊緩衝// Version: 3.0.0.0 (build 2014.10.21)// Author : Kyee Ye// Email : kyee_ye(at)126.com// Copyright (C) Kyee workroom// =======================================#include <malloc.h>#include "KYCache.h"// KYLib 2.0 開始使用 KYLib 命名空間namespace KYLib{// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/* TKYCache - 固定尺寸的記憶體塊緩衝類 */// ---------------- 建構函式和解構函式 ----------------// 建構函式TKYCache::TKYCache(long ABlockSize, long AMaxCount){ // 初始化 FHead = NULL; FTail = NULL; FFlag = 0; FPushCount = 0; FPopCount = 0; // 設定緩衝最大個數 FMaxCount = (AMaxCount >= 0) ? AMaxCount : 0; // 設定記憶體塊的尺寸 if (ABlockSize <= 0x40) FBlockSize = 0x40; else if (ABlockSize <= 0x40000000) FBlockSize = ABlockSize; else FBlockSize = 0x40000000;}// 解構函式TKYCache::~TKYCache(){ // 運行清除緩衝隊列 if (FPopCount != FPushCount) { FPopCount = FPushCount; DoClear(FHead); }}// ---------------- 私人函數 ----------------// 運行分配帶連結的記憶體塊TKYCache::TLink* TKYCache::DoNew(){ // 初始化 TLink* result = NULL; // 推斷緩衝隊列是否為空白 if (FPopCount == FPushCount) result = (TLink*)malloc(sizeof(TLink) + FBlockSize); else if (FPushCount - FPopCount != 1) { // 取第一項, 而且計數加 1 result = FHead; FHead = (TLink*)result->Next; FPopCount++; } else { // 取第一項 result = FHead; // 推斷是否須要等待, 防止 DoDelete 衝突 if (InterlockedIncrement(&FFlag) == 1) { FPopCount++; if (FPopCount == FPushCount) { FHead = NULL; FTail = NULL; } InterlockedDecrement(&FFlag); } else { FPopCount++; InterlockedDecrement(&FFlag); // 迴圈等待 FPushCount 變化 while (FPopCount == FPushCount) Sleep(1); } // 改動緩衝的頭連結 if (result->Next != NULL) FHead = (TLink*)result->Next; } // 初始化連結項 if (result != NULL) { result->Self = this; result->Next = NULL; } // 返回結果 return result;}// 運行釋放帶連結的記憶體塊void TKYCache::DoDelete(TLink* ALink){ // 推斷是否已滿 if (FPushCount - FPopCount >= (Longword)FMaxCount) free(ALink); else { // 置空 ALink->Next = NULL; // 引用計數加 1, 若不等於 1 則等待 DoNew 變成 1 if (InterlockedIncrement(&FFlag) != 1) while (FFlag != 1) Sleep(0); // 推斷是否為第一項 if (FTail == NULL) { FTail = ALink; FHead = ALink; } else { FTail->Next = ALink; FTail = ALink; } // 計數加 1, 且引用計數減 1(注: 順序不能改, 否則可能會導致DoNew死迴圈) FPushCount++; InterlockedDecrement(&FFlag); }}// 運行清除緩衝隊列void TKYCache::DoClear(TLink* AHead){ // 初始化 void* pCurr; // 迴圈釋放 while (AHead != NULL) { pCurr = AHead; AHead = (TLink*)AHead->Next; // 釋放 free(pCurr); }}}
--------------------------------------------------------------------------------
固定尺寸記憶體塊的緩衝隊列類及C++實現原始碼