//////////////////////////////////////// /////////////////////////
// Custom Memory Manager
//
// [Total number of idle instances (4 bytes)]
// [Data block (itemsize byte)] [occupied (1 byte)] [current block index (4 byte)] [next block index (4 byte)]
// [Data block (itemsize byte)] [occupied (1 byte)] [current block index (4 byte)] [next block index (4 byte)]
//......
// [Data block (itemsize byte)] [occupied (1 byte)] [current block index (4 byte)] [next block index (4 byte)]
// [1st idle block Index] [2nd idle block Index] ...... [nth idle block Index]
// The Block index starts from 1.
//////////////////////////////////////// /////////////////////////
Class cmymemorymanager
{
PRIVATE:
Int m_itemcount; // The total number of parts.
Int m_itemsize; // The number of bytes.
Int m_blocksize; // the size of each item = m_itemsize + 5
Int m_freeindexaddr; // The first address of the idle index area.
Lpvoid pdata; // The first address of the global memory area.
Handle m_waitevent; // wait for the event (wait when idle memory is insufficient)
Critical_section m_lock; // data mutex lock
// Initialize the memory area (Reserved memory area)
Bool Init (INT iitemsize, int iitemcount );
Public:
Cmymemorymanager (INT iitemsize, int iitemcount );
~ Cmymemorymanager ();
Void lock ();
Void unlock ();
// Apply for Memory Reference
Lpvoid new (INT Len );
// Release memory reference
Bool Delete (lpvoid P );
// Obtain the number of bytes of data blocks
Int getitemsize ();
// Obtain the total number of blocks
Int getitemcount ();
// Obtain the total number of idle instances.
Int getfreecount ();
// Obtain the first address of the Data Area
Int getbeginaddr () {return (INT) pdata ;};
};
// Implementation
# Include "stdafx. H"
# Include "windows. H"
# Include "mymemorymanager. H"
Cmymemorymanager: cmymemorymanager (INT iitemsize, int iitemcount)
{
M_waitevent =: createevent (null, true, false, null );
Initializecriticalsection (& m_lock );
If (! Init (iitemsize, iitemcount ))
Afxmessagebox ("failed to open the custom memory zone! ");
};
Cmymemorymanager ::~ Cmymemorymanager ()
{
//: Globalunlock (hdata );
: Globalfree (pdata );
Deletecriticalsection (& m_lock );
Closehandle (m_waitevent );
};
// Initialize the memory area (Reserved memory area)
// Iitemsize-number of bytes each iitemcount-Total number of bytes
Bool cmymemorymanager: Init (INT iitemsize, int iitemcount)
{
Int iindexaddr;
M_itemsize = iitemsize;
M_itemcount = iitemcount;
M_blocksize = iitemsize + 9;
Pdata =: globalalloc (gmem_fixed | gmem_zeroinit,
4 + iitemcount * (iitemsize + 9) +
Iitemcount * 4 );
If (! Pdata) return false;
// Initialize idle block information
* (Int *) pdata) = iitemcount;
M_freeindexaddr = (INT) pdata + 4 + iitemcount * (iitemsize + 9 );
For (INT I = 1; I <= m_itemcount; I ++)
{
* (Int *) (m_freeindexaddr + (I-1) * 4) = I; // idle Index
Iindexaddr = (INT) pdata + 4 + (I-1) * m_blocksize + m_itemsize + 1;
* (Int *) iindexaddr) = I; // each index
}
Return true;
}
Void cmymemorymanager: Lock ()
{
Entercriticalsection (& m_lock );
}
Void cmymemorymanager: Unlock ()
{
Leavecriticalsection (& m_lock );
}
// Apply for Memory Reference
Lpvoid cmymemorymanager: New (INT Len)
{
Bool blnget = false;
Int iindex;
Int inext = 0;
Int ineedcount;
Int ifreecount;
Int irefaddr;
Lpvoid P = NULL;
// Calculate the number of blocks to be applied
Ineedcount = (INT) (LEN/m_itemsize );
If (ineedcount * m_itemsize <Len) ineedcount ++;
While (! Blnget)
{
// Check whether there are sufficient idle Blocks
Lock ();
Ifreecount = * (int *) pdata );
If (ifreecount * m_itemsize <Len)
{
// Insufficient space. Wait
Unlock ();
Waitforsingleobject (m_waitevent, 200 );
}
Else
{
For (INT I = ifreecount; I> = 1; I --)
{
// Read the idle block Index
Iindex = * (int *) (m_freeindexaddr + (I-1) * 4 ));
Irefaddr = (INT) pdata + 4 + (iindex-1) * m_blocksize + m_itemsize;
// Mark of write occupation
* (Byte *) irefaddr) = 1;
// Reduce the total number of idle instances
* (Int *) pdata) = * (int *) pdata)-1;
// Write down an index
* (Int *) (irefaddr + 5) = inext;
// Obtain the first block address
P = (lpvoid) (irefaddr-m_itemsize );
Ineedcount --;
If (ineedcount = 0) break;
// Save the current block Index
Inext = iindex;
}
Unlock ();
Blnget = true;
}
}
Return P;
}
// Release memory reference
Bool cmymemorymanager: delete (lpvoid P)
{
Byte * Pref;
Int * pnext;
Int inext = 1;
If (P = NULL) return true;
While (inext> = 1)
{
// Clear data block content
// Zeromemory (p, m_itemsize );
Lock ();
// Clear reference
Pref = (byte *) (INT) P + m_itemsize );
// Add idle data to write idle Indexes
If (* Pref! = 0)
{
Int * pfree = (int *) pdata;
* Pfree = * pfree + 1;
* (Int *) (m_freeindexaddr + (* pfree-1) * 4) = * (int *) (INT) P + m_itemsize + 1 ));
}
* Pref = 0;
// Read and clear the next Index
Pnext = (int *) (INT) P + m_itemsize + 5 );
Inext = * pnext;
* Pnext = 0;
Unlock ();
// Calculate the next address
If (inext> = 1)
P = (lpvoid) (INT) pdata + 4 + (inext-1) * (m_itemsize + 5 ));
}
P = NULL;
Return true;
}
// Obtain the number of bytes of data blocks
Int cmymemorymanager: getitemsize ()
{
Return m_itemsize;
}
// Obtain the total number of blocks
Int cmymemorymanager: getitemcount ()
{
Return m_itemcount;
}
// Obtain the total number of idle instances.
Int cmymemorymanager: getfreecount ()
{
Int icnt;
Lock ();
Copymemory (& icnt, pdata, 4 );
Unlock ();
Return icnt;
}