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

📄 memmap.cpp

📁 memory map file class for C++ builder
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	*lpOffset	= lpCurPos;
}

BOOL CMemMap::DeleteID(UINT uId)
{
	/********************************************************
	* Remove the string
	* move following data to fill the void
	********************************************************/

	ASSERT ( m_pMappedViews );

	CheckForNewPages();

	// Validate the ID
	if ( uId == 0xFFFFFFFF || uId == 0xFFFFFF00 )
		return FALSE;

	LPBYTE lpBytePos	= 0; // a navigation pointer
	LPBYTE lpDebugView	= 0; // enable the watch view in debug
	UINT   uPage = 0;

	// Check if the id exists
	if ( FindID(uId,&uPage,&lpBytePos) == FALSE )
		return FALSE;

	if (uId == 100)
		int i=0;

	lpDebugView = (LPBYTE)m_pMappedViews[uPage];

	// Set the pointers to track the source and dest
	UINT   uSrcPage  = uPage;
	LPBYTE lpDestPos = lpBytePos;
	UINT   uSize     = 0;

	// Calc full size of the removed block
	uSize = GetLength(uPage,lpBytePos);
	uSize += 4/*id*/ + 4/*strlen*/;

	// move pointer to end
	NextID(&uPage,&lpBytePos);

	// Calc page spans
	UINT uRemaining = ((UINT)m_pMappedViews[uPage] + MMF_PAGESIZE);
	UINT uSpanned	=  uPage - uSrcPage;

	// setup before entering loop
	if ( uSpanned ) {
		// size from start (bytes to fill)
		uRemaining = ((UINT)m_pMappedViews[uSrcPage] + MMF_PAGESIZE);
		uRemaining -= (UINT)lpDestPos; // 8

		// fill remainder of this page
		memset(lpDestPos,0xFF,uRemaining);				// DEBUG last 8 bytes
		memmove(lpDestPos,lpBytePos,uRemaining); // 

		// set pointer to next block
		lpBytePos += uRemaining;
		lpDestPos = (LPBYTE)m_pMappedViews[uPage];

		// set the data size
		uRemaining = ((UINT)m_pMappedViews[uPage] + MMF_PAGESIZE);
		uRemaining -= (UINT)lpBytePos; // 8
	}
	else {
		// size from end (bytes to move)
		uRemaining -= (UINT)lpBytePos;

		// fill void on this page
		memmove(lpDestPos,lpBytePos,uRemaining);

		// set pointer to next block
		lpDestPos += uRemaining;

		if ( uPage < m_uPageCount-1 ) {
			// Account for flags
			if ( uPage == 0 )
				uRemaining += 4;

			// goto start of next page
			uPage += 1;
			lpBytePos = (LPBYTE)m_pMappedViews[uPage];

			// fill remainder 0f this page
			memmove(lpDestPos,lpBytePos,uSize);

			// set pointers to next block
			lpBytePos += uSize;
			lpDestPos = (LPBYTE)m_pMappedViews[uPage];
		}
		else {
			// no more pages, set remainder unallocated
			memset(lpDestPos,0xFF,uSize);

			// double null terminate
			*lpDestPos = 0;

			return TRUE;
		}
	}

	// current page now starts with a void space
	// uSize	  == size of the void
	// uRemaining == size of the data
	// lpDestPos  == start of void
	// lpBytePos  == start of data

	// loop through remaining pages
	while ( 1 ) {
		// enable the watch view
		lpDebugView = lpDestPos;

		// move data into void
		memmove(lpDestPos,lpBytePos,uRemaining);

		// reset pointers
		if ( uPage < m_uPageCount-1 ) {
			uPage += 1;
			lpBytePos = (LPBYTE)m_pMappedViews[uPage];
			lpDestPos += uRemaining;
		}
		else {
			// no more pages
			break;
		}

		// move from next page into void
		memmove(lpDestPos,lpBytePos,uSize);

		// reset the pointers
		lpBytePos += uSize;
		lpDestPos = (LPBYTE)m_pMappedViews[uPage];
	}

	// unallocate the remaining void
	memset(lpBytePos,0xFF,uSize);
	*lpBytePos = 0;

	return TRUE;
}

UINT CMemMap::GetID(UINT uPage, LPBYTE lpOffset)
{
	/***********************************************************
	* Get the id but do not increase the pointers
	* lpOffset should be pointing to the ID location
	***********************************************************/

	UINT uId = 0;

	Read(&uPage,&lpOffset,4,&uId);

	return uId;
}

UINT CMemMap::GetLength(UINT uPage, LPBYTE lpOffset)
{
	/***********************************************************
	* Get the strlen but do not increase the pointers
	* lpOffset should be pointing to the ID location
	***********************************************************/

	UINT uSize = 0;

	Read(&uPage,&lpOffset,4,NULL);
	Read(&uPage,&lpOffset,4,&uSize);

	return uSize;
}

