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

📄 gmmf.cpp

📁 具有工业强度的内存池动态库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		dwStatus = GetLastError();
		if (NULL == pbTemp)
		{
			//kyu001204 - this should not happen, in case this happens,
			//get another base address
			m_pbFile = (PBYTE)ResAddrSpace(NULL, m_dwFileSizeMax + m_dwOverrunBuf);
		
			UnmapViewOfFile(m_pbFile);
			CloseHandle(m_hFileMapRes);

			// 
			//  Map the view again for the size of dwDiskFileNew:
			//
			pbTemp = (PBYTE)MapViewOfFileEx(m_hFileMap, 
										FILE_MAP_ALL_ACCESS, 
										0, 
										0, 
										dwDiskFileNew, 
										m_pbFile);

			if(pbTemp == NULL)
			{
				//if failed again, log the error:
				LogError(GetLastError(), MEM_MAP_VIEW, m_szRegionName);
			}
		}

		// 
		//  Check to see if our region has been corrupted 
		//  by another thread.
		//
		if (pbTemp != m_pbFile)
		{
			RaiseException(EXCEPTION_GMMF_CORRUPTEDRGN, 
						   EXCEPTION_NONCONTINUABLE, 
						   0, 
						   NULL);
		}
	
		//
		// If the memory region is larger than the size of the file, 
		// clear the leftover to zeros
		//

		DWORD dwRegionSize = (DWORD)((((float)m_dwFileSizeNow + (float)m_dwFileGrowInc - 1) / 
				(float)m_dwFileGrowInc) * (float)m_dwFileGrowInc);
		
		if (ERROR_ALREADY_EXISTS != dwStatus)
		{
			if (m_dwFileSizeNow < dwRegionSize)
			{
				memset((m_pbFile + m_dwFileSizeNow), 0, 
					   (dwRegionSize - m_dwFileSizeNow));
			}
		}

		InterlockedIncrement((LPLONG)&m_pCtlBlock->dwCurrentlyMapped);
	}


	if (dwDiskFileNew < m_dwFileSizeMax + m_dwOverrunBuf) 
	{
		//
		// Reserve space after the GMMF for growth detection.
		// The space should be reserved after the MMF and the size should be the 
		// maximum size of the file plus the overrun buffer size minus the 
		// current size of the MMF.
		//
		m_hFileMapRes = CreateFileMapping(HFILE_PAGEFILE, 
										  &m_SecAttr,
										  PAGE_READONLY|SEC_RESERVE, 
										  0, 
										  ((m_dwFileSizeMax+m_dwOverrunBuf)-dwDiskFileNew), 
										  NULL);
		if (NULL != m_hFileMapRes)
		{
			pbTemp = (PBYTE)MapViewOfFileEx(m_hFileMapRes, 
											FILE_MAP_READ, 
											0, 0, 0, 
											m_pbFile+dwDiskFileNew);
			if (NULL == pbTemp)
			{	
				//kyu001204 -  Retry to get a new base address:
				// 
				m_pbFile = (PBYTE)ResAddrSpace(NULL, m_dwFileSizeMax + m_dwOverrunBuf);
				
				UnmapViewOfFile(m_pbFile);
				CloseHandle(m_hFileMapRes);
		
				pbTemp = (PBYTE)MapViewOfFileEx(m_hFileMap, 
										FILE_MAP_ALL_ACCESS, 
										0, 
										0, 
										dwDiskFileNew, 
										m_pbFile);
  

				if(pbTemp == NULL)
				{
					LogError(GetLastError(), MEM_MAP_VIEW, m_szRegionName);

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


				}

				m_hFileMapRes = CreateFileMapping(HFILE_PAGEFILE, 
										  &m_SecAttr,
										  PAGE_READONLY|SEC_RESERVE, 
										  0, 
										  ((m_dwFileSizeMax+m_dwOverrunBuf)-dwDiskFileNew), 
										  NULL);

				if(m_hFileMapRes !=NULL)
				{
					pbTemp = (PBYTE)MapViewOfFileEx(m_hFileMapRes, 
											FILE_MAP_READ, 
											0, 0, 0, 
											m_pbFile+dwDiskFileNew);

				
					if(pbTemp == NULL)
					{
						TCHAR chWin32Error[MAX_PATH];

						m_pLog->GetErrorText(GetLastError(), (TCHAR *)&chWin32Error[0]);
						m_pLog->WriteEventLog(MEM_MAP_RESERVE,
									  EVENTLOG_ERROR_TYPE,
									  0,
									  NULL,
									  chWin32Error,
									  NULL);
					}
				}
			}
		}
		else
		{
			TCHAR chWin32Error[MAX_PATH];

			m_pLog->GetErrorText(GetLastError(), (TCHAR *)&chWin32Error[0]);
			m_pLog->WriteEventLog(MEM_CREATE_RESERVE,
								  EVENTLOG_ERROR_TYPE,
								  0,
								  NULL,
								  chWin32Error,
								  NULL);
		}

		dwStatus = GetLastError();
		// 
		//  Check to see if our region has been corrupted 
		//  by another thread.
		//
		if (pbTemp != (m_pbFile + dwDiskFileNew)) 
		{
			TCHAR dummy[80],dummy1[80];

			//kyu001204 - itoa() does not work here:
			sprintf(dummy,"%d",pbTemp);
			sprintf(dummy1,"%d",m_pbFile+dwDiskFileNew);

			m_pLog->WriteEventLog(MEM_CORRUPT,
								  EVENTLOG_ERROR_TYPE,
								  0,
								  NULL,
								  //itoa((int)pbTemp,(TCHAR *)&dummy,10),
								  //itoa((int)(m_pbFile+dwDiskFileNew),(TCHAR *)&dummy,10),
								  dummy,
								  dummy1,
								  NULL);

			RaiseException(EXCEPTION_GMMF_CORRUPTEDRGN, 
						   EXCEPTION_NONCONTINUABLE, 
						   0, 
						   NULL);
		}
	}

	m_dwFileSizeNow = dwDiskFileNew;
}


