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

📄 gmmf.cpp

📁 具有工业强度的内存池动态库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// @doc
//
// @module              Gmmf.cpp - Global Memory Mapped File Object |
//
// The CGmmf class contains member functions that allow the
// caller to allocate global memory and automatically handle
// expanding and re-mapping the memory.
//

// Maintenance:
//      
// Version   Date         Who           What
// -------   -----------  ------        -------------------------------------
// 7.0       07/27/96     msb           Created
//


#include <stdio.h>
#include <windows.h>
#include <ItkDef.h>
#include <DrvRegistry.h>
#include <LogEvent.h>
#include <DrvSystem.h>
#include <ItkErr.h>
#include "gmmf.h"


static SYSTEM_INFO Gsinf;

// 
// @mfunc <c CGmmf> constructor for this class. This
//                  constuctor will create a memory mapped file and 
//                  place it in the address space of the process. It 
//                  will check the registry for run-time parameters,
//                  kick-off a thread responsible for freeing
//                  memory when it expands and create an initial global
//                  memory area.
//
// @parm   const TCHAR * | pszApp | Name of the application using this object
//
// @parm   const TCHAR * | pszKey | Registry key where parameters are stored
//
// @parm   const TCHAR * | pszName | Name of memory area to be created
//
// @devnote Until someone attempts to add a block, the memory and file
//          sizes will be 0. The first attempt to access the memory will
//          trigger an expansion to the needed size.
// 
CGmmf::CGmmf(IN const TCHAR *pszApp, IN const TCHAR *pszKey, 
			 IN const TCHAR *pszName)
{
	TCHAR szTemp[MAX_PATH],
		  szMemoryFile[MAX_PATH];

	DWORD dwStatus,
		  dwSize = MAX_PATH;

	//
	//  Set the sizes to some defaults, in case the registry 
	//      does not contain these keys
	//
	m_dwFileSizeMax = FILESIZEMAX;
	m_dwFileGrowInc = FILEGROWINC;
	m_dwOverrunBuf  = OVERRUNBUF;

	m_bItsMe = FALSE;

	//
	//  Check the registry
	//
	CRegistry pRegistry;

	pRegistry.OpenKey(pszKey);
	pRegistry.ReadValue("MaxSize", &m_dwFileSizeMax);
	pRegistry.ReadValue("GrowIncrement", &m_dwFileGrowInc);
	pRegistry.ReadValue("OverrunBuffer", &m_dwOverrunBuf);
	dwStatus = pRegistry.ReadValue("BasePath", 
								   (TCHAR *)&m_szBasePath, 
								   (DWORD *)&dwSize);
	if (ERROR_SUCCESS == dwStatus)
	{
		strcpy(szMemoryFile, m_szBasePath);
		strcat(szMemoryFile, pszName);
	}
	else
	{
		m_szBasePath[0] = '\0';
		strcpy(szMemoryFile, pszName);
	}

	pRegistry.CloseKey();


	//
	//  If a name for the memory is specified, copy it in
	//
	if (NULL != pszName)
	{
		m_szRegionName = _strdup(pszName);
	}
	else
	{
		m_szRegionName = NULL;
	}

	
	m_hFileMap = 0;
	m_pbFile = 0;
	m_bShutdown = FALSE;

	//
	// Open the event log for this driver
	//
	sprintf(szTemp, "%s", pszApp);
	m_pLog = new CLogEvent(szTemp);

	
	//
	//  Initialize the Win32 security attributes structures
	//
	INIT_SECURITY_ALL(m_SecAttr, m_SecDesc);
	
	//
	//  Create a static MMF that we don't have to worry about
	//  resizing ...
	//
	if (MapControlBlock(pszName))
	{
		//
		//  Start a thread to wait for remap events
		//
		if (StartRemapThread(pszName))
		{
			if (*pszName != '\0')
			{
				m_hFile = CreateFile(szMemoryFile, 
									 GENERIC_READ|GENERIC_WRITE, 
									 FILE_SHARE_READ|FILE_SHARE_WRITE,
									 &m_SecAttr, 
									 OPEN_ALWAYS, 
									 FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_HIDDEN,
									 NULL);
				//
				//  If there is an error creating the disk file, log it
				//
				if (m_hFile == INVALID_HANDLE_VALUE) 
				{
					LogError(GetLastError(), MEM_CREATE_FILE, pszName);
					m_hFile = 0;
					return;
				}
			}
			else
			{
				m_hFile = HFILE_PAGEFILE;
			}
			//kyu001204 - initialize to 1: RoundUp(0,value) returns 0.
			m_dwFileSizeNow = 1;
			m_hFileMapRes = 0;

			//
			//  Bump the number of instances of this object
			//
			InterlockedIncrement((LPLONG)&m_pCtlBlock->dwTotalInstances);

			//
			//  Go build it
			//
			Create();
		}
	}
}

//
// 
// @mfunc <c ~CGmmf> destructor for this class. This
//                   destructor closes memory and releases all
//                   the Win32 resources allocated.
// 
CGmmf::~CGmmf()
{
	Close(m_dwFileSizeNow);
}


