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

📄 ppmdsuballoc.h

📁 7-Zip 3.11的源码
💻 H
字号:
// SubAlloc.h
// This code is based on Dmitry Shkarin's PPMdH code

#pragma once

#ifndef __SubAlloc_H
#define __SubAlloc_H

#include "PPMdType.h"

const UINT N1=4, N2=4, N3=4, N4=(128+3-1*N1-2*N2-3*N3)/4;
const UINT UNIT_SIZE=12, N_INDEXES=N1+N2+N3+N4;

#pragma pack(1)
struct MEM_BLK {
    WORD Stamp, NU;
    MEM_BLK* next, * prev;
    void insertAt(MEM_BLK* p) {
        next=(prev=p)->next;                p->next=next->prev=this;
    }
    void remove() { prev->next=next;        next->prev=prev; }
} _PACK_ATTR;
#pragma pack()


class CSubAllocator
{
  DWORD SubAllocatorSize;
  BYTE Indx2Units[N_INDEXES], Units2Indx[128], GlueCount;
  struct NODE { NODE* next; } FreeList[N_INDEXES];
public:
  BYTE* HeapStart, * pText, * UnitsStart, * LoUnit, * HiUnit;
  CSubAllocator():
    SubAllocatorSize(0),
    GlueCount(0),
    pText(0),
    UnitsStart(0),
    LoUnit(0),
    HiUnit(0)
  {
    memset(Indx2Units, 0, sizeof(Indx2Units));
    memset(FreeList, 0, sizeof(FreeList));
  }
  ~CSubAllocator()
  {
    StopSubAllocator();
  };


inline void InsertNode(void* p,int indx) {
    ((NODE*) p)->next=FreeList[indx].next;  FreeList[indx].next=(NODE*) p;
}
inline void* RemoveNode(int indx) {
    NODE* RetVal=FreeList[indx].next;       FreeList[indx].next=RetVal->next;
    return RetVal;
}
inline UINT U2B(int NU) { return 8*NU+4*NU; }
inline void SplitBlock(void* pv,int OldIndx,int NewIndx)
{
    int i, UDiff=Indx2Units[OldIndx]-Indx2Units[NewIndx];
    BYTE* p=((BYTE*) pv)+U2B(Indx2Units[NewIndx]);
    if (Indx2Units[i=Units2Indx[UDiff-1]] != UDiff) {
        InsertNode(p,--i);                  p += U2B(i=Indx2Units[i]);
        UDiff -= i;
    }
    InsertNode(p,Units2Indx[UDiff-1]);
}

DWORD _STDCALL GetUsedMemory()
{
    DWORD i, k, RetVal=SubAllocatorSize-(HiUnit-LoUnit)-(UnitsStart-pText);
    for (k=i=0;i < N_INDEXES;i++, k=0) {
        for (NODE* pn=FreeList+i;(pn=pn->next) != NULL;k++)
                ;
        RetVal -= UNIT_SIZE*Indx2Units[i]*k;
    }
    return (RetVal >> 2);
}

  void _STDCALL StopSubAllocator() 
  {
    if ( SubAllocatorSize ) 
    {
      #ifdef WIN32
      VirtualFree(HeapStart, 0, MEM_RELEASE);
      #else
      delete[] HeapStart;
      #endif
      SubAllocatorSize = 0;
      HeapStart = 0;
    }
  }

