C、C++實現的一種智慧資料管理架構
之前研究STL相關結構的時候,發現STL系列的map、list、vector等設計有以下缺陷:
1.迭代刪除節點的情況下只可以刪除一個節點(不包括清除所有節點的情況);
2.在多執行緒情況下需要加鎖或臨界區等形式同步物件結構資訊,這種情況屬於當前大部分系統設計的短板;
3.計算機執行記憶體產生碎片(STL系列結構分配一個新節點需要申請一次相應長度的記憶體空間,當清除這個節點時,這塊記憶體有可能過短無法再次被分配使用),
參考圖1,假如STL系列結構釋放當前節點在執行記憶體中的地址為0x0005-0x0007,並且0x0008記憶體地址已經被使用,如果這塊記憶體長度過短不能夠被再次分配使用,即為記憶體碎片。
針對上述這些情況,我做了一些猜想並進行證實,設計如下:
1.使用仿照系統記憶體分配方式構建記憶體池,完全由記憶體池管理所有的描述資訊及記憶體分配;
2.使用紅黑樹平衡分配的節點,達到記憶體順序分配(遍歷)、隨機分配(遍歷)的高效率;
3.建立管理層維護資料節點的申請、刪除等工作;
4.使用者層可以儲存任意結構資料,可以使用迭代順序訪問儲存的資料,或隨機訪問儲存的結構;
根據上面的設計思路,資料管理架構設計了四層:
1.最底層(第一層)是記憶體管理層,記憶體池的實現;
2.偏中層(第二層)是結構管理層,紅黑樹結構的上下互動實現;
3.中層(第三層)是資料管理層,提供記憶體分配的結構,以及記憶體等待區域與記憶體回收區域的實現;
4.上層(第四層)是使用者介面層,提供使用者使用結構,其中包括從記憶體池中分配記憶體空間、迭代器查詢及刪除、新增節點,儲存任意格式的資料。
2.結構管理層(紅黑樹結構):
https://blog.csdn.net/a29562268/article/details/80809344,
在這篇文章的基礎上紅黑樹做了一下變動:
2.1.紅黑樹可以通過分配新的資料存入結構或者通過記憶體地址(使用記憶體地址作為紅黑樹的遍歷Key)存入結構;
2.2.黑紅樹的維護節點也是由記憶體池分配;
2.3.紅黑樹提供除錯引數,用來檢視當前的樹結構;
紅黑樹在本架構裡起上下文的作用,維護了記憶體池分配管理和節點的遍歷操作管理;
3.資料管理層:
維護記憶體等待區域與記憶體回收區域:
3.1.通過紅黑樹(上下文作用)進行記憶體分配供使用者層使用;
3.2.當用戶刪除節點時,首先把節點放入記憶體等待區域(這麼做的初衷是達到資料同步效果,經測試windows和linux系統必須同步化資料才能達到不越界訪問);
3.3.當等待區域內有節點超時後,放入記憶體回收區域,由紅黑樹(上下文作用)進行節點回收和紅黑樹的維護節點回收;
3.4.記憶體等待區域與記憶體回收區域採用執行緒的方式啟動執行,如果當前區域內(記憶體等待區域或記憶體回收區域)沒有節點,將掛起執行緒,等到區域內有新節點時再次啟動執行;
4.使用者介面層:
任何型別資料的儲存(可以是自定義類),仿照STL迭代器形式的資料節點遍歷操作:
4.1.採用連結串列形式管理當前所有分配的節點以及申請的記憶體空間(可以呼叫申請記憶體函式,申請一塊連續的記憶體使用);
4.2.定義過載函式,可以多種形式進行儲存節點(直接使用=賦值,或者List形式賦值,呼叫巨集自定義結構賦值);
4.3.編寫迭代器,擁有遍歷插入、刪除等功能;
下面貼上相關程式碼:
1.記憶體管理層(記憶體池):
/**
*李坤昱
*QQ:[email protected]
*/
#include "stdafx.h"
#include "LMemoryPool.h"
Lm_MemoryPool::Lm_MemoryPool(unsigned long AllocSize):m_Memory(0),m_MemoryEnd(0),
m_nInitPoolSize(AllocSize),m_nCompareMini(1),m_nCount(0),
m_nPoolSize(MEMPOOLSIZE),m_bRun(true)
{
memset(m_LastError,0,sizeof(m_LastError));
}
Lm_MemoryPool::~Lm_MemoryPool()
{
m_bRun = false;
Sleep(200);
Lm_MemPoolFree();
}
bool Lm_MemoryPool::Lm_SetComPareMemMini(int nMini)
{
if (1 >= nMini)
{
return false;
}
m_nCompareMini = nMini;
return true;
}
//設定單個記憶體池大小
bool Lm_MemoryPool::Lm_SetPoolSize(unsigned long nSize)
{
if (nSize < MEMPOOLMINI)
return false;
m_nPoolSize = nSize;
return true;
}
char *Lm_MemoryPool::Lm_GetLastError()
{
return m_LastError;
}
bool Lm_MemoryPool::WriteLastError(const char *data)
{
if (0 == data)
return false;
memset(m_LastError,0,sizeof(m_LastError));
memcpy(m_LastError,data,sizeof(data));
return true;
}
//初始化記憶體池
/*首先建立記憶體池,記憶體池起始地址為記憶體池管理錶鏈表節點的地址加1個位元組(比如第一個記憶體池的起始地址加1個位元組為10位元組,
前10位元組為第一記憶體池的連結串列資訊,從10位元組開始一直到記憶體池末尾地址為資料空間地址,所有記憶體池都將以這種形式儲存)*/
/*這種儲存方式有以下優點:1.只需要管理記憶體池就可以保證資料的完整與安全;2.不需要關心連結串列節點的分配與釋放;
3.避免連結節點釋放造成的記憶體碎片*/
bool Lm_MemoryPool::InitMemPool(unsigned long AllocSize)
{
//構建池子
if (0 < AllocSize)
{
//多分配出記憶體池結構描述表記憶體和1個數據連結串列節點,這樣可以保證一次分配出超出記憶體池大小的記憶體
char *Mem = (char *)malloc(AllocSize + sizeof(MemoryStore) + 1 + sizeof(MemList) + 1);
if (0 == Mem)
return false;
if (0 == m_Memory)
{
m_Memory = (PMemoryStore)Mem;
m_Memory->Init();
}
m_Memory->StartAddress = (unsigned long)Mem;
m_Memory->EndAddress = (m_Memory->StartAddress + AllocSize + m_Memory->MemoryStoreSize + sizeof(MemList) + 1);
m_Memory->MemVolumeDose = (AllocSize + m_Memory->MemoryStoreSize + sizeof(MemList) + 1);
}
else
{
char *Mem = (char *)malloc(m_nPoolSize + sizeof(MemoryStore) + 1 + sizeof(MemList) + 1);
if (0 == Mem)
return false;
if (0 == m_Memory)
{
m_Memory = (PMemoryStore)Mem;
m_Memory->Init();
}
m_Memory->StartAddress = (unsigned long)Mem;
m_Memory->EndAddress = (m_Memory->StartAddress + m_nPoolSize + m_Memory->MemoryStoreSize + sizeof(MemList) + 1);
m_Memory->MemVolumeDose = (m_nPoolSize + m_Memory->MemoryStoreSize + sizeof(MemList) + 1);
}
if (0 == m_Memory)
return false;
m_Memory->Count = 1;
m_Memory->CurrentUsageAmount = m_Memory->MemoryStoreSize;
//資料儲存起始地址
m_Memory->StartDataAddress = (m_Memory->StartAddress + m_Memory->MemoryStoreSize);
//記憶體池剩餘容量
m_Memory->SurplusVolumeDose = (m_Memory->MemVolumeDose - m_Memory->MemoryStoreSize);
//分配記憶體失敗
if (0 == m_Memory->StartAddress)
{
WriteLastError("this MemoryAlloc is Not Valid");
return false;
}
m_MemoryEnd = m_Memory;
//記錄當前記憶體池資訊
m_PoolCal.PoolTotal += m_Memory->MemVolumeDose;
++m_PoolCal.PoolAmount;
m_PoolCal.PoolUsage += m_Memory->CurrentUsageAmount;
return true;
}
//建立下一個記憶體池
bool Lm_MemoryPool::CreateNextMemPool(unsigned long AllocSize)
{
PMemoryStore memoryPool = GetPoolHead();
if (m_bRun && 0 == memoryPool)
{
InitMemPool(((AllocSize + m_nCompareMini >= m_nPoolSize) ? (AllocSize + m_nCompareMini) : m_nPoolSize));
return true;
}
while (m_bRun && memoryPool && 0 != memoryPool->Next)
memoryPool = memoryPool->Next;
//構建池子
if (0 < AllocSize)
{
//多分配出記憶體池結構描述表記憶體和1個數據連結串列節點,這樣可以保證一次分配出超出記憶體池大小的記憶體
char *Mem = (char *)malloc(AllocSize + sizeof(MemoryStore) + 1 + sizeof(MemList) + 1);
if (0 == Mem)
return false;
if (!m_bRun)
{
delete Mem;
return false;
}
memoryPool->Next = (PMemoryStore)Mem;
memoryPool->Next->Init();
memoryPool->Next->MemVolumeDose = (AllocSize + memoryPool->Next->MemoryStoreSize + sizeof(MemList) + 1);
memoryPool->Next->StartAddress = (unsigned long)Mem;
memoryPool->Next->EndAddress = (memoryPool->Next->StartAddress + AllocSize + memoryPool->Next->MemoryStoreSize + sizeof(MemList) + 1);
}
else
{
char *Mem = (char *)malloc(m_nPoolSize + sizeof(MemoryStore) + 1 + sizeof(MemList) + 1);
if (0 == Mem)
return false;
memoryPool->Next = (PMemoryStore)Mem;
memoryPool->Next->Init();
memoryPool->Next->MemVolumeDose = (m_nPoolSize + memoryPool->Next->MemoryStoreSize + sizeof(MemList) + 1);
memoryPool->Next->StartAddress = (unsigned long)Mem;
memoryPool->Next->EndAddress = (memoryPool->Next->StartAddress + m_nPoolSize + memoryPool->Next->MemoryStoreSize + sizeof(MemList) + 1);
}
if (0 == memoryPool->Next)
return false;
memoryPool->Next->Count = (memoryPool->Count + 1);
memoryPool->Next->CurrentUsageAmount = memoryPool->Next->MemoryStoreSize;
//資料儲存起始地址
memoryPool->Next->StartDataAddress = (memoryPool->Next->StartAddress + memoryPool->Next->MemoryStoreSize);
//記憶體池剩餘容量
memoryPool->Next->SurplusVolumeDose = (memoryPool->Next->MemVolumeDose - memoryPool->Next->MemoryStoreSize);
//分配記憶體失敗
if (0 == memoryPool->Next->StartAddress)
{
WriteLastError("this MemoryAlloc is Not Valid");
return false;
}
m_MemoryEnd = memoryPool->Next;
m_MemoryEnd->Prev = memoryPool;
//記錄當前記憶體池資訊
m_PoolCal.PoolTotal += m_MemoryEnd->MemVolumeDose;
++m_PoolCal.PoolAmount;
m_PoolCal.PoolUsage += m_MemoryEnd->CurrentUsageAmount;
return true;
}
void *Lm_MemoryPool::Lm_MemAlloc(unsigned long nSize)
{
return GetPoolMem(nSize);
}
//獲取首個記憶體池資訊
PMemoryStore Lm_MemoryPool::GetPoolHead()
{
return m_Memory;
}
//獲取最後一個記憶體池資訊
PMemoryStore Lm_MemoryPool::GetPoolEnd()
{
return m_MemoryEnd;
}
//從所有記憶體池中取出未使用的記憶體地址
void *Lm_MemoryPool::GetPoolMem(unsigned long nSize)
{
PMemoryStore pool = GetPoolHead();
while (m_bRun && pool)
{
char *pData = (char *)GetAPoolofMem(pool,nSize);
if (0 != pData)
return (void *)pData;
pool = pool->Next;
}
//如果沒有建立記憶體池或者所有的池子都遍歷了還是沒有合適記憶體,那麼建立一個新的池子
if ((nSize + m_nCompareMini) > m_nPoolSize)
CreateNextMemPool(nSize + m_nCompareMini);
else
CreateNextMemPool(m_nPoolSize);
char *pData = (char *)GetAPoolofMem(m_MemoryEnd,nSize);
return (void *)pData;
}
//從一塊記憶體池中獲取資料
void *Lm_MemoryPool::GetAPoolofMem(PMemoryStore obj,unsigned long nSize)
{
if (!m_bRun || 0 == obj || 0 >= obj->SurplusVolumeDose || nSize >= obj->SurplusVolumeDose)
{
return 0;
}
//如果達到查詢的條件 開始遍歷對應編號的記憶體池 ,為了最大利用記憶體選擇從頭開始遍歷,如果沒有資料插入到最後
PMemList listData = obj->GetHeadList();
while (m_bRun && listData && (0 != listData->Next))
{
//如果節點中儲存的記憶體使用量大於或等於需要分配的記憶體,那麼使用這塊記憶體
if ((nSize + m_nCompareMini <= listData->CurrentUsgeAmount) && (0 == listData->bValid))
{
PMemList PList = RevampMemUsgeAmount(obj,listData,nSize);
PList->bValid = 1;
return (void *)PList->StartAddress;
}
listData = listData->Next;
}
//建立新的節點儲存分配記憶體
return CreateNextMem(obj,nSize,1);
}
//修改指定記憶體塊當前使用量
PMemList Lm_MemoryPool::RevampMemUsgeAmount(PMemoryStore pool,PMemList list,unsigned long nSize)
{
PMemList pList = list;
if (0 != pool)
{
unsigned long nLen = 0;
pList = MemAllocOfList(list,nSize,nLen);
pool->CurrentUsageAmount += nLen;
pool->SurplusVolumeDose = (pool->MemVolumeDose - pool->CurrentUsageAmount);
m_PoolCal.PoolUsage += nLen;
}
return pList;
}
//回收廢棄的記憶體
void Lm_MemoryPool::recycleMemUsgeAmount(PMemoryStore pool,unsigned long nSize)
{
if (0 != pool)
{
pool->CurrentUsageAmount -= nSize;
pool->SurplusVolumeDose = (pool->MemVolumeDose - pool->CurrentUsageAmount);
m_PoolCal.PoolUsage -= nSize;
}
}
//資料鏈表分配記憶體,如果當前資料鏈表節點記憶體多出需要分配的一部分,那麼記憶體分配後,再建立一個新的節點管理多餘的當前節點記憶體
PMemList Lm_MemoryPool::MemAllocOfList(PMemList list,unsigned long nSize,unsigned long & nLen)
{
//如果當前節點的記憶體空間大於需要分配記憶體加上節點描述記憶體加5個位元組,那麼建立一個新的節點
if (m_bRun && list->CurrentUsgeAmount >= (nSize + sizeof(MemList) + 5))
{
PMemList Nextlist = list->Next;
list->Next = (PMemList)(list->StartAddress + nSize + 2);
list->Next->nodeInfo.StartAddress = (list->StartAddress + nSize + 2);
list->Next->nodeInfo.CurrentUsgeAmount = (sizeof(MemList) + 1);
list->Next->StartAddress = (list->Next->nodeInfo.StartAddress + list->Next->nodeInfo.CurrentUsgeAmount);
list->Next->EndAddress = list->EndAddress;
list->Next->CurrentUsgeAmount = (list->CurrentUsgeAmount - list->Next->nodeInfo.CurrentUsgeAmount - nSize - 2);
list->Next->Next = Nextlist;
list->Next->Next->Prev = list->Next;
list->Next->Prev = list;
list->CurrentUsgeAmount = (nSize + 1);
list->EndAddress = (list->StartAddress + nSize + 1);
nLen = (list->CurrentUsgeAmount + sizeof(MemList) + 2);
}
else
nLen = list->CurrentUsgeAmount;
//分配乾淨的記憶體
memset((void *)list->StartAddress,0,list->CurrentUsgeAmount);
return list;
}
//建立新的節點以及分配記憶體
void *Lm_MemoryPool::CreateNextMem(PMemoryStore obj,unsigned long nSize,bool bValid)
{
PMemList list = obj->GetEndList();
list = CreateMemList(obj,list,nSize);
if (0 == list)
return 0;
list->StartAddress = (obj->StartDataAddress + obj->StartDataOffsetAddress);
//多分配一個位元組用來防止記憶體越界
list->EndAddress = (list->StartAddress + nSize + 1);
list->CurrentUsgeAmount = (nSize + 1);
list->bValid = bValid;
obj->CurrentUsageAmount += list->CurrentUsgeAmount;
obj->SurplusVolumeDose -= list->CurrentUsgeAmount;
obj->StartDataOffsetAddress += list->CurrentUsgeAmount;
obj->pMemEnd = list;
obj->pMemEnd->Next = 0;
m_PoolCal.PoolUsage += list->CurrentUsgeAmount;
//分配出一段乾淨的記憶體 上層方便使用
memset((void *)list->StartAddress,0,list->CurrentUsgeAmount);
return (void *)list->StartAddress;
}
PMemList Lm_MemoryPool::CreateMemList(PMemoryStore pool,PMemList list,int nSize)
{
if (!m_bRun)
return 0;
if (0 == list)
{
list = (PMemList)(pool->StartDataAddress + pool->StartDataOffsetAddress);
if (0 == list)
return 0;
list->Init();
if (0 == list)
return 0;
list->nodeInfo.StartAddress = (pool->StartDataAddress + pool->StartDataOffsetAddress);
list->nodeInfo.CurrentUsgeAmount = (sizeof(MemList) + 1);
pool->pMemHead = list;
pool->CurrentUsageAmount += list->nodeInfo.CurrentUsgeAmount;
pool->SurplusVolumeDose -= list->nodeInfo.CurrentUsgeAmount;
//當前資料偏移地址
pool->StartDataOffsetAddress += list->nodeInfo.CurrentUsgeAmount;
m_PoolCal.PoolUsage += list->nodeInfo.CurrentUsgeAmount;
return list;
}
list->Next = (PMemList)(pool->StartDataAddress + pool->StartDataOffsetAddress);
if (0 == list)
return 0;
list->Next->Init();
if (0 == list->Next)
return 0;
list->Next->nodeInfo.StartAddress = (pool->StartDataAddress + pool->StartDataOffsetAddress);
list->Next->nodeInfo.CurrentUsgeAmount = (sizeof(MemList) + 1);
list->Next->Prev = list;
pool->CurrentUsageAmount += list->Next->nodeInfo.CurrentUsgeAmount;
pool->SurplusVolumeDose -= list->Next->nodeInfo.CurrentUsgeAmount;
//當前資料偏移地址
pool->StartDataOffsetAddress += list->Next->nodeInfo.CurrentUsgeAmount;
m_PoolCal.PoolUsage += list->Next->nodeInfo.CurrentUsgeAmount;
return list->Next;
}
//記憶體釋放
bool Lm_MemoryPool::Lm_MemFree(void * ptr)
{
//根據分配的地址在記憶體池中匹配,匹配到後 修改結構資料後,等待再次使用
PMemoryStore pool = GetPoolHead();
while (m_bRun && pool)
{
PMemList list = pool->GetHeadList();
while (m_bRun && list)
{
//如果連結串列中其中一節資料與需要釋放的地址相同 ,而且這段資料屬於使用中,屬於這塊記憶體
if ((list->StartAddress == (unsigned long)ptr) && (1 == list->bValid))
{
recycleMemUsgeAmount(pool,list->CurrentUsgeAmount);
//回收的時候不需要初始化記憶體,因為再次使用的時候會進行初始化
list->bValid = 0;
ptr = 0;
//判斷連結串列中上一個節點與下一個節點是否為未使用的記憶體(把連續未使用的記憶體放在一起)
if (pool)
ContinuousMemory(list,pool);
return true;
}
list = list->Next;
}
pool = pool->Next;
}
return false;
}
//判斷連結串列中上一個節點與下一個節點是否為未使用的記憶體(把連續未使用的記憶體放在一起)
void Lm_MemoryPool::ContinuousMemory(PMemList list,PMemoryStore pool)
{
PMemList pList = mergePrivMemory(list,pool);
pList = mergeNextMemory(pList,pool);
GiveBackMemory(pList,pool);
//記憶體池使用率低於百分之四十的情況下釋放未使用的記憶體池
FreeNeedlessPool();
}
//合併當前連結串列中與上一個連結串列中未使用的記憶體
PMemList Lm_MemoryPool::mergePrivMemory(PMemList list,PMemoryStore pool)
{
int nNum = 0;
while (m_bRun && list->Prev && !list->Prev->bValid)
{
list->Prev->CurrentUsgeAmount += (list->nodeInfo.CurrentUsgeAmount + list->CurrentUsgeAmount);
list->Prev->EndAddress = list->EndAddress;
//如果是第一次合併記憶體,只需要減去連結串列描述結構大小即可
if (0 == nNum)
{
pool->CurrentUsageAmount -= list->nodeInfo.CurrentUsgeAmount;
pool->SurplusVolumeDose += list->nodeInfo.CurrentUsgeAmount;
m_PoolCal.PoolUsage -= list->nodeInfo.CurrentUsgeAmount;
}
else
{
pool->CurrentUsageAmount -= (list->nodeInfo.CurrentUsgeAmount + list->CurrentUsgeAmount);
pool->SurplusVolumeDose += (list->nodeInfo.CurrentUsgeAmount + list->CurrentUsgeAmount);
m_PoolCal.PoolUsage -= (list->nodeInfo.CurrentUsgeAmount + list->CurrentUsgeAmount);
}
++nNum;
if (list->Next)
{
list->Prev->Next = list->Next;
list->Next->Prev = list->Prev;
}
else
{
list->Prev->Next = 0;
}
list = list->Prev;
//如果上一個節點存在 而且是有效節點 或者 上一個節點不存在,直接返回本次執行結果
if ((list->Prev && list->Prev->bValid) || !list->Prev)
return list;
}
return list;
}
//合併當前連結串列中與下一個連結串列中未使用的記憶體
PMemList Lm_MemoryPool::mergeNextMemory(PMemList list,PMemoryStore pool)
{
while (m_bRun && list->Next && !list->Next->bValid)
{
//兩塊連續未使用的記憶體合併,並且去掉後面未使用記憶體的連結串列節點(一起放入合併的記憶體中)
list->CurrentUsgeAmount += (list->Next->nodeInfo.CurrentUsgeAmount + list->Next->CurrentUsgeAmount);
list->EndAddress = list->Next->EndAddress;
//計算記憶體池當前使用量和可用量
pool->CurrentUsageAmount -= (list->Next->nodeInfo.CurrentUsgeAmount + list->Next->CurrentUsgeAmount);
pool->SurplusVolumeDose += (list->Next->nodeInfo.CurrentUsgeAmount + list->Next->CurrentUsgeAmount);
m_PoolCal.PoolUsage -= (list->Next->nodeInfo.CurrentUsgeAmount + list->Next->CurrentUsgeAmount);
if (list->Next->Next)
{
list->Next->Next->Prev = list;
list->Next = list->Next->Next;
}
else
list->Next = 0;
//如果下一個節點存在 而且是有效節點 或者 下一個節點不存在,直接返回本次執行結果
if ((list->Next && list->Next->bValid) || !list->Next)
return list;
}
return list;
}
//如果當前資料鏈表節點後面沒有分配的節點,那麼把這部分記憶體資訊描述擦除,由記憶體池分配使用
void Lm_MemoryPool::GiveBackMemory(PMemList list,PMemoryStore pool)
{
if (m_bRun && list && !list->Next)
{
pool->CurrentUsageAmount -= list->nodeInfo.CurrentUsgeAmount;
pool->SurplusVolumeDose += list->nodeInfo.CurrentUsgeAmount;
pool->StartDataOffsetAddress = (list->nodeInfo.StartAddress - pool->StartDataAddress);
m_PoolCal.PoolUsage -= list->nodeInfo.CurrentUsgeAmount;
if (list->Prev)
list->Prev->Next = 0;
else //資料鏈表已經沒有節點了,完全由記憶體池分配使用
pool->pMemHead = pool->pMemEnd = 0;
}
}
//釋放記憶體池 ,這個不需要手動釋放 ,類物件銷燬前會進行釋放
bool Lm_MemoryPool::Lm_MemPoolFree()
{
PMemoryStore memPool = GetPoolHead();
while (0 != memPool)
{
PMemoryStore next = memPool->Next;
MemPoolFree_(memPool->Count);
memPool = next;
}
return true;
}
//釋放指定編號記憶體池
bool Lm_MemoryPool::MemPoolFree_(int nCount)
{
PMemoryStore memPool = GetPoolHead();
while (memPool->Count != nCount)
memPool = memPool->Next;
if (0 == memPool)
return false;
PMemoryStore Prev = 0,next = 0;
if (0 != memPool->Prev)
Prev = memPool->Prev;
if (0 != memPool->Next)
next = memPool->Next;
//修改記憶體池使用率資訊
m_PoolCal.PoolTotal -= memPool->MemVolumeDose;
m_PoolCal.PoolUsage -= memPool->CurrentUsageAmount;
--m_PoolCal.PoolAmount;
delete memPool;
memPool = 0;
if (0 != Prev)
Prev->Next = next;
else
m_Memory = next;
if (0 != next)
next->Prev = Prev;
else
m_MemoryEnd = m_Memory;
return true;
}
//記憶體池使用率低於百分之四十的情況下釋放未使用的記憶體池
void Lm_MemoryPool::FreeNeedlessPool()
{
ReRun:
if (40 >= ((double)m_PoolCal.PoolUsage / (double)m_PoolCal.PoolTotal * 100) && 2 <= m_PoolCal.PoolAmount)
{
//找到未使用的記憶體池進行釋放
PMemoryStore memPool = GetPoolHead();
while (0 != memPool)
{
if (0 == memPool->StartDataOffsetAddress)
{
MemPoolFree_(memPool->Count);
//釋放記憶體池後,繼續檢查記憶體使用率是否大於百分之四十
goto ReRun;
}
else
memPool = memPool->Next;
}
}
}
2.結構管理層(紅黑樹結構):
#include "stdafx.h"
#include "LRb_tree.h"
Lr_Rb_tree::Lr_Rb_tree():m_NodeInfo(0)
{
#ifdef DEBUG
m_bLr = true;
#endif
}
Lr_Rb_tree::~Lr_Rb_tree()
{
if (m_NodeInfo)
delete m_NodeInfo;
//All_Delete_Rb_tree_node();
}
bool Lr_Rb_tree::CreateHead(unsigned long nCount)
{
return Init_node(nCount);
}
//初始化
bool Lr_Rb_tree::Init_node(unsigned long nCount)
{
if (_S_red != m_head._M_color && _S_black != m_head._M_color)
{
m_head._M_left = &m_head;
m_head._M_right = &m_head;
m_head._M_parent = 0;
m_head._M_color = _S_red;
m_head.data.nCount = nCount;
m_head.data.Val = (void*)nCount;
m_node_count = 0;
return true;
}
return false;
}
//建立節點
Lr_Rb_tree_node_base* Lr_Rb_tree::Create_Rb_tree_node(unsigned long val)
{
Lr_Rb_tree_node_base* ptr = (Lr_Rb_tree_node_base*)m_pool.Lm_MemAlloc(sizeof(Lr_Rb_tree_node_base));
if (0 == ptr)
return 0;
memset(ptr,0,sizeof(ptr));
ptr->_M_color = _S_red;
ptr->data.nCount = val;
ptr->data.Val = (void*)val;
#ifdef DEBUG
//測試使用
static unsigned long nCount = 0;
if (m_bLr)
{
nCount = 0;
m_bLr = false;
}
ptr->data.nLrCount = ++nCount;
#endif
return ptr;
}
//新增樹資料
unsigned long Lr_Rb_tree::Lr_insert(void* val)
{
unsigned long pdata = WriteData((char*)val);
//判斷是否有頭節點 如果沒有建立頭節點
if (CreateHead(pdata))
return pdata;
return Lr_P_Insert(pdata);
}
//新增樹節點
unsigned long Lr_Rb_tree::Lr_insert(unsigned long nSize)
{
unsigned long pdata = GetMemory(nSize);
//判斷是否有頭節點 如果沒有建立頭節點
if (CreateHead(pdata))
return pdata;
return Lr_P_Insert(pdata);
}
//新增樹節點以及繫結資料
unsigned long Lr_Rb_tree::Lr_P_Insert(unsigned long nCount)
{
if (0 == nCount)
return 0;
Lr_Rb_tree_Ptr x = Begin();
Lr_Rb_tree_Ptr y = End();
Lr_Rb_tree_Ptr pbound;
//首先檢查val是否與之前插入過的資料有重複
if (0 == (pbound = Lr_M_lower_bound(x,y,nCount)))
{
m_pool.Lm_MemFree((void*)nCount);
return 0;
}
//增加數節點以及插入資料
if (!Lr_M_insert_unique_(pbound,nCount))
{
m_pool.Lm_MemFree((void*)nCount);
return 0;
}
return nCount;
}
//從記憶體池中分配記憶體並使用
unsigned long Lr_Rb_tree::WriteData(char *data)
{
if (0 == data)
return 0;
void* pdata = m_pool.Lm_MemAlloc(strlen(data));
memcpy(pdata,data,strlen(data));
return (unsigned long)pdata;
}
//從記憶體池中獲取指定大小
unsigned long Lr_Rb_tree::GetMemory(unsigned long nSize)
{
if (0 >= nSize)
return 0;
void* pdata = m_pool.Lm_MemAlloc(nSize);
return (unsigned long)pdata;
}
//
bool Lr_Rb_tree::Lr_M_insert_unique_(Lr_Rb_tree_Ptr position, const unsigned long & __v)
{
// end()
if (position == End())
{
if (size() > 0 && 1 == compare_less(Right(), __v))
return Lr_M_insert_(0, Right(), __v);
else
return Lr_M_insert_unique(__v);
}
else if (-1 == compare_less(position, __v))
{
if (position == Left()) // begin()
return Lr_M_insert_(Left(), Left(), __v);
else if (position->_M_parent)
{
if (position->_M_parent->_M_right == 0)
return Lr_M_insert_(0, position->_M_parent, __v);
else
return Lr_M_insert_(position, position, __v);
}
else
return Lr_M_insert_unique(__v);
}
else if (1 == compare_less(position, __v))
{
// ... then try after.
if (position == Right())
return Lr_M_insert_(0, Right(), __v);
else if (1 == compare_less(position->_M_right, __v))
{
if (Right(position->_M_right) == 0)
return Lr_M_insert_(0, position->_M_right, __v);
else
return Lr_M_insert_(position->_M_right, position->_M_right, __v);
}
else
return Lr_M_insert_unique(__v);
}
return false;
}
//
bool Lr_Rb_tree::Lr_M_insert_unique(const unsigned long& __v)
{
Lr_Rb_tree_Ptr __x = Begin();
Lr_Rb_tree_Ptr __y = End();
bool __comp = true;
while (__x != 0)
{
__y = __x;
__comp = compare_less(__x,__v);
__x = __comp ? Left(__x) : Right(__x);
}
Lr_Rb_tree_Ptr __j = __y;
if (__comp)
{
if (__y == Begin())
return Lr_M_insert_(__x, __y, __v);
else
__j = __j->_M_left;
}
//if (1 == compare_less(__j,__v))
return Lr_M_insert_(__x, __y, __v);
//return false;
}
//
long long Lr_Rb_tree::size()
{
return m_node_count;
}
//
bool Lr_Rb_tree::Lr_M_insert_(Lr_Rb_tree_Ptr x,Lr_Rb_tree_Ptr y,unsigned long val)
{
bool __insert_left = (x != 0 || y == End()
|| -1 == compare_less(y,val));
Lr_Rb_tree_Ptr z = Create_Rb_tree_node(val);
if (0 == z)
return z;
Lr_Rb_tree_insert_and_rebalance(__insert_left, z,
y, this->m_head);
++m_node_count;
return true;
}
//返回需要插入節點的位置
Lr_Rb_tree_node_base* Lr_Rb_tree::Lr_M_lower_bound(Lr_Rb_tree_Ptr x,Lr_Rb_tree_Ptr y,unsigned long val)
{
while (x != 0)
{
int nless = compare_less(x, val);
if (-1 == nless)
y = x, x = Left(x);
else if (1 == nless)
x = Right(x);
else//如果相等,這條資料不再插入,直接返回
return 0;
}
return y;
}
//返回查詢到的節點位置,如果沒有返回空
Lr_Rb_tree_node_base* Lr_Rb_tree::Lr_FindNode(unsigned long val)
{
//臨時儲存需要插入的節點位置
Lr_Rb_tree_Ptr x = Begin();
while (x != 0)
{
int nless = compare_less(x, val);
if (-1 == nless)
x = Left(x);
else if (1 == nless)
x = Right(x);
else if (-2 == nless)
return 0;
else//如果相等,返回這條資料
return x;
}
return 0;
}
//
int Lr_Rb_tree::compare_less(Lr_Rb_tree_Ptr x,unsigned long val)
{
if (0 == x)
return -2;
if (x->data.nCount < val)
{
return 1;
}
else if (x->data.nCount > val)
{
return -1;
}
return 0;
}
//
Lr_Rb_tree_node_base* Lr_Rb_tree::Begin()
{
return m_head._M_parent;
}
//
Lr_Rb_tree_node_base* Lr_Rb_tree::End()
{
return &m_head;
}
//
Lr_Rb_tree_node_base* Lr_Rb_tree::Left()
{
return m_head._M_left;
}
//
Lr_Rb_tree_node_base* Lr_Rb_tree::Left(Lr_Rb_tree_Ptr ptr)
{
return ptr->_M_left;
}
//
Lr_Rb_tree_node_base* Lr_Rb_tree::Right()
{
return m_head._M_right;
}
//
Lr_Rb_tree_node_base* Lr_Rb_tree::Right(Lr_Rb_tree_Ptr ptr)
{
return ptr->_M_right;
}
//
Lr_Rb_tree_node_base* Lr_Rb_tree::Minimum(Lr_Rb_tree_Ptr ptr)
{
while (ptr->_M_left != 0) ptr = ptr->_M_left;
return ptr;
}
//
Lr_Rb_tree_node_base* Lr_Rb_tree::Maximum(Lr_Rb_tree_Ptr ptr)
{
while (ptr->_M_right != 0)
ptr = ptr->_M_right;
return ptr;
}
void Lr_Rb_tree::Lr_Rb_tree_insert_and_rebalance(const bool __insert_left,
Lr_Rb_tree_node_base* __x,
Lr_Rb_tree_node_base* __p,
Lr_Rb_tree_node_base& __header)//紅黑樹結構核心實現
{
Lr_Rb_tree_node_base **rootptrptr = &__header._M_parent;
__x->_M_parent = __p;
__x->_M_left = 0;
__x->_M_right = 0;
__x->_M_color = _S_red;
if(__insert_left){
__p->_M_left = __x;
if(__p == &__header){
__header._M_parent = __x;
__header._M_right = __x;
}else if( __p == __header._M_left )
__header._M_left = __x;
}else{
__p->_M_right = __x;
if(__p == __header._M_right)
__header._M_right = __x;
}
while( __x != *rootptrptr && __x->_M_parent->_M_color==_S_red ){
Lr_Rb_tree_node_base* const xpp = __x->_M_parent->_M_parent;
if(__x->_M_parent == xpp->_M_left){
Lr_Rb_tree_node_base* const y = xpp->_M_right;
if(y && y->_M_color == _S_red){
__x->_M_parent->_M_color = _S_black;
y->_M_color = _S_black;
xpp->_M_color = _S_red;
__x = xpp;
}else{
if( __x==__x->_M_parent->_M_right){
__x = __x->_M_parent;
_Rb_tree_rotate_left(__x,*rootptrptr);
}
__x->_M_parent->_M_color = _S_black;
xpp->_M_color = _S_red;
_Rb_tree_rotate_right(xpp,*rootptrptr);
}
}else{
Lr_Rb_tree_node_base* const y = xpp->_M_left;
if(y && y->_M_color == _S_red){
__x->_M_parent->_M_color = _S_black;
y->_M_color = _S_black;
xpp->_M_color = _S_red;
__x = xpp;
}else{
if(__x == __x->_M_parent->_M_left){
__x = __x->_M_parent;
_Rb_tree_rotate_right(__x,*rootptrptr);
}
__x->_M_parent->_M_color = _S_black;
xpp->_M_color = _S_red;
_Rb_tree_rotate_left(xpp,*rootptrptr);
}
}
}
(*rootptrptr)->_M_color = _S_black;
return ;
}
//刪除樹節點
bool Lr_Rb_tree::Lr_earse(unsigned long val)
{
if (0 >= size())
return false;
Lr_Rb_tree_Ptr ptr = Lr_FindNode(val);
if (0 == ptr)
return false;
Lr_Rb_tree_rebalance_for_erase(ptr,*Begin(),End()->_M_left,End()->_M_right);
Delete_Rb_tree_node(ptr);
ptr = 0;
--m_node_count;
return true;
}
//刪除節點
void Lr_Rb_tree::Delete_Rb_tree_node(Lr_Rb_tree_Ptr & ptr)
{
//刪除資料
m_pool.Lm_MemFree(ptr->data.Val);
if (Begin()->data.nCount != ptr->data.nCount)
//刪除描述結構
m_pool.Lm_MemFree(ptr);
else
m_head._M_color = Lr_Rb_tree_color(-1);
}
//刪除所有節點,不平衡樹結構
void Lr_Rb_tree::Lr_M_erase(Lr_Rb_tree_Ptr ptr)
{
while (ptr != 0)
{
Lr_M_erase(Right(ptr));
Lr_Rb_tree_Ptr left = Left(ptr);
Delete_Rb_tree_node(ptr);
ptr = left;
}
}
//刪除所有節點
void Lr_Rb_tree::All_Delete_Rb_tree_node()
{
Lr_M_erase(Begin());
m_node_count = 0;
m_head._M_color = Lr_Rb_tree_color(-1);
m_head._M_parent = 0;
m_head._M_left = &m_head;
m_head._M_right = &m_head;
}
Lr_Rb_tree_node_base* Lr_Rb_tree::Lr_Rb_tree_rebalance_for_erase(Lr_Rb_tree_node_base* __z,
Lr_Rb_tree_node_base& __root,
Lr_Rb_tree_node_base*& __leftmost,
Lr_Rb_tree_node_base*& __rightmost)
{
Lr_Rb_tree_node_base* __y = __z;
Lr_Rb_tree_node_base* __x = 0;
Lr_Rb_tree_node_base* __x_parent = 0;
Lr_Rb_tree_node_base* __root_ = &__root;
if (__y->_M_left == 0) // __z has at most one non-null child. y == z.
__x = __y->_M_right; // __x might be null.
else
if (__y->_M_right == 0) // __z has exactly one non-null child. y == z.
__x = __y->_M_left; // __x is not null.
else { // __z has two non-null children. Set __y to
__y = __y->_M_right; // __z's successor. __x might be null.
while (__y->_M_left != 0)
__y = __y->_M_left;
__x = __y->_M_right;
}
if (__y != __z) { // relink y in place of z. y is z's successor
__z->_M_left->_M_parent = __y;
__y->_M_left = __z->_M_left;
if (__y != __z->_M_right) {
__x_parent = __y->_M_parent;
if (__x) __x->_M_parent = __y->_M_parent;
__y->_M_parent->_M_left = __x; // __y must be a child of _M_left
__y->_M_right = __z->_M_right;
__z->_M_right->_M_parent = __y;
}
else
__x_parent = __y;
if (__root_ == __z)
__root_ = __y;
else if (__z->_M_parent->_M_left == __z)
__z->_M_parent->_M_left = __y;
else
__z->_M_parent->_M_right = __y;
__y->_M_parent = __z->_M_parent;
//swap(__y->_M_color, __z->_M_color);
__y = __z;
// __y now points to node to be actually deleted
}
else { // __y == __z
__x_parent = __y->_M_parent;
if (__x) __x->_M_parent = __y->_M_parent;
if (__root_ == __z)
__root_ = __x;
else
if (__z->_M_parent->_M_left == __z)
__z->_M_parent->_M_left = __x;
else
__z->_M_parent->_M_right = __x;
if (__leftmost == __z)
if (__z->_M_right == 0) // __z->_M_left must be null also
__leftmost = __z->_M_parent;
// makes __leftmost == _M_header if __z == __root
else
__leftmost = Minimum(__x);
if (__rightmost == __z)
if (__z->_M_left == 0) // __z->_M_right must be null also
__rightmost = __z->_M_parent;
// makes __rightmost == _M_header if __z == __root
else // __x == __z->_M_left
__rightmost = Maximum(__x);
}
if (__y->_M_color != _S_red) {
while (__x != __root_ && (__x == 0 || __x->_M_color == _S_black))
if (__x == __x_parent->_M_left) {
Lr_Rb_tree_node_base* __w = __x_parent->_M_right;
if (__w->_M_color == _S_red) {
__w->_M_color = _S_black;
__x_parent->_M_color = _S_red;
_Rb_tree_rotate_left(__x_parent, __root_);
__w = __x_parent->_M_right;
}
if ((__w->_M_left == 0 ||
__w->_M_left->_M_color == _S_black) &&
(__w->_M_right == 0 ||
__w->_M_right->_M_color == _S_black)) {
__w->_M_color = _S_red;
__x = __x_parent;
__x_parent = __x_parent->_M_parent;
} else {
if (__w->_M_right == 0 ||
__w->_M_right->_M_color == _S_black) {
if (__w->_M_left) __w->_M_left->_M_color = _S_black;
__w->_M_color = _S_red;
_Rb_tree_rotate_right(__w, __root_);
__w = __x_parent->_M_right;
}
__w->_M_color = __x_parent->_M_color;
__x_parent->_M_color = _S_black;
if (__w->_M_right) __w->_M_right->_M_color = _S_black;
_Rb_tree_rotate_left(__x_parent, __root_);
break;
}
} else { // same as above, with _M_right <-> _M_left.
Lr_Rb_tree_node_base* __w = __x_parent->_M_left;
if (__w->_M_color == _S_red) {
__w->_M_color = _S_black;
__x_parent->_M_color = _S_red;
_Rb_tree_rotate_right(__x_parent, __root_);
__w = __x_parent->_M_left;
}
if (__w && (__w->_M_right == 0 ||
__w->_M_right->_M_color == _S_black) &&
(__w->_M_left == 0 ||
__w->_M_left->_M_color == _S_black)) {
__w->_M_color = _S_red;
__x = __x_parent;
__x_parent = __x_parent->_M_parent;
} else {
if (__w && (__w->_M_left == 0 ||
__w->_M_left->_M_color == _S_black)) {
if (__w->_M_right) __w->_M_right->_M_color = _S_black;
__w->_M_color = _S_red;
_Rb_tree_rotate_left(__w, __root_);
__w = __x_parent->_M_left;
}
__w->_M_color = __x_parent->_M_color;
__x_parent->_M_color = _S_black;
if (__w->_M_left) __w->_M_left->_M_color = _S_black;
_Rb_tree_rotate_right(__x_parent, __root_);
break;
}
}
if (__x) __x->_M_color = _S_black;
}
return __y;
}
void Lr_Rb_tree::_Rb_tree_rotate_left(Lr_Rb_tree_node_base* __x, Lr_Rb_tree_node_base*& __root)//節點左旋轉
{
Lr_Rb_tree_node_base* __y = __x->_M_right;
__x->_M_right = __y->_M_left;
if (__y->_M_left !=0)
__y->_M_left->_M_parent = __x;
__y->_M_parent = __x->_M_parent;
if (__x == __root)
__root = __y;
else if (__x == __x->_M_parent->_M_left)
__x->_M_parent->_M_left = __y;
else
__x->_M_parent->_M_right = __y;
__y->_M_left = __x;
__x->_M_parent = __y;
}
void Lr_Rb_tree::_Rb_tree_rotate_right(Lr_Rb_tree_node_base* __x, Lr_Rb_tree_node_base*& __root)//節點右旋轉
{
Lr_Rb_tree_node_base* __y = __x->_M_left;
__x->_M_left = __y->_M_right;
if (__y->_M_right != 0)
__y->_M_right->_M_parent = __x;
__y->_M_parent = __x->_M_parent;
if (__x == __root)
__root = __y;
else if (__x == __x->_M_parent->_M_right)
__x->_M_parent->_M_right = __y;
else
__x->_M_parent->_M_left = __y;
__y->_M_right = __x;
__x->_M_parent = __y;
}
//顯示節點資訊
char * Lr_Rb_tree::ShowNodeInfo()
{
if (0 == m_node_count)
return 0;
if (0 != m_NodeInfo)
{
delete m_NodeInfo;
m_NodeInfo = new char[m_node_count * 50];
memset(m_NodeInfo,0,sizeof(m_NodeInfo));
}
else
{
m_NodeInfo = new char[m_node_count * 50];
memset(m_NodeInfo,0,sizeof(m_NodeInfo));
}
int noffset = 0;
unsigned long nVal = 0;
return GetNodeInfo(WriteRootInfo(m_NodeInfo,m_head._M_parent,noffset,nVal),m_head._M_parent,noffset,nVal,-1);
}
//寫入root資訊
char * Lr_Rb_tree::WriteRootInfo(char *nodeInfo,Lr_Rb_tree_node_base * node,int & noffset,unsigned long & nVal)
{
if (0 == nodeInfo)
return 0;
if (node)
{
#ifdef DEBUG
sprintf(nodeInfo,"The root node is %d\r\n",node->data.nLrCount);
#else
sprintf(nodeInfo,"The root node is %d\r\n",node->data.nCount);
#endif
noffset = strlen(nodeInfo);
nVal = node->data.nCount;
*(nodeInfo + nVal) = 0;
}
return nodeInfo;
}
//節點資訊寫入字串
char * Lr_Rb_tree::GetNodeInfo(char *nodeInfo,Lr_Rb_tree_node_base * node,int & noffset,unsigned long nVal,int left)
{
if (0 == nodeInfo)
return 0;
if (node)
{
if (-1 != left)
WriteNodeInfo(nodeInfo,node,noffset,nVal,left);
#ifdef DEBUG
if (node->_M_left)
GetNodeInfo(nodeInfo,node->_M_left,noffset,/*node->_val*/node->data.nLrCount,1);
if (node->_M_right)
GetNodeInfo(nodeInfo,node->_M_right,noffset,node->data.nLrCount,0);
#else
if (node->_M_left)
GetNodeInfo(nodeInfo,node->_M_left,noffset,/*node->_val*/node->data.nCount,1);
if (node->_M_right)
GetNodeInfo(nodeInfo,node->_M_right,noffset,node->data.nCount,0);
#endif
}
return nodeInfo;
}
//寫入節點資料
char * Lr_Rb_tree::WriteNodeInfo(char *nodeInfo,Lr_Rb_tree_node_base * node,int & noffset,unsigned long nVal,bool left)
{
char TempData[100] = {0};
#ifdef DEBUG
if (_S_red == node->_M_color)
sprintf(TempData,"%d is the red %s node of %d\r\n",/*node->_val*/node->data.nLrCount,(left ? "left" : "right"),nVal);
else if (_S_black == node->_M_color)
sprintf(TempData,"%d is the black %s node of %d\r\n",node->data.nLrCount,(left ? "left" : "right"),nVal);
#else
if (_S_red == node->_M_color)
sprintf(TempData,"%d is the red %s node of %d\r\n",/*node->_val*/node->data.nCount,(left ? "left" : "right"),nVal);
else if (_S_black == node->_M_color)
sprintf(TempData,"%d is the black %s node of %d\r\n",node->data.nCount,(left ? "left" : "right"),nVal);
#endif
int nLen = strlen(TempData);
memcpy(nodeInfo + noffset,TempData,nLen);
noffset += nLen;
*(nodeInfo + noffset) = 0;
return nodeInfo;
}
3.資料管理層:
#include "stdafx.h"
#include "Lmangement.h"
Lmangement::Lmangement():m_WaitThread(0),m_RecycleThread(0),m_WaitHead(0),m_WaitEnd(0),m_RecycleHead(0)
,m_RecycleEnd(0)
,m_bRunWaitArea(false)
,m_bRunRecycleArea(false)
{
}
Lmangement::~Lmangement()
{
if (m_WaitThread)
CloseHandle(m_WaitThread),m_WaitThread = 0;
if (m_RecycleThread)
CloseHandle(m_RecycleThread),m_RecycleThread = 0;
}
//放入到等待或刪除區域
bool Lmangement::Lm_WaitArea(PNode node)
{
if (100 > GetTickCount() - node->ntime)
{
WaitAddNode(node);
return Run_WaitArea();
}
return RecycleInValidNode(node);
}
//直接回收不使用的記憶體
bool Lmangement::Lm_Recycle(PNode node)
{
return RecycleInValidNode(node);
}
//執行等待區域
bool Lmangement::Run_WaitArea()
{
if (!GetWaitHandle())
return (m_WaitThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)WaitAreaThread,this,CREATE_SUSPENDED,NULL));
else if (GetWaitHandle() && !IsWaitAreaRun())
{
if (1 <= ResumeThread(GetWaitHandle()))
SetWaitArea(true);
else
return false;
}
return true;
}
//執行回收區域
bool Lmangement::Run_RecycleArea()
{
if (!GetRecycleHandle())
return (m_RecycleThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RecycleAreaThread,this,CREATE_SUSPENDED,NULL));
else if (GetRecycleHandle() && !IsRecycleAreaRun())
{
DWORD nval;
if (1 <= (nval = ResumeThread(GetRecycleHandle())))
SetRecycleArea(true);
else
return false;
}
return true;
}
//等待區域放入節點
void Lmangement::WaitAddNode(PNode node)
{
if (IsWaitArea())
InsertWaitHead(node);
else
InsertWaitEnd(node);
}
//回收區域放入節點
void Lmangement::RecycleNode(PNode node)
{
if (IsRecycleArea())
InsertRecycleHead(node);
else
InsertWaitEnd(node);
//啟動回收執行緒
Run_RecycleArea();
}
//檢查等待區域是否為空
bool Lmangement::IsWaitArea()
{
return (m_WaitHead == 0);
}
//檢查回收區域是否為空
bool Lmangement::IsRecycleArea()
{
return (m_RecycleHead == 0);
}
//等待區域頭位置增加節點
void Lmangement::InsertWaitHead(PNode node)
{
m_WaitHead = m_WaitEnd = node;
m_WaitHead->Prev = 0;
}
//等待區域尾部位置增加節點
void Lmangement::InsertWaitEnd(PNode node)
{
m_WaitEnd = node;
m_WaitEnd->Next = 0;
}
//等待區域頭位置增加節點
void Lmangement::InsertRecycleHead(PNode node)
{
m_RecycleHead = m_RecycleEnd = node;
m_RecycleHead->Prev = 0;
}
//等待區域尾部位置增加節點
void Lmangement::InsertRecycleEnd(PNode node)
{
m_RecycleEnd = node;
m_RecycleEnd->Next = 0;
}
//獲取等待節點,true 頭節點,false end 末尾節點
PNode Lmangement::GetWaitNode(bool bHead)
{
if (bHead)
return m_WaitHead;
else
return m_WaitEnd;
}
//獲取回收節點,true 頭節點,false end 末尾節點
PNode Lmangement::GetRecycleNode(bool bHead)
{
if (bHead)
return m_RecycleHead;
else
return m_RecycleEnd;
}
//獲取當前等待區域狀態是否正在執行
bool Lmangement::IsWaitAreaRun()
{
return m_bRunWaitArea;
}
//獲取當前回收區域狀態是否正在執行
bool Lmangement::IsRecycleAreaRun()
{
return m_bRunRecycleArea;
}
//設定當前等待區域狀態
void Lmangement::SetWaitArea(bool bRun)
{
m_bRunWaitArea = bRun;
}
//設定當前回收區域狀態
void Lmangement::SetRecycleArea(bool bRun)
{
m_bRunRecycleArea = bRun;
}
DWORD CALLBACK Lmangement::WaitAreaThread(void* _this)
{
Lmangement * ment = (Lmangement *)_this;
ReRun:
PNode node = ment->GetWaitNode(true);
while ((node || (node = ment->GetWaitNode(true))) && ment->IsWaitAreaRun() && ment->GetWaitHandle())
{
unsigned long nCurrent = GetTickCount();
PNode nextnode = node->Next;
if (DeleteNodeTime <= nCurrent - node->ntime)
{
ment->RemoveWaitNode(node);
//放入回收區域
ment->RecycleNode(node);
}
node = nextnode;
}
ment->SetWaitArea(false);
ReSuspend:
//如果釋放了控制代碼 直接退出執行緒
if (!ment->GetWaitHandle())
return 0;
//掛起執行緒,有任務時,自動開始執行
if ( -1 == SuspendThread(ment->GetWaitHandle()))
goto ReSuspend;
goto ReRun;
return 0;
}
//回收區域執行緒
DWORD CALLBACK Lmangement::RecycleAreaThread(void* _this)
{
Lmangement * ment = (Lmangement *)_this;
ReRun:
PNode node = ment->GetRecycleNode(true);
while ((node || (node = ment->GetRecycleNode(true))) && ment->IsRecycleAreaRun() && ment->GetRecycleHandle())
{
PNode nextnode = node->Next;
ment->RecycleInValidNode(node);
//節點和資料佔用記憶體放回記憶體池
ment->RemoveRecycleNode(node);
node = nextnode;
}
ment->SetRecycleArea(false);
ReSuspend:
//如果釋放了控制代碼 直接退出執行緒
if (!ment->GetRecycleHandle())
return 0;
//掛起執行緒,有任務時,自動開始執行
DWORD nval;
if (-1 == (nval = SuspendThread(ment->GetRecycleHandle())))
goto ReSuspend;
goto ReRun;
return 0;
}
//回收無效節點函式
bool Lmangement::RecycleInValidNode(PNode node)
{
if (!Lr_earse((unsigned long)node->Data))
return false;
return Lr_earse((unsigned long)node);
}
//從等待區域內去掉當前節點
void Lmangement::RemoveWaitNode(PNode node)
{
if (0 == node)
return;
if (0 == node->Prev && 0 != node->Next)
{
InsertWaitHead(node->Next);
}
else if (0 != node->Prev && 0 != node->Next)
{
MergeNode(node->Prev,node->Next);
}
else if (0 != node->Prev && 0 == node->Next)
{
SetNextNode(node->Prev,0);
InsertWaitEnd(node->Prev);
}
else//最後一種情況只有當前一個節點
{
InitWaitListNode();
}
}
//從回收區域內去掉當前節點
void Lmangement::RemoveRecycleNode(PNode node)
{
if (0 == node)
return;
if (0 == node->Prev && 0 != node->Next)
{
InsertRecycleHead(node->Next);
}
else if (0 != node->Prev && 0 != node->Next)
{
MergeNode(node->Prev,node->Next);
}
else if (0 != node->Prev && 0 == node->Next)
{
SetNextNode(node->Prev,0);
InsertRecycleEnd(node->Prev);
}
else//最後一種情況只有當前一個節點
{
InitRecycleListNode();
}
}
//兩段斷開的連結串列,合併成一條連結串列
bool Lmangement::MergeNode(PNode Prev,PNode next)
{
if (0 == Prev || 0 == next)
return false;
SetNextNode(Prev,next);
SetPrevNode(next,Prev);
return true;
}
//設定上一個節點
void Lmangement::SetPrevNode(PNode DstNode,PNode SrcNode)
{
DstNode->Prev = SrcNode;
}
//設定下一個節點
void Lmangement::SetNextNode(PNode DstNode,PNode SrcNode)
{
DstNode->Next = SrcNode;
}
//初始化等待區域連結串列節點
void Lmangement::InitWaitListNode()
{
m_WaitEnd = m_WaitHead = 0;
}
//初始化等待區域連結串列節點
void Lmangement::InitRecycleListNode()
{
m_RecycleEnd = m_RecycleHead = 0;
}
//獲取等待區域執行緒控制代碼
HANDLE Lmangement::GetWaitHandle()
{
return m_WaitThread;
}
//獲取等待區域執行緒控制代碼
HANDLE Lmangement::GetRecycleHandle()
{
return m_RecycleThread;
}
4.使用者介面層:
#include "stdafx.h"
#include "LData.h"
LData::LData():m_nNodeTotal(0),m_bRun(true)
{
InitListNode();
}
LData::~LData()
{
m_bRun = false;
}
//初始化連結串列節點
bool LData::InitNode()
{
if (0 == m_HeadNode)
{
int nNodeLen = sizeof(Node);
m_HeadNode = (PNode)allocMem(nNodeLen);
if (0 == m_HeadNode)
return false;
m_HeadNode->InitNode();
m_EndNode = m_HeadNode;
//計算當前分配記憶體總量
++m_nNodeTotal;
return true;
}
return false;
}
//獲取頭節點
PNode LData::GetNodeHead()
{
return m_HeadNode;
}
//獲取尾節點
PNode LData::GetNodeEnd()
{
return m_EndNode;
}
//分配新的頭節點
PNode LData::InsertHeadNode(PNode node)
{
m_HeadNode = node;
m_HeadNode->Prev = 0;
return m_HeadNode;
}
//分配新的尾節點
PNode LData::InsertEndNode(PNode node)
{
m_EndNode = node;
m_EndNode->Next = 0;
return m_EndNode;
}
//分配出節點使用
PNode LData::AllocNode(bool bHead)
{
int nLen = sizeof(Node);
PNode node = 0;
if (bHead && 0 != GetNodeHead())
{
node = GetNodeHead();
node->Prev = (PNode)allocMem(nLen);
if (0 == node->Prev)
return 0;
node->Prev->InitNode();
SetNextNode(node->Prev,m_HeadNode);
node = InsertHeadNode(node->Prev);
//計算當前分配記憶體總量
++m_nNodeTotal;
}
else if (!bHead && 0 != GetNodeEnd())
{
node = GetNodeEnd();
node->Next = (PNode)allocMem(nLen);
if (0 == node->Next)
return 0;
node->Next->InitNode();
SetPrevNode(node->Next,m_EndNode);
node = InsertEndNode(node->Next);
//計算當前分配記憶體總量
++m_nNodeTotal;
}
return node;
}
//分配一個單獨的連結串列節點
PNode LData::AllocAloneNode()
{
int nLen = sizeof(Node);
PNode node = (PNode)allocMem(nLen);
if (0 == node)
return 0;
node->InitNode();
return node;
}
//分配出可以使用的節點,用來關聯資料
PNode LData::UsableNode(bool bHead)
{
if (bHead && m_bRun && m_HeadNode && type_error == m_HeadNode->Type)
return m_HeadNode;
else if (!bHead && m_bRun && m_EndNode && type_error == m_EndNode->Type)
return m_EndNode;
return AllocNode(bHead);
}
//從記憶體池中獲取記憶體使用
unsigned long LData::allocMem(unsigned long nSize)
{
return Lr_insert(nSize);
}
//獲取一段連續的記憶體,並且已經記錄在容器結構中
void* LData::Ld_GetMem(unsigned long nSize,bool bHead)
{
if (!m_bRun)
return 0;
unsigned long nCount = allocMem(nSize);
InitNode();
PNode node = UsableNode(bHead);
node->InitNode();
node->Type = type_string;
node->Data = (void*)nCount;
return node->Data;
}
//儲存過載得到的資料
PNode LData::OperList(Data_Type type,int nLen,bool bHead,bool bNew)
{
InitNode();
PNode node = UsableNode(bHead);
if (0 == node)
return 0;
switch (type)
{
case type_int8:
node->Type = type_int8;
break;
case type_uint8:
node->Type = type_uint8;
break;
case type_int16:
node->Type = type_int16;
break;
case type_uint16:
node->Type = type_uint16;
break;
case type_int32:
node->Type = type_int32;
break;
case type_uint32:
node->Type = type_uint32;
break;
case type_int64:
node->Type = type_int64;
break;
case type_uint64:
node->Type = type_uint64;
break;
case type_string:
node->Type = type_string;
break;
case type_obj:
node->Type = type_obj;
break;
default:
node->Type = type_error;
break;
}
if (type_error == node->Type)
return 0;
if (bNew)
{
unsigned long nCount = allocMem(nLen);
node->Data = (void*)nCount;
}
return node;
}
//儲存過載得到的資料資訊
void* LData::OperData(void* data,void* obj,Data_Type type,int nLen)
{
if (0 == nLen)
return 0;
switch (type)
{
case type_int8:
*(char*)data = *(char*)obj;
break;
case type_uint8:
*(unsigned char*)data = *(unsigned char*)obj;
break;
case type_int16:
*(short*)data = *(short*)obj;
break;
case type_uint16:
*(unsigned short*)data = *(unsigned short*)obj;
break;
case type_int32:
*(int*)data = *(int*)obj;
break;
case type_uint32:
*(unsigned int*)data = *(unsigned int*)obj;
break;
case type_int64:
*(long long*)data = *(long long*)obj;
break;
case type_uint64:
*(unsigned long long*)data = *(unsigned long long*)obj;
break;
case type_string:
memcpy(data,obj,nLen);
break;
case type_obj:
memcpy(data,obj,nLen);
break;
}
return data;
}
char LData::operator = (const char & obj)
{
PNode node = OperList(type_int8,sizeof(char));
if (0 == node)
return 0;
return (char)OperData(node->Data,(void*)&obj,type_int8);
}
unsigned char LData::operator = (const unsigned char & obj)
{
PNode node = OperList(type_uint8,sizeof(unsigned char));
if (0 == node)
return 0;
return (unsigned char)OperData(node->Data,(void*)&obj,type_uint8);
}
short LData::operator = (const short & obj)
{
PNode node = OperList(type_int16,sizeof(short));
if (0 == node)
return 0;
return (short)OperData(node->Data,(void*)&obj,type_int16);
}
unsigned short LData::operator = (const unsigned short & obj)
{
PNode node = OperList(type_uint16,sizeof(unsigned short));
if (0 == node)
return 0;
return (unsigned short)OperData(node->Data,(void*)&obj,type_uint16);
}
int LData::operator = (const int & obj)
{
PNode node = OperList(type_int32,sizeof(int));
if (0 == node)
return 0;
return (int)OperData(node->Data,(void*)&obj,type_int32);
}
unsigned int LData::operator = (const unsigned int & obj)
{
PNode node = OperList(type_uint32,sizeof(unsigned int));
if (0 == node)
return 0;
return (unsigned int)OperData(node->Data,(void*)&obj,type_uint32);
}
long long LData::operator = (const long long & obj)
{
PNode node = OperList(type_int64,sizeof(long long));
if (0 == node)
return 0;
return (long long)OperData(node->Data,(void*)&obj,type_int64);
}
unsigned long long LData::operator = (const unsigned long long & obj)
{
PNode node = OperList(type_uint64,sizeof(unsigned long long));
if (0 == node)
return 0;
return (unsigned long long)OperData(node->Data,(void*)&obj,type_uint64);
}
char* LData::operator = (const char* obj)
{
PNode node = OperList(type_string,strlen(obj));
if (0 == node)
return 0;
return (char*)OperData(node->Data,(void*)obj,type_string,strlen(obj));
}
void* LData::InClassObj(const void* obj,int nlen)
{
if (!m_bRun)
return 0;
PNode node = OperList(type_obj,nlen);
if (0 == node)
return 0;
return OperData(node->Data,(void*)obj,type_obj,nlen);
}
//返回頭節點
LData_iterator LData::Begin()
{
iter.iterNode = GetNodeHead();
return iter;
}
//返回末尾節點
LData_iterator LData::End()
{
iter.iterNode = GetNodeEnd();
return iter;
}
//給需要刪除的結構增加刪除時間
void LData::AddNodeTime(PNode node)
{
node->ntime = GetTickCount();
}
//刪除資料 放入到管理層的等待區域,等待後續處理
bool LData::Ld_erase(LData_iterator it)
{
if (!m_bRun || 0 == it.iterNode || type_error == it.iterNode->Type)
return false;
AddNodeTime(it.iterNode);
PNode node = separateNode(it.iterNode);
if (0 == node)
return false;
--m_nNodeTotal;
return Lm_WaitArea(node);
}
//需要刪除的資料與連結串列分離
PNode LData::separateNode(PNode node)
{
if (0 == node)
return 0;
if (0 == node->Prev && 0 != node->Next)
{
InsertHeadNode(node->Next);
return node;
}
else if (0 != node->Prev && 0 != node->Next)
{
MergeNode(node->Prev,node->Next);
return node;
}
else if (0 != node->Prev && 0 == node->Next)
{
SetNextNode(node->Prev,0);
InsertEndNode(node->Prev);
return node;
}
else if (0 == node->Prev && 0 == node->Next)//最後一種情況只有當前一個節點
{
InitListNode();
}
return node;
}
//初始化連結串列節點
void LData::InitListNode()
{
m_EndNode = m_HeadNode = 0;
m_nNodeTotal = 0;
}
//獲取資料型別長度
int LData::GetTypeLen(Data_Type type)
{
int nLen = 0;
switch (type)
{
case type_int8:
nLen = sizeof(char);
break;
case type_uint8:
nLen = sizeof(unsigned char);
break;
case type_int16:
nLen = sizeof(short);
break;
case type_uint16:
nLen = sizeof(unsigned short);
break;
case type_int32:
nLen = sizeof(int);
break;
case type_uint32:
nLen = sizeof(unsigned int);
break;
case type_int64:
nLen = sizeof(long long);
break;
case type_uint64:
nLen = sizeof(unsigned long long);
break;
}
return nLen;
}
//修改節點儲存的資料型別
void LData::ReviseNodeType(PNode node,Data_Type type)
{
node->Type = type;
}
//指定位置增加資料
bool LData::Ld_insert(iterator it,void *data,Data_Type type,unsigned long nLen)
{
if (!m_bRun)
return false;
int nlen = (nLen > 0 ? nLen : GetTypeLen(type));
if (0 >= nlen)
return false;
PNode node = AllocAloneNode();
if (0 == node)
return false;
ReviseNodeType(node,type);
unsigned long nCount = allocMem(nlen);
node->Data = (void*)nCount;
//計算當前分配記憶體總量
++m_nNodeTotal;
if (type_string == type || type_obj == type)
(char*)OperData(node->Data,(void*)data,type,nlen);
else
(char*)OperData(node->Data,(void*)&data,type,nlen);
return InsertNodeToList(node,it.iterNode,true);
}
//一節連結串列節點 嵌入到連結串列指定位置
bool LData::InsertNodeToList(PNode SrcNode,PNode DsrNode,bool prev)
{
if (0 == SrcNode || 0 == DsrNode)
return false;
if (prev)
{
if (DsrNode->Prev)
{
SetPrevNode(SrcNode,DsrNode->Prev);
SetNextNode(SrcNode,DsrNode);
SetNextNode(DsrNode->Prev,SrcNode);
SetPrevNode(DsrNode,SrcNode);
}
else
{
SetNextNode(SrcNode,DsrNode);
SetPrevNode(DsrNode,SrcNode);
InsertHeadNode(SrcNode);
}
}
else
{
if (DsrNode->Next)
{
SetPrevNode(SrcNode,DsrNode);
SetNextNode(SrcNode,DsrNode->Next);
SetPrevNode(DsrNode->Next,SrcNode);
SetNextNode(DsrNode,SrcNode);
}
else
{
SetPrevNode(SrcNode,DsrNode);
SetNextNode(DsrNode,SrcNode);
InsertEndNode(SrcNode);
}
}
return true;
}
//獲取指定位置資料型別
Data_Type LData::Ld_GetDataType(iterator it)
{
if (!m_bRun)
return type_error;
if (0 == it.iterNode)
return type_error;
return it.iterNode->Type;
}
//獲取指定位置資料值
void* LData::Ld_GetData(iterator it)
{
if (!m_bRun)
return 0;
if (0 == it.iterNode)
return 0;
return it.iterNode->Data;
}
//向容器結構中插入資料,主要作用是從記憶體池中分配的記憶體進行儲存
bool LData::Ld_push_back(void *data,Data_Type type,bool bNew,unsigned long nSize)
{
if (!m_bRun)
return false;
int nlen = (nSize > 0 ? nSize : GetTypeLen(type));
if (0 >= nlen)
return false;
PNode node = OperList(type,nlen,false,bNew);
if (0 == node)
return false;
if (!bNew)
node->Data = data;
else
{
if (type_string == type || type_obj == type)
(char*)OperData(node->Data,(void*)data,type,nlen);
else
(char*)OperData(node->Data,(void*)&data,type,nlen);
}
return true;
}
//在第一位向前插入
bool LData::Ld_push_front(void *data,Data_Type type,bool bNew,unsigned long nSize)
{
if (!m_bRun)
return false;
int nlen = (nSize > 0 ? nSize : GetTypeLen(type));
if (0 >= nlen)
return false;
PNode node = OperList(type,nlen,true,bNew);
if (0 == node)
return false;
if (!bNew)
node->Data = data;
else
{
if (type_string == type || type_obj == type)
return (char*)OperData(node->Data,(void*)data,type,nlen);
else
return (char*)OperData(node->Data,(void*)&data,type,nlen);
}
return false;
}
//清除所有節點
void LData::Ld_clear()
{
PNode node = GetNodeHead();
while (m_bRun && node)
{
PNode next = node->Next;
Lm_Recycle(node);
node = next;
}
InitListNode();
}
相關推薦
C、C++實現的一種智慧資料管理架構
之前研究STL相關結構的時候,發現STL系列的map、list、vector等設計有以下缺陷: 1.迭代刪除節點的情況下只可以刪除一個節點(不包括清除所有節點的情況); 2.在多執行緒情況下需要加鎖或臨界區等形式同步物件結構資訊,這種情況屬於當前大部分系統設計的
C語言實現一種建立易管理易維護執行緒的方法
一、什麼是執行緒? 在一個程式中的多個執行路線就叫做執行緒。 就個人理解而言,一個執行緒就是一個程序裡的一個while(1),一般情況下執行緒是不會退出的。 而多執行緒自然就是一個程序裡的多個while(1)了。 《西遊記》中,有一種有趣的設定——“天上
關於C++、C#實現EXCEL資料庫批量匯入資料庫萬行以上資料效率問題
最近開發一個數據展示、處理的一個管理類網站,開始沒有考慮資料量問題,測試才發現,當excel資料匯入資料庫的時候,隨著資料量的增加,越來越慢。慢的難易理解。 通過網上查詢發現事務在資料庫中是一個重要的概念,使用事務可以保證資料的統一和完整性。同時也
人工智慧框架資料集轉換C++實現(一):TFRecord資料集
最近在研究將各種資料集轉換為不同AI框架的自有資料,這些框架包括Caffe,MXNet,Tensorflow等.C++這樣一個通用而又強大的語言,卻讓使用C++的同鞋在AI時代有一個痛點,那就是目前的AI框架基本都是底層用C/C++實現,但提供的介面卻大部分都是python的
Linux雜談: 實現一種簡單實用的執行緒池(C語言)
基本功能 1. 實現一個執行緒的佇列,佇列中的執行緒啟動後不再釋放; 2. 沒有任務執行時,執行緒處於pending狀態,等待喚醒,不佔cpu; 3. 當有任務需要執行時,從執行緒佇列中取出一個執行緒執行任務; 4. 任務執行完成後執行緒再次進入pending狀態,等待喚醒; 擴充套件功能 1.
用C++、Qt實現的小遊戲2048
圖片 explicit AC 向上 類的構造函數 += cli 而後 遊戲 窗口布局與遊戲截圖: 實現思路: 1.使用二維數組模擬整個遊戲網格,並將二維數組中每個數的大小用作遊戲中每個網格中的數據。 2.將對遊戲的數據及數據的操作(即玩家的操
C語言數組一種巧妙的使用方式
數組 raw n) 計算 blob 今天 href alloc arr 作為計算機一種比較古老的語言,它並沒有隨著歲月老去,而是仍舊在整個領域發揮出耀眼的光芒,就像寫作,有很多光芒萬丈的句子值得我們去珍藏,今天就遇到了個比較巧妙的數組使用方法,做個記錄,以供後續使用.
插入排序的C、C++實現
一、插入排序 有一個已經有序的資料序列,要求在這個已經排好的資料序列中插入一個數,但要求插入後此資料序列仍然有序,這個時候就要用到一種新的排序方法——插入排序法,插入排序的基本操作就是將一個數據插入到已經排好序的有序資料中,從而得到一個新的、個數加一的有序資料,演算法適用於少量資料的排序,時間複雜度為O(n
氣泡排序的C、C++實現
一、氣泡排序 氣泡排序就是重複地走訪過要排序的元素列,依次比較兩個相鄰的元素,如果他們的順序(如數字從大到小、首字母從A到Z)錯誤就把他們交換過來。走訪元素的工作是重複地進行直到沒有相鄰元素需要交換,也就是說該元素已經排序完成。 這個演算法的名字由來是因為越大的元素會經由交換慢慢“浮”到數列的頂端(升序或
想分一杯自動駕駛招聘熱潮的羹?先學好C、 C++、Python吧!python
我們正在慢慢進入自動駕駛的時代。 雖然進步神速,而且特斯拉的自動駕駛汽車已經行駛了將近15億英里,但是一些酷炫的事情仍然只存在科幻小說裡。 根據最新麻省理工的一項研究,48%的消費者沒有購買全自動駕駛汽車的意願。 即便如此,對於相關領域的職位,求職者仍然趨之若鶩。自2015
用.net core 寫後端—— c++外的另一種選擇?
https://blog.csdn.net/kenkao/article/details/71249138 用.net core 寫後端—— c++外的另一種選擇? 2017年05月06日 10:40:48 獨孤殘雲 閱讀數:8283 本文原創版權歸 騰訊GAD&nb
C#獲取List的一種方式
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 using System.Linq; 5 6 public class lgs : MonoBehaviour 7
LeetCode 442. 陣列中重複的資料(C、C++、python)
給定一個整數陣列 a,其中1 ≤ a[i] ≤ n (n為陣列長度), 其中有些元素出現兩次而其他元素出現一次。 找到所有出現兩次的元素。 你可以不用到任何額外空間並在O(n)時間複雜度內解決這個問題嗎? 示例: 輸入: [4,3,2,7,8,2,3,1] 輸出
C# 三層實現對多表資料查詢
首先:資料庫設計--使用mysql資料庫。資料庫名稱:DBTest 資料表有4個: //年級表(Grade):gradeid,gradename //學生表(Student):studentno,gradeid,studentname
Java、C、C+ +、PHP、Python分別用來開發什麼?一篇文章告訴你!
我自己是一名大資料架構師,目前辭職在做線上教育大資料講師,每天都會直播分享免費公開課,大家可以加群參加。以及我自己整理了一套最新的大資料學習系統教程,包括Hadoop,資料探勘,資料分析。送給正在學習大資料的小夥伴!這裡是大資料學習者聚集地,歡迎初學和進階中的小夥伴!加QQ群:5849001
【C語言】實現對一個8bit資料(unsigned char 型別)的指定位(例如第n位)的置0或者置1操作,並保持其他位不變
請編碼實現以下功能的函式 功能:實現對一個8bit資料(unsigned char 型別)的指定位(例如第n位)的置0或者置1操作,並保持其他位不變。 函式原型:void bit_set(unsigned char *p_data,unsigned char position,int flag)
C++知識分享:一種C++函式的過載機制
一種C++函式過載機制 這個機制是由張素琴等人提出並實現的,他們寫了一個C++的編譯系統COC++(開發在國產機上,UNIX作業系統環境下具有中國自己版權的C、C++和FORTRAN語言編譯系統,這些編譯系統分別滿足了ISOC90、AT&T的C++85和ISOFORTRAN90標準)。COC++中的
【C語言】實現對一個8bit資料的指定位的置0或者置1操作,並保持其他位不變。
給定函式原型:void bit_set(unsigned char *p_data,unsigned char positin,int flag) 引數說明:p_data是指定的源資料;position是指定位(取值範圍為1~8);flag表示置0還是
【C語言】實現對一個8bit資料(unsigned char)型別的指定位的置0或置1操作,並保持其他位不變
功能:實現對一個8bit資料(unsigned char)型別的指定位(例如第n位)的置0或置1操作,並保持其他位不變。 函式原型:void bit_set(unsigned char *p_data
PHP、Java、Python、C、C++ 這幾種程式語言都各有什麼特點或優點?
Java 猶如宮澤賢治的《不畏風雨》中出現的、性格木訥的女孩子。從小就由於遲鈍和大食量等特徵被別人當作笨蛋,從小學入學開始進入田徑部、堅持跑步,在中長跑中經常取得好成績,給人以活潑的印象。是十分努力的女孩子。 她的家境並不算好。父親Sun是有才能的藝術家,但不擅長理財,在她14歲的時候因為苦於借債積勞