//
// 
// @mfunc <c Create> General routine to create the initial memory.
//                   This function will roundup the maximum file size 
//                   as well as the growth increment based on the
//                   systems allocation granularity. This function is only
//                   called from the constructor.
// 
// @rvalue None | 
//
void CGmmf::Create(void)
{
	DWORD dwMaxRgnSize;

	if (Gsinf.dwAllocationGranularity == 0) 
	{
		GetSystemInfo(&Gsinf);
	}


	m_dwFileSizeMax = RoundUp(m_dwFileSizeMax, Gsinf.dwAllocationGranularity);
	m_dwFileGrowInc = RoundUp(m_dwFileGrowInc, Gsinf.dwAllocationGranularity);

	// Reserve an address space region that is big enough to hold 
	// the GMMF assuming that it grew to its maximum size and the 
	// overrun buffer area.
	dwMaxRgnSize = m_dwFileSizeMax + m_dwOverrunBuf;
	
	// Windows NT guarantess allocation granularity so we don't 
	// have to force it.
	m_pbFile = (PBYTE)ResAddrSpace(NULL, dwMaxRgnSize);
   


   // Adjust the GMMF region so that it contains a MMF backed by the disk 
   // file's storage and a reserved region (up to the maximum size of the 
   // GMMF specified) immediately following the MMF.
   Adjust(m_dwFileSizeNow);
}

//
// 
// @mfunc <c ~ExcFilter> Stuctured Exception Handler for the Gmmf object.
//                       If the calling routine contains a try-except
//                       block specifying this routine, it will be called
//                       when an exception occurs. We then determine if its
//                       an exception we want to deal with. If it is
//                       determined to be attempt to expand the memory of
//                       this object, we call Adjust to re-size the global
//                       memory mapped file.
//
// @parm   PEXCEPTION_POINTERS | pExpception | pointer to an exception record
//
// @rvalue EXCEPTION_CONTINUE_EXCEPTION | If successful 
// @rvalue EXCEPTION_CONTINUE_SEARCH | If this is not an exception we want to deal with
// @rvalue EXCEPTION_NONCONTINUABLE | If attempting to write past the maximum allowed size
//
long CGmmf::ExcFilter(IN PEXCEPTION_POINTERS pException)
{
	DWORD lDisposition = EXCEPTION_CONTINUE_SEARCH;

	PEXCEPTION_RECORD pExceptionRecord = pException->ExceptionRecord;

	PBYTE pbAccAddr;


	// 
	// If its not a access violation, we don't want it
	//
	if (pExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) 
	{
		return(lDisposition);
	}

	//
	// Get the address of the attempted memory access
	//
	pbAccAddr = (PBYTE)pExceptionRecord->ExceptionInformation[1];

	//
	// Check to see if we are writing into the overrun area
	//
	if (InRange(m_pbFile + m_dwFileSizeMax, pbAccAddr, 
				m_pbFile + m_dwFileSizeMax + m_dwOverrunBuf - 1)) 
	{
		RaiseException(EXCEPTION_GMMF_WRITEPAST, 
					   EXCEPTION_NONCONTINUABLE, 
					   0, 
					   NULL);
	}

	//
	// Check to see if its outside our area of interest
	//
	if (!InRange(m_pbFile, pbAccAddr, m_pbFile + m_dwFileSizeMax - 1))
	{
		return(lDisposition);
	}

	//
	//  Check to see if someone else expanded the area beyond
	//  what we know about
	//
	DWORD dwNewSize;

	if (m_pCtlBlock->dwMaxSize > (DWORD)((pbAccAddr-m_pbFile+1)))
	{
		 dwNewSize = m_pCtlBlock->dwMaxSize;
	}
	else
	{
		dwNewSize = m_pCtlBlock->dwMaxSize = (pbAccAddr-m_pbFile+1);
	}

	Adjust(dwNewSize);

	return(EXCEPTION_CONTINUE_EXECUTION);
}