  bool _STDCALL StartSubAllocator(UINT32 aSize)
  {
    if (SubAllocatorSize == aSize)              
      return true;
    StopSubAllocator();
    #ifdef WIN32
    if ((HeapStart = (BYTE *)::VirtualAlloc(0, aSize, MEM_COMMIT, PAGE_READWRITE)) == 0)
      return false;
    #else
    if ((HeapStart = new BYTE[aSize]) == NULL)    
      return false;
    #endif
    SubAllocatorSize = aSize;                     
    return true;
  }

inline void InitSubAllocator()
{
    int i, k;
    memset(FreeList,0,sizeof(FreeList));
    HiUnit=(pText=HeapStart)+SubAllocatorSize;
    UINT Diff=UNIT_SIZE*(SubAllocatorSize/8/UNIT_SIZE*7);
    LoUnit=UnitsStart=HiUnit-Diff;
    for (i=0,k=1;i < N1     ;i++,k += 1)    Indx2Units[i]=k;
    for (k++;i < N1+N2      ;i++,k += 2)    Indx2Units[i]=k;
    for (k++;i < N1+N2+N3   ;i++,k += 3)    Indx2Units[i]=k;
    for (k++;i < N1+N2+N3+N4;i++,k += 4)    Indx2Units[i]=k;
    for (GlueCount=k=i=0;k < 128;k++) {
        i += (Indx2Units[i] < k+1);         Units2Indx[k]=i;
    }
}
inline void GlueFreeBlocks()
{
    MEM_BLK s0, * p, * p1;
    int i, k, sz;
    if (LoUnit != HiUnit)                   *LoUnit=0;
    for (i=0, s0.next=s0.prev=&s0;i < N_INDEXES;i++)
            while ( FreeList[i].next ) {
                p=(MEM_BLK*) RemoveNode(i); p->insertAt(&s0);
                p->Stamp=0xFFFF;            p->NU=Indx2Units[i];
            }
    for (p=s0.next;p != &s0;p=p->next)
        while ((p1=p+p->NU)->Stamp == 0xFFFF && int(p->NU)+p1->NU < 0x10000) {
            p1->remove();                   p->NU += p1->NU;
        }
    while ((p=s0.next) != &s0) {
        for (p->remove(), sz=p->NU;sz > 128;sz -= 128, p += 128)
                InsertNode(p,N_INDEXES-1);
        if (Indx2Units[i=Units2Indx[sz-1]] != sz) {
            k=sz-Indx2Units[--i];           InsertNode(p+(sz-k),k-1);
        }
        InsertNode(p,i);
    }
}
void* AllocUnitsRare(int indx)
{
    if ( !GlueCount ) {
        GlueCount = 255;                    GlueFreeBlocks();
        if ( FreeList[indx].next )          return RemoveNode(indx);
    }
    int i=indx;
    do {
        if (++i == N_INDEXES) {
            GlueCount--;                    i=U2B(Indx2Units[indx]);
            return (UnitsStart-pText > i)?(UnitsStart -= i):(NULL);
        }
    } while ( !FreeList[i].next );
    void* RetVal=RemoveNode(i);             SplitBlock(RetVal,i,indx);
    return RetVal;
}
inline void* AllocUnits(int NU)
{
    int indx=Units2Indx[NU-1];
    if ( FreeList[indx].next )              return RemoveNode(indx);
    void* RetVal=LoUnit;                    LoUnit += U2B(Indx2Units[indx]);
    if (LoUnit <= HiUnit)                   return RetVal;
    LoUnit -= U2B(Indx2Units[indx]);        return AllocUnitsRare(indx);
}
inline void* AllocContext()
{
    if (HiUnit != LoUnit)                   return (HiUnit -= UNIT_SIZE);
    if ( FreeList->next )                   return RemoveNode(0);
    return AllocUnitsRare(0);
}
inline void* ExpandUnits(void* OldPtr,int OldNU)
{
    int i0=Units2Indx[OldNU-1], i1=Units2Indx[OldNU-1+1];
    if (i0 == i1)                           return OldPtr;
    void* ptr=AllocUnits(OldNU+1);
    if ( ptr ) {
        memcpy(ptr,OldPtr,U2B(OldNU));      InsertNode(OldPtr,i0);
    }
    return ptr;
}
inline void* ShrinkUnits(void* OldPtr,int OldNU,int NewNU)
{
    int i0=Units2Indx[OldNU-1], i1=Units2Indx[NewNU-1];
    if (i0 == i1)                           return OldPtr;
    if ( FreeList[i1].next ) {
        void* ptr=RemoveNode(i1);           memcpy(ptr,OldPtr,U2B(NewNU));
        InsertNode(OldPtr,i0);              return ptr;
    } else {
        SplitBlock(OldPtr,i0,i1);           return OldPtr;
    }
}
inline void FreeUnits(void* ptr,int OldNU)
{
    InsertNode(ptr,Units2Indx[OldNU-1]);
}
};

#endif

⌨️ 快捷键说明

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