//
// @mfunc <c Adjust> This function actually handles the re-allocation 
//                   of memory when an exception occures.
//
// @parm   IN DWORD | dwDiskFileNow | New size for the memory
//
// @rvalue None |
//
void CGmmf::Adjust(IN DWORD dwDiskFileNow) 
{
	int nThreadPriority,
		nMaxLoops = 0;

	__try 
	{
		//
		// Boost our thread's priority so that another thread is 
		// less likely to use the same address space while 
		//  we're changing it.
		//
		nThreadPriority = GetThreadPriority(GetCurrentThread());
		SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);

		//
		// Clear the contents of the memory
		//
		if (Clear())
		{
			//
			//  If someone else is mapped, set an event to signal them
			//  to free their memory. They will remap on the next time
			//  they try to access the memory. We need to set a 
			//  flag (m_bItsMe) so the local thread won't also call clear().
			//
			if (m_pCtlBlock->dwCurrentlyMapped)
			{
				m_bItsMe = TRUE;
				PulseEvent(m_hRemapEvent);
		
				while ((m_pCtlBlock->dwCurrentlyMapped > 0 ) &&
					   nMaxLoops < 100)
				{
					Sleep(10);
					nMaxLoops++;
				}
			}
		}

		//
		// Restore the contents with the properly adjusted lengths
		//
		Construct(dwDiskFileNow);
	}
	__finally 
	{       
		//
		// Make sure that we always restore our priority class and thread 
		// priority so that we do not continue to adversely affect other 
		// threads in the system.
		//
		
		SetThreadPriority(GetCurrentThread(), nThreadPriority);
	}
}