UINT64 CMemMap::UsedSize()
{
	/***********************************************************
	* Return the actual used bytes
	***********************************************************/

	ASSERT ( m_pMappedViews );

	CheckForNewPages();

	LPBYTE lpBytePos	= (LPBYTE)m_pMappedViews[0]; // a navigation pointer
	UINT   uPage = 0;

	// First byte is reserved for flags
	lpBytePos += 4;

	// seek to the end of the data
	while (	1 ) {

		// read 4 bytes into an int
		unsigned int i = GetID(uPage,lpBytePos);
		if ( i == 0xFFFFFFFF || i == 0xFFFFFF00 )
			// unused memory
			break;

		NextID(&uPage,&lpBytePos);
	}

	UINT uUsed = (UINT)m_pMappedViews[uPage] + (UINT)lpBytePos;
	uUsed += (uPage * MMF_PAGESIZE);
	return uUsed;
}

UINT CMemMap::Count()
{
	/***********************************************************
	* Return the count of items being stored
	***********************************************************/

	ASSERT ( m_pMappedViews );

	CheckForNewPages();

	LPBYTE	lpBytePos	= (LPBYTE)m_pMappedViews[0]; // a navigation pointer
	UINT	uPage		= 0;
	UINT	uiCount		= 0;

	// First byte is reserved for flags
	lpBytePos += 4;

	// Count all the strings
	while (	1 ) {

		// read 4 bytes into an int
		unsigned int i = GetID(uPage,lpBytePos);
		if ( i == 0xFFFFFFFF || i == 0xFFFFFF00 )
			// unused memory
			break;

		NextID(&uPage,&lpBytePos);

		uiCount++;
	}

	return uiCount;
}



//////////////////////////////////////////////////////////////////////
// Single Writer / Multi Reader  Written by: Alex Farber   alexm@cmt.co.il
//////////////////////////////////////////////////////////////////////

BOOL CMemMap::InitProtect(LPCTSTR szName,DWORD dwWait)
{
	/************************************************************
	* Create the unique names
	************************************************************/

	ASSERT ( szName );

	int iLen = _tcslen(szName);
	iLen += 6 * sizeof(TCHAR);

	try
	{
		m_sMutexName		= new TCHAR [iLen];
		m_sSemReadersName	= new TCHAR [iLen];
		m_sSemWritersName	= new TCHAR [iLen];
		m_sMemFileName		= new TCHAR [iLen];

		_stprintf(m_sMutexName,		 _T("%s_Mutex"), szName);
		_stprintf(m_sSemReadersName, _T("%s_SemRd"), szName);
		_stprintf(m_sSemWritersName, _T("%s_SemWr"), szName);
		_stprintf(m_sMemFileName,	 _T("%s_MemFl"), szName);
	}
	catch (...)
	{
		TRACE ( _T("Failed to InitProtect") );
	}

	// keep time interval
	m_dwMilliseconds = dwWait;

	return InitSyncObjects();
}

BOOL CMemMap::EndProtect()
{
	/************************************************************
	* Clean up
	************************************************************/

	delete [] m_sMutexName;
	delete [] m_sSemReadersName;
	delete [] m_sSemWritersName;
	delete [] m_sMemFileName;

    if ( m_hFileMapping )
        if ( m_pViewOfFile )
            if ( UnmapViewOfFile(m_pViewOfFile) )
				CloseHandle(m_hFileMapping);

    if ( m_hMutex )
        CloseHandle(m_hMutex);

    if ( m_hsemWriters )
        CloseHandle(m_hsemWriters);

    if ( m_hsemReaders )
        CloseHandle(m_hsemReaders);

	return TRUE;
}

BOOL CMemMap::InitSyncObjects()
{
	/************************************************************
	* Init the mutex, semaphores and mapped file
	************************************************************/

	// create semaphore for waiting readers
	m_hsemReaders = CreateSemaphore(NULL,0,MAXLONG,m_sSemReadersName);
	if ( ! m_hsemReaders ) {
		TRACE ( _T("Failed to CreateSemaphore") );
		return FALSE;
	}

	// create semaphore for waiting writers
	m_hsemWriters = CreateSemaphore(NULL,0,MAXLONG,m_sSemWritersName );
	if ( ! m_hsemWriters ) {
		TRACE ( _T("Failed to CreateSemaphore") );
		return FALSE;
	}

	// crate mutex protecting access to other members
	m_hMutex = CreateMutex(NULL,FALSE,m_sMutexName );
	if ( ! m_hMutex ) {
		TRACE ( _T("Failed to CreateMutex") );
		return FALSE;
	}

	// create file mapping to keep counters
	m_hFileMapping = CreateFileMapping(	INVALID_HANDLE_VALUE,
										NULL,
										PAGE_READWRITE,
										0,
										sizeof(RW_COUNTERS),
										m_sMemFileName);
	if ( ! m_hFileMapping ) {
		TRACE ( _T("Failed to CreateFileMapping for mutex") );
		return FALSE;
	}

	m_pViewOfFile = MapViewOfFile(m_hFileMapping,FILE_MAP_ALL_ACCESS,0,0,0);
	if ( ! m_pViewOfFile ) {
		TRACE ( _T("Failed to MapViewOfFile for mutex") );
		return FALSE;
	}

	// get pointers to counters
	RW_COUNTERS* pCounters = (RW_COUNTERS*) m_pViewOfFile;

	m_pnActive			= &pCounters->m_nActive;
	m_pnWaitingReaders	= &pCounters->m_nWaitingReaders;
	m_pnWaitingWriters	= &pCounters->m_nWaitingWriters;

	return TRUE;
}