// Closes a GMMF and truncates the file to the specified size.
// 
// @mfunc <c Close> Called from the destructor to cleanup all the 
//                  Win32 resources allocated and truncate the file
//                  to the specified size.
//
// @parm   IN DWORD | dwDiskFile | Size to truncate the file to
//
// @rvalue None | 
//
void CGmmf::Close(IN DWORD dwDiskFile) 
{
	DWORD dwReturn;

	//
	// Notify the remap thread that we're shutting down
	// We set the event to free it from its wait.
	//
	m_bItsMe = TRUE;
	m_bShutdown = TRUE;
	SetEvent(m_hShutdownEvent);

	//
	//  Wait for the thread to exit. If it times out, kill it
	//
	dwReturn = WaitForSingleObject(m_hRemapThread,3000);
	if (WAIT_TIMEOUT == dwReturn)
	{
		TerminateThread(m_hRemapThread,0);
	}

	//
	// Shrink the file to its required size
	//
	if (m_hFile != HFILE_PAGEFILE)
	{
		SetFilePointer(m_hFile, dwDiskFile, NULL, FILE_BEGIN);
		SetEndOfFile(m_hFile);
		FlushFileBuffers(m_hFile);
		CloseHandle(m_hFile);
	}

	//
	// Unmap the view of the file, close the file-mapping object 
	// and free the reserved address space region
	//
	Clear();

	m_dwFileSizeNow = 0;
	m_dwFileSizeMax = 0;
	m_dwFileGrowInc = 0;
	m_dwOverrunBuf = 0;
	m_hFileMap = 0;
	m_pbFile = 0;
	m_hFileMapRes = 0;

	//
	//  Decrement the total number of object instantiations
	//
	InterlockedDecrement((LPLONG)&m_pCtlBlock->dwTotalInstances);
	if (0 == m_pCtlBlock->dwTotalInstances)
	{
		TCHAR szTemp[MAX_PATH];

		if ('\0' != m_szBasePath[0])
		{
			strcpy(szTemp, m_szBasePath);
			strcat(szTemp, m_szRegionName);
		}
		else
		{
			strcpy(szTemp, m_szRegionName);
		}

		if (!DeleteFile(szTemp))
		{
			LogError(GetLastError(), MEM_DELETE_FILE, szTemp);
		}

		m_pCtlBlock->dwElements = 0;
		m_pCtlBlock->dwMaxSize = 0;
	}


	//
	// Since this area was malloc'ed by the _strdup
	// function, we will free it here
	//
	if (m_szRegionName != NULL)
	{
		free(m_szRegionName);
		m_szRegionName = NULL;
	}


	//
	//  Cleanup the "Control Block"
	//
	UnmapViewOfFile(m_pCtlBlock);   // Unmap the virtual memory
	CloseHandle(m_hCBlock);         // Close the File Map Object
	CloseHandle(m_hRemapThread);    // Close the thread handle
	CloseHandle(m_hRemapEvent);     // Close the event
	CloseHandle(m_hShutdownEvent);  // ""   "	"

	//
	//  Free our event log object
	//
	delete m_pLog;
}


// 
// @mfunc <c Clear> This function clears the memory mapped file and
//                  any reserved space following it. If a memory mapped
//                  file actually exists and we close the handle, we
//                  decrement a counter of how many instances are 
//                  currently mapped to it.
//
// @rvalue TRUE | If we were actually mapped to a memory mapped file
// @rvalue FALSE | If we had not mapped, but only reserved memory
//
BOOL CGmmf::Clear()
{
	MEMORY_BASIC_INFORMATION mbi;

	//
	// Get the state of memory at the base of the GMMF region.
	//
	VirtualQuery(m_pbFile, &mbi, sizeof(mbi));

	//
	// Enhance our chances of running the upcoming code without
	// interruption
	//
	Sleep(0);

	if (mbi.State == MEM_RESERVE)
	{
		UnmapViewOfFile(mbi.AllocationBase);
		CloseHandle(m_hFileMapRes);
	} 
	else
	{
		UnmapViewOfFile(m_pbFile);
		if (mbi.RegionSize < m_dwFileSizeMax + m_dwOverrunBuf) 
		{
			UnmapViewOfFile((PBYTE)mbi.AllocationBase + mbi.RegionSize);
			CloseHandle(m_hFileMapRes);
		}
	}

	if (m_hFileMap != NULL)
	{
		CloseHandle(m_hFileMap);
		m_hFileMap = NULL;
		InterlockedDecrement((LPLONG)&m_pCtlBlock->dwCurrentlyMapped);
		return(TRUE);
	}
	
	return(FALSE);
}


// 
// @mfunc <c Construct> Allocates the memory mapped file and any
//                      reserved space following it.
//
// @parm   IN DWORD | dwDiskFileNow | New size for the memory
//
// @rvalue None |
//
void CGmmf::Construct(IN DWORD dwDiskFileNow) 
{
	DWORD dwDiskFileNew = RoundUp(dwDiskFileNow, m_dwFileGrowInc),
		  dwStatus = ERROR_SUCCESS;

	PBYTE pbTemp;

	if (dwDiskFileNew > 0) 
	{
		//
		// Grow the MMF by creating a new file-mapping object.
		//

		m_hFileMap = CreateFileMapping(m_hFile, 
									   &m_SecAttr, 
									   PAGE_READWRITE, 
									   0, 
									   dwDiskFileNew, 
									   m_szRegionName);
		if (m_hFileMap == NULL) 
		{
			LogError(GetLastError(), MEM_CREATE_MMF, m_szRegionName);

			// 
			//  File-mapping could not be created, the disk is 
			//  probably full.
			//
			RaiseException(EXCEPTION_GMMF_DISKFULL, 
						   EXCEPTION_NONCONTINUABLE, 
						   0, 
						   NULL);
		}

		// 
		//  Map the new MMF at the same location as 
		//  the previously mapped view.
		//
		//kyu001204 - map the size of dwDiskFileNew only:
		pbTemp = (PBYTE)MapViewOfFileEx(m_hFileMap, 
										FILE_MAP_ALL_ACCESS, 
										0, 
										0, 
										dwDiskFileNew, 
										m_pbFile);

⌨️ 快捷键说明

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