//
// @mfunc <c GetAddress> This function returns the address at the base
//                       of the memory region.
//
// @rvalue VOID * | Pointer the the beginning of the gmmf
//
void *CGmmf::GetAddress()
{ 
	return(m_pbFile);
}

//
// @mfunc <c GetCurrentSize> Returns the current size, in bytes, of the
//                           memory area.
//
// @rvalue DWORD | Current size of the gmmf
//
DWORD CGmmf::GetCurrentSize()
{
	return(m_dwFileSizeNow);
}

//
// @mfunc <c GetMaximumSize> Returns the maximum size that this memory
//                           area will be allowed to expand. The value
//                           is defined in the registry.
//
// @rvalue DWORD | Maximum size memory will be allowed to grow
//
DWORD CGmmf::GetMaximumSize()
{
	return(m_dwFileSizeMax);
}

//
// @mfunc <c GetElements> Returns the number of elements that are stored
//                        in the memory object.
//
// @rvalue DWORD | Number of elements
//
DWORD CGmmf::GetElements()
{
	return(m_pCtlBlock->dwElements);
}

//
// @mfunc <c IncElements> Increments the number of elements that are stored
//                        in the memory object. This object really doesn't 
//                        care but this information needs to be kept global
//                        to all instances of this object so its stored in
//                        the control block and accessed via member functions.
//
// @rvalue None |
//
void CGmmf::IncElements()
{
	InterlockedIncrement((LPLONG)&m_pCtlBlock->dwElements);
}

//
// @mfunc <c DecElements> Decrements the number of elements that are stored
//                        in the memory object. This object really doesn't 
//                        care but this information needs to be kept global
//                        to all instances of this object so its stored in
//                        the control block and accessed via member functions.
//
// @rvalue None |
//
void CGmmf::DecElements()
{
	InterlockedDecrement((LPLONG)&m_pCtlBlock->dwElements);
}

//
// @mfunc <c MapControlBlock> This function maps a global mapped file to
//                            be used as a control block for this object.
//                            We don't have to concern ourselves with 
//                            re-sizing this area so it will exist as long
//                            as there is at least one instantiation of
//                            this object.
//
// @parm        IN const TCHAR * | szName | Name used to derive the name of the block
//
// @rvalue TRUE | If successful, otherwise it returns FALSE
//
BOOL CGmmf::MapControlBlock(IN const TCHAR *szName)
{
	DWORD   dwReturnStatus;

	TCHAR   szMemoryName[MAX_PATH];


	sprintf(szMemoryName, "%s_CB", szName);

	m_hCBlock = CreateFileMapping(HFILE_PAGEFILE,
								  &m_SecAttr,
								  PAGE_READWRITE,
								  0,
								  sizeof(CBLOCK),
								  szMemoryName);
	dwReturnStatus = GetLastError();
	if (m_hCBlock)
	{
		m_pCtlBlock = (CBLOCK *)MapViewOfFile(m_hCBlock, FILE_MAP_WRITE, 
											  0, 0, 0);
		if (m_pCtlBlock)
		{
			if (ERROR_ALREADY_EXISTS != dwReturnStatus)
			{
				memset(m_pCtlBlock, 0, sizeof(CBLOCK));
				m_pCtlBlock->dwTotalInstances = 0;
				m_pCtlBlock->dwCurrentlyMapped = 0;
			}
		}
		else
		{
			LogError(GetLastError(), MEM_MAP_VIEW, szMemoryName);
			CloseHandle(m_hCBlock);
			return(FALSE);
		}
	}       
	else
	{
		LogError(GetLastError(), MEM_CREATE_MMFCB, szMemoryName);
		return(FALSE);
	}

	return(TRUE);
}