BOOL CMemMap::WaitToRead() 
{
	/************************************************************
	* Attempt to read the shared file
	************************************************************/

	// Ensure exclusive access to the member variables
	if ( WaitForSingleObject(m_hMutex, m_dwMilliseconds) != WAIT_OBJECT_0 )
		return FALSE;

	// Check for writers waiting or writing
	bool fResourceWritePending = (*m_pnWaitingWriters || (*m_pnActive < 0));

	// Check if can read
	if ( fResourceWritePending ) 
		(*m_pnWaitingReaders)++;
	else 
		(*m_pnActive)++;

	// Allow other clients to attempt reading/writing
	ReleaseMutex(m_hMutex);

	// Wait for write to complete
	if ( fResourceWritePending ) {
		// This thread must wait
		if ( WaitForSingleObject(m_hsemReaders,m_dwMilliseconds) != WAIT_OBJECT_0 ) {
			// try to make rollback
			if ( WaitForSingleObject(m_hMutex,m_dwMilliseconds) == WAIT_OBJECT_0 ) {
				(*m_pnWaitingReaders)--;    // rollback

				ReleaseMutex(m_hMutex);
			}
			return FALSE;
		}
	}

	return TRUE;
}

BOOL CMemMap::WaitToWrite() 
{
	/************************************************************
	* Attempt to write to the shared file
	************************************************************/

	// Wait for access
	if ( WaitForSingleObject(m_hMutex, m_dwMilliseconds) != WAIT_OBJECT_0 )
		return FALSE;

	// Check other threads
	BOOL fResourceOwned = (*m_pnActive != 0);

	// Check if can write
	if ( fResourceOwned )
		(*m_pnWaitingWriters)++;
	else
		*m_pnActive = -1;

	// Allow other clients to attempt reading/writing
	ReleaseMutex(m_hMutex);

	// Wait
	if ( fResourceOwned ) {
		// This thread must wait
		if ( WaitForSingleObject(m_hsemWriters,m_dwMilliseconds) != WAIT_OBJECT_0 ) {
			// try to make rollback
			if ( WaitForSingleObject(m_hMutex,m_dwMilliseconds) == WAIT_OBJECT_0 ) {
				(*m_pnWaitingWriters)--;        // rollback

				ReleaseMutex(m_hMutex);
			}

			return FALSE;
		}
	}

	return TRUE;
}

BOOL CMemMap::Done() 
{
	/************************************************************
	* Release the shared file
	************************************************************/

	// Get the mutex
	if ( WaitForSingleObject(m_hMutex, m_dwMilliseconds) != WAIT_OBJECT_0 )
		return FALSE;

	if (*m_pnActive > 0)
		// Readers have control so a reader must be done
		(*m_pnActive)--;
	else
		// Writers have control so a writer must be done
		(*m_pnActive)++;

	HANDLE hsem   = NULL;  // Assume no threads are waiting
	LONG   lCount = 1;     // Assume only 1 waiter wakes; always true for writers

	if ( *m_pnActive == 0 ) 
	{
		if ( *m_pnWaitingWriters > 0 ) 
		{
			// Writers are waiting and they take priority over readers
			*m_pnActive = -1;			// A writer will get access
			(*m_pnWaitingWriters)--;	// One less writer will be waiting
			hsem = m_hsemWriters;		// Writers wait on this semaphore
			// NOTE: The semaphore will release only 1 writer thread
		} 
		else if ( *m_pnWaitingReaders > 0 ) 
		{
			// Readers are waiting and no writers are waiting
			*m_pnActive = *m_pnWaitingReaders;   // All readers will get access
			*m_pnWaitingReaders = 0;             // No readers will be waiting
			hsem = m_hsemReaders;                // Readers wait on this semaphore
			lCount = *m_pnActive;                // Semaphore releases all readers
		} 
		else 
		{
		// There are no threads waiting at all; no semaphore gets released
		}
	}

	// Allow other threads to attempt reading/writing
	ReleaseMutex(m_hMutex);

	if (hsem != NULL) 
	{
		// Some threads are to be released
		ReleaseSemaphore(hsem, lCount, NULL);
	}

	return TRUE;
}

⌨️ 快捷键说明

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