Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

SubAlloc.h

Go to the documentation of this file.
00001 /****************************************************************************
00002  *  This file is part of PPMd project                                       *
00003  *  Written and distributed to public domain by Dmitry Shkarin 1997,        *
00004  *  1999-2001                                                               *
00005  *  Contents: memory allocation routines                                    *
00006  ****************************************************************************/
00007 
00008 enum { UNIT_SIZE=12, N1=4, N2=4, N3=4, N4=(128+3-1*N1-2*N2-3*N3)/4,
00009         N_INDEXES=N1+N2+N3+N4 };
00010 
00011 #pragma pack(1)
00012 struct BLK_NODE {
00013     DWORD Stamp;
00014     BLK_NODE* next;
00015     BOOL   avail()      const { return (next != NULL); }
00016     void    link(BLK_NODE* p) { p->next=next; next=p; }
00017     void  unlink()            { next=next->next; }
00018     void* remove()            {
00019         BLK_NODE* p=next;                   unlink();
00020         Stamp--;                            return p;
00021     }
00022     inline void insert(void* pv,int NU);
00023 } BList[N_INDEXES];
00024 struct MEM_BLK: public BLK_NODE { DWORD NU; } _PACK_ATTR;
00025 #pragma pack()
00026 
00027 static BYTE Indx2Units[N_INDEXES], Units2Indx[128]; // constants
00028 static DWORD GlueCount, SubAllocatorSize=0;
00029 static BYTE* HeapStart, * pText, * UnitsStart, * LoUnit, * HiUnit;
00030 
00031 inline void PrefetchData(void* Addr)
00032 {
00033 #if defined(_USE_PREFETCHING)
00034     BYTE PrefetchByte = *(volatile BYTE*) Addr;
00035 #endif /* defined(_USE_PREFETCHING) */
00036 }
00037 inline void BLK_NODE::insert(void* pv,int NU) {
00038     MEM_BLK* p=(MEM_BLK*) pv;               link(p);
00039     p->Stamp=~0UL;                          p->NU=NU;
00040     Stamp++;
00041 }
00042 inline UINT U2B(UINT NU) { return 8*NU+4*NU; }
00043 inline void SplitBlock(void* pv,UINT OldIndx,UINT NewIndx)
00044 {
00045     UINT i, k, UDiff=Indx2Units[OldIndx]-Indx2Units[NewIndx];
00046     BYTE* p=((BYTE*) pv)+U2B(Indx2Units[NewIndx]);
00047     if (Indx2Units[i=Units2Indx[UDiff-1]] != UDiff) {
00048         k=Indx2Units[--i];                  BList[i].insert(p,k);
00049         p += U2B(k);                        UDiff -= k;
00050     }
00051     BList[Units2Indx[UDiff-1]].insert(p,UDiff);
00052 }
00053 DWORD _STDCALL GetUsedMemory()
00054 {
00055     DWORD i, RetVal=SubAllocatorSize-(HiUnit-LoUnit)-(UnitsStart-pText);
00056     for (i=0;i < N_INDEXES;i++)
00057             RetVal -= UNIT_SIZE*Indx2Units[i]*BList[i].Stamp;
00058     return RetVal;
00059 }
00060 void _STDCALL StopSubAllocator() {
00061     if ( SubAllocatorSize ) {
00062         SubAllocatorSize=0;                 delete[] HeapStart;
00063     }
00064 }
00065 BOOL _STDCALL StartSubAllocator(UINT SASize)
00066 {
00067     DWORD t=SASize << 19U;
00068     if (SubAllocatorSize == t)              return TRUE;
00069     StopSubAllocator();
00070     if ((HeapStart=new BYTE[t]) == NULL)    return FALSE;
00071     SubAllocatorSize=t;                     return TRUE;
00072 }
00073 static inline void InitSubAllocator()
00074 {
00075     memset(BList,0,sizeof(BList));
00076     HiUnit=(pText=HeapStart)+SubAllocatorSize;
00077     UINT Diff=UNIT_SIZE*(SubAllocatorSize/8/UNIT_SIZE*7);
00078     LoUnit=UnitsStart=HiUnit-Diff;          GlueCount=0;
00079 }
00080 static void GlueFreeBlocks()
00081 {
00082     UINT i, k, sz;
00083     MEM_BLK s0, * p, * p0, * p1;
00084     if (LoUnit != HiUnit)                   *LoUnit=0;
00085     for (i=0, (p0=&s0)->next=NULL;i < N_INDEXES;i++)
00086             while ( BList[i].avail() ) {
00087                 p=(MEM_BLK*) BList[i].remove();
00088                 if ( !p->NU )               continue;
00089                 while ((p1=p+p->NU)->Stamp == ~0UL) {
00090                     p->NU += p1->NU;        p1->NU=0;
00091                 }
00092                 p0->link(p);                p0=p;
00093             }
00094     while ( s0.avail() ) {
00095         p=(MEM_BLK*) s0.remove();           sz=p->NU;
00096         if ( !sz )                          continue;
00097         for ( ;sz > 128;sz -= 128, p += 128)
00098                 BList[N_INDEXES-1].insert(p,128);
00099         if (Indx2Units[i=Units2Indx[sz-1]] != sz) {
00100             k=sz-Indx2Units[--i];           BList[k-1].insert(p+(sz-k),k);
00101         }
00102         BList[i].insert(p,Indx2Units[i]);
00103     }
00104     GlueCount=1 << 13;
00105 }
00106 static void* _STDCALL AllocUnitsRare(UINT indx)
00107 {
00108     UINT i=indx;
00109     if ( !GlueCount ) {
00110         GlueFreeBlocks();
00111         if ( BList[i].avail() )             return BList[i].remove();
00112     }
00113     do {
00114         if (++i == N_INDEXES) {
00115             GlueCount--;                    i=U2B(Indx2Units[indx]);
00116             return (UnitsStart-pText > i)?(UnitsStart -= i):(NULL);
00117         }
00118     } while ( !BList[i].avail() );
00119     void* RetVal=BList[i].remove();         SplitBlock(RetVal,i,indx);
00120     return RetVal;
00121 }
00122 inline void* AllocUnits(UINT NU)
00123 {
00124     UINT indx=Units2Indx[NU-1];
00125     if ( BList[indx].avail() )              return BList[indx].remove();
00126     void* RetVal=LoUnit;                    LoUnit += U2B(Indx2Units[indx]);
00127     if (LoUnit <= HiUnit)                   return RetVal;
00128     LoUnit -= U2B(Indx2Units[indx]);        return AllocUnitsRare(indx);
00129 }
00130 inline void* AllocContext()
00131 {
00132     if (HiUnit != LoUnit)                   return (HiUnit -= UNIT_SIZE);
00133     else if ( BList->avail() )              return BList->remove();
00134     else                                    return AllocUnitsRare(0);
00135 }
00136 inline void UnitsCpy(void* Dest,void* Src,UINT NU)
00137 {
00138     DWORD* p1=(DWORD*) Dest, * p2=(DWORD*) Src;
00139     do {
00140         p1[0]=p2[0];                        p1[1]=p2[1];
00141         p1[2]=p2[2];
00142         p1 += 3;                            p2 += 3;
00143     } while ( --NU );
00144 }
00145 inline void* ExpandUnits(void* OldPtr,UINT OldNU)
00146 {
00147     UINT i0=Units2Indx[OldNU-1], i1=Units2Indx[OldNU-1+1];
00148     if (i0 == i1)                           return OldPtr;
00149     void* ptr=AllocUnits(OldNU+1);
00150     if ( ptr ) {
00151         UnitsCpy(ptr,OldPtr,OldNU);         BList[i0].insert(OldPtr,OldNU);
00152     }
00153     return ptr;
00154 }
00155 inline void* ShrinkUnits(void* OldPtr,UINT OldNU,UINT NewNU)
00156 {
00157     UINT i0=Units2Indx[OldNU-1], i1=Units2Indx[NewNU-1];
00158     if (i0 == i1)                           return OldPtr;
00159     if ( BList[i1].avail() ) {
00160         void* ptr=BList[i1].remove();       UnitsCpy(ptr,OldPtr,NewNU);
00161         BList[i0].insert(OldPtr,Indx2Units[i0]);
00162         return ptr;
00163     } else {
00164         SplitBlock(OldPtr,i0,i1);           return OldPtr;
00165     }
00166 }
00167 inline void FreeUnits(void* ptr,UINT NU) {
00168     UINT indx=Units2Indx[NU-1];
00169     BList[indx].insert(ptr,Indx2Units[indx]);
00170 }
00171 inline void SpecialFreeUnit(void* ptr)
00172 {
00173     if ((BYTE*) ptr != UnitsStart)          BList->insert(ptr,1);
00174     else { *(DWORD*) ptr=~0UL;              UnitsStart += UNIT_SIZE; }
00175 }
00176 inline void* MoveUnitsUp(void* OldPtr,UINT NU)
00177 {
00178     UINT indx=Units2Indx[NU-1];
00179     if ((BYTE*) OldPtr > UnitsStart+16*1024 || (BLK_NODE*) OldPtr > BList[indx].next)
00180             return OldPtr;
00181     void* ptr=BList[indx].remove();
00182     UnitsCpy(ptr,OldPtr,NU);                NU=Indx2Units[indx];
00183     if ((BYTE*) OldPtr != UnitsStart)       BList[indx].insert(OldPtr,NU);
00184     else                                    UnitsStart += U2B(NU);
00185     return ptr;
00186 }
00187 static inline void ExpandTextArea()
00188 {
00189     BLK_NODE* p;
00190     UINT Count[N_INDEXES];                  memset(Count,0,sizeof(Count));
00191     while ((p=(BLK_NODE*) UnitsStart)->Stamp == ~0UL) {
00192         MEM_BLK* pm=(MEM_BLK*) p;           UnitsStart=(BYTE*) (pm+pm->NU);
00193         Count[Units2Indx[pm->NU-1]]++;      pm->Stamp=0;
00194     }
00195     for (UINT i=0;i < N_INDEXES;i++)
00196         for (p=BList+i;Count[i] != 0;p=p->next)
00197             while ( !p->next->Stamp ) {
00198                 p->unlink();                BList[i].Stamp--;
00199                 if ( !--Count[i] )          break;
00200             }
00201 }

Generated on Sat Nov 5 16:16:59 2005 for OPIE by  doxygen 1.4.2