//
// @mfunc <c StartRemapThread> Creates an event and a thread that are
//                             used to clear the memory if another instance
//                             of this object expands the memory
//
// @parm        IN const TCHAR * | szName | Name used to derive the event name
//
// @rvalue TRUE | If successful, otherwise it returns FALSE
//
BOOL CGmmf::StartRemapThread(IN const TCHAR *szName)
{
	DWORD dwThreadId;

	TCHAR szEventName[MAX_PATH];

	sprintf(szEventName, "%s_EV", szName);

	m_hRemapEvent = CreateEvent(&m_SecAttr,TRUE,FALSE,szEventName);
	if (NULL != m_hRemapEvent)
	{
		m_hShutdownEvent = CreateEvent(&m_SecAttr,FALSE,FALSE,NULL);
		if (NULL != m_hShutdownEvent)
		{
			m_hRemapThread = CreateThread(&m_SecAttr,
										  0,
										  (LPTHREAD_START_ROUTINE)RemapHandler, 
										  (LPVOID)this, 
										  0, 
										  &dwThreadId); 
			if (NULL == m_hRemapThread)
			{   
				LogError(GetLastError(), MEM_CREATE_REMAPTHREAD, szName);
				return(FALSE);
			}
		}
	}
	else
	{
		LogError(GetLastError(), MEM_CREATE_REMAPEVENT, szName);
		return(FALSE);
	}

	return(TRUE);
}

//
// @mfunc <c RemapHandler> Thread function that is responsible for
//                         clearing the memory if another instance attempts
//                         to expand it. This is necessary because the
//                         other instance will attempt to create a new
//                         memory mapped file with the same name as the 
//                         existing one.
//
// @parm        IN LPVOID | pObj | Pointer to the "this" object
//
// @rvalue None |
//
VOID CGmmf::RemapHandler(IN LPVOID pObj)
{
#define REMAP_EVENT         0
#define SHUTDOWN_EVENT      1

#define NUMBER_OF_EVENTS    2

	CGmmf *pObject = (CGmmf *)pObj;

	DWORD dwStatus;

	HANDLE hWaitList[NUMBER_OF_EVENTS];
	
	
	hWaitList[REMAP_EVENT]      = pObject->m_hRemapEvent;
	hWaitList[SHUTDOWN_EVENT]   = pObject->m_hShutdownEvent;

	while (!pObject->m_bShutdown)
	{
		dwStatus = WaitForMultipleObjects(NUMBER_OF_EVENTS,
										  (HANDLE *)hWaitList,
										  FALSE,
										  INFINITE);
		switch(dwStatus)
		{
		case WAIT_OBJECT_0 + REMAP_EVENT:
			if (pObject->m_bItsMe)
			{
				pObject->m_bItsMe = FALSE;
			}
			else
			{
				if ((pObject->m_pCtlBlock->dwCurrentlyMapped > 0) &&
					(!pObject->m_bShutdown))
				{
					pObject->Clear();
				}
			}
			break;
		case WAIT_OBJECT_0 + SHUTDOWN_EVENT:
			break;
		case WAIT_ABANDONED:
		case WAIT_TIMEOUT:
			break;
		}
	}
}

//
// @mfunc <c LogError>      Wrapper function that simply makes it a little
//                          easier to call WriteEventLog(). Since most of
//                          the calls use the same parameters, this makes
//                          the rest of the code much easier to read
//
// @parm    IN DWORD | dwWin32Code | Last Win32 error returned from GetLastError()
//
// @parm    IN LONG | lErrorCode | Elwood error code defined in ItkErr.h
//
// @parm    IN TCHAR [] | szText | Insertion string 
//
// @rvalue None |
//
VOID CGmmf::LogError(IN DWORD dwWin32Code, IN LONG lErrorCode, IN const TCHAR *szText)
{
	TCHAR chWin32Error[256];

	m_pLog->GetErrorText(dwWin32Code, (TCHAR *)&chWin32Error[0]);
	m_pLog->WriteEventLog(lErrorCode,
						  EVENTLOG_ERROR_TYPE,
						  0,
						  NULL,
						  szText,
						  chWin32Error,
						  NULL);
	return;
}

⌨️ 快捷键说明

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