📄 sh_smem.cpp
字号:
// SH_SMem.cpp: implementation of the SH_SMem class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "SH_SMem.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#include <process.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
SH_SMem::SH_SMem()
{
m_nOtherInstanceID = 0;
m_nInstanceID = 0;
m_hClosed = CreateEvent(NULL, TRUE, TRUE, NULL);
m_hDataWrit[0] = NULL;
m_hDataWrit[1] = NULL;
m_hDataRead[0] = NULL;
m_hDataRead[1] = NULL;
m_hDataInQueue = NULL;
m_hQueueMutex = NULL;
}
SH_SMem::~SH_SMem()
{
Close();
CloseHandle(m_hClosed);
}
BOOL SH_SMem::Open( const char* sName, int nDataSize, int nTimeOut/*= INFINITE*/)
{
m_pFirst = NULL;
if (WaitForSingleObject(m_hClosed, 0) == WAIT_OBJECT_0)
{
if (strlen(sName) != 0 && strlen(sName) < MAX_PATH - 10)
{
if (nDataSize > 0)
{
char sMutex0 [MAX_PATH];
char sMutex1 [MAX_PATH];
strcpy(sMutex0 , sName);
strcpy(sMutex1 , sName);
strcat(sMutex0 , "Mutex0");
strcat(sMutex1 , "Mutex1");
m_hSMemMutex[0] = CreateMutex(NULL, FALSE, sMutex0);
m_hSMemMutex[1] = CreateMutex(NULL, FALSE, sMutex1);
if (m_hSMemMutex[0] && m_hSMemMutex[1])
{
HANDLE hWait[2] = {m_hSMemMutex[0], m_hSMemMutex[1]};
DWORD dwResult = WaitForMultipleObjects(2, hWait, FALSE, 0);
if (dwResult == WAIT_OBJECT_0 || dwResult == (WAIT_OBJECT_0 + 1))
{
if ((m_nInstanceID = dwResult - WAIT_OBJECT_0) == 0)
m_nOtherInstanceID = 1;
else
m_nOtherInstanceID = 0;
char sName0 [MAX_PATH];
char sName1 [MAX_PATH];
strcpy(sName0 , sName);
strcpy(sName1 , sName);
strcat(sName0 , "0");
strcat(sName1 , "1");
if ((m_hSMem[0] = CreateFileMapping( (HANDLE)0xFFFFFFFF,
NULL,
PAGE_READWRITE,
0,
sizeof(int) + nDataSize,
sName0)) != NULL
&&
(m_hSMem[1] = CreateFileMapping( (HANDLE)0xFFFFFFFF,
NULL,
PAGE_READWRITE,
0,
sizeof(int) + nDataSize,
sName1)) != NULL)
{
bool bFileMappingAlreadyExists = (GetLastError() == ERROR_ALREADY_EXISTS);
m_pSize = (int*)MapViewOfFile( m_hSMem[0],
FILE_MAP_ALL_ACCESS,
0,
0,
sizeof(int));
if (m_pSize)
{
bool bSharedMemorySizeOk = false;
if (bFileMappingAlreadyExists)
{
if (*m_pSize == nDataSize)
bSharedMemorySizeOk = true;
}
else
{
*m_pSize = nDataSize;
bSharedMemorySizeOk = true;
}
if (bSharedMemorySizeOk)
{
m_pSMem[0] = (BYTE*)MapViewOfFile( m_hSMem[0],
FILE_MAP_ALL_ACCESS,
0,
0,
nDataSize);
m_pSMem[1] = (BYTE*)MapViewOfFile( m_hSMem[1],
FILE_MAP_ALL_ACCESS,
0,
0,
nDataSize);
if (m_pSMem[0] && m_pSMem[1])
{
m_pSMem[0] += sizeof(int);
m_pSMem[1] += sizeof(int);
char sDataWrit0 [MAX_PATH];
char sDataWrit1 [MAX_PATH];
char sDataRead0 [MAX_PATH];
char sDataRead1 [MAX_PATH];
strcpy(sDataWrit0 , sName);
strcpy(sDataWrit1 , sName);
strcpy(sDataRead0 , sName);
strcpy(sDataRead1 , sName);
strcat(sDataWrit0 , "DataWrit0");
strcat(sDataWrit1 , "DataWrit1");
strcat(sDataRead0 , "DataRead0");
strcat(sDataRead1 , "DataRead1");
m_hDataWrit[0] = CreateEvent(NULL, FALSE, FALSE, sDataWrit0);
m_hDataWrit[1] = CreateEvent(NULL, FALSE, FALSE, sDataWrit1);
m_hDataRead[0] = CreateEvent(NULL, FALSE, TRUE, sDataRead0);
m_hDataRead[1] = CreateEvent(NULL, FALSE, TRUE, sDataRead1);
if (m_hDataWrit[0] && m_hDataWrit[1] && m_hDataRead[0] && m_hDataRead[1])
{
m_hSecondInstanceAvailable = CreateEvent(NULL, FALSE, FALSE, sName);
if (m_hSecondInstanceAvailable)
{
if (m_nInstanceID == 0)
{
if (WaitForSingleObject(m_hSecondInstanceAvailable, nTimeOut) == WAIT_OBJECT_0)
{
CloseHandle(m_hSecondInstanceAvailable);
ResetEvent(m_hClosed);
m_hQueueMutex = CreateMutex(NULL, FALSE, NULL);
m_hDataInQueue = CreateEvent(NULL, FALSE, FALSE, NULL);
m_hQueueThread = (HANDLE)_beginthread(QueueThread, 0, this);
return true;
}
}
else if (m_nInstanceID == 1)
{
SetEvent(m_hSecondInstanceAvailable);
if (WaitForSingleObject(m_hSecondInstanceAvailable, 0) == WAIT_TIMEOUT)
{
CloseHandle(m_hSecondInstanceAvailable);
ResetEvent(m_hClosed);
m_hQueueMutex = CreateMutex(NULL, FALSE, NULL);
m_hDataInQueue = CreateEvent(NULL, FALSE, FALSE, NULL);
m_hQueueThread = (HANDLE)_beginthread(QueueThread, 0, this);
return true;
}
}
CloseHandle(m_hSecondInstanceAvailable);
}
}
UnmapViewOfFile(m_pSMem[0]);
UnmapViewOfFile(m_pSMem[1]);
}
}
UnmapViewOfFile(m_pSize);
}
CloseHandle(m_hSMem[0]);
CloseHandle(m_hSMem[1]);
}
}
CloseHandle(m_hSMemMutex[0]);
CloseHandle(m_hSMemMutex[1]);
}
}
}
}
return FALSE;
}
void SH_SMem::Close()
{
if (WaitForSingleObject(m_hClosed, 0) == WAIT_TIMEOUT)
{
SetEvent(m_hClosed);
ReleaseMutex(m_hSMemMutex[m_nInstanceID]);
EmptyWriteQueue();
WaitForSingleObject(m_hQueueThread, INFINITE);
CloseHandle(m_hQueueMutex);
CloseHandle(m_hDataInQueue);
m_hQueueMutex = NULL;
m_hDataInQueue = NULL;
CloseHandle(m_hDataWrit[0]);
CloseHandle(m_hDataWrit[1]);
CloseHandle(m_hDataRead[0]);
CloseHandle(m_hDataRead[1]);
m_hDataWrit[0] = NULL;
m_hDataWrit[1] = NULL;
m_hDataRead[0] = NULL;
m_hDataRead[1] = NULL;
UnmapViewOfFile(m_pSize);
m_pSMem[0] -= sizeof(int);
m_pSMem[1] -= sizeof(int);
UnmapViewOfFile(m_pSMem[0]);
UnmapViewOfFile(m_pSMem[1]);
CloseHandle(m_hSMem[0]);
CloseHandle(m_hSMem[1]);
CloseHandle(m_hSMemMutex[0]);
CloseHandle(m_hSMemMutex[1]);
}
}
int SH_SMem::Write(void *pData, int nDataSize, DWORD dwTimeOut)
{
HANDLE hWait[3];
hWait[0] = m_hClosed;
hWait[1] = m_hSMemMutex[m_nOtherInstanceID];
hWait[2] = m_hDataRead[m_nOtherInstanceID];
DWORD dwWaitResult = WaitForMultipleObjects(3, hWait, FALSE, dwTimeOut);
switch(dwWaitResult)
{
case WAIT_OBJECT_0 + 2:
if (nDataSize > *m_pSize)
return SH_SMEM_ERROR_DATASIZE;
memcpy(m_pSMem[m_nOtherInstanceID], pData, nDataSize);
SetEvent(m_hDataWrit[m_nOtherInstanceID]);
return SH_SMEM_SUCCESS;
case WAIT_OBJECT_0:
return SH_SMEM_ERROR_CLOSED;
case WAIT_OBJECT_0 + 1:
ReleaseMutex(m_hSMemMutex[m_nOtherInstanceID]);
return SH_SMEM_ERROR_OTHERPARTY;
case WAIT_ABANDONED_0 + 1:
ReleaseMutex(m_hSMemMutex[m_nOtherInstanceID]);
return SH_SMEM_ERROR_OTHERPARTY;
case WAIT_FAILED:
if (!m_hDataRead[m_nOtherInstanceID])
return SH_SMEM_ERROR_CLOSED;
return SH_SMEM_ERROR_UNKNOWN;
case WAIT_TIMEOUT:
return SH_SMEM_ERROR_TIMEOUT;
}
return SH_SMEM_ERROR_UNKNOWN;
}
int SH_SMem::WriteToQueue(void *pData, int nDataSize)
{
HANDLE hWait[3];
hWait[0] = m_hClosed;
hWait[1] = m_hSMemMutex[m_nOtherInstanceID];
hWait[2] = m_hQueueMutex;
switch (WaitForMultipleObjects(3, hWait, FALSE, INFINITE))
{
case WAIT_OBJECT_0:
return SH_SMEM_ERROR_CLOSED;
case WAIT_OBJECT_0 + 2:
{
if (nDataSize > *m_pSize)
return SH_SMEM_ERROR_DATASIZE;
SH_WriteQue *pNew = new SH_WriteQue(*m_pSize);
memcpy(pNew->pData, pData, *m_pSize);
if (!m_pFirst)
m_pFirst = pNew;
else
{
SH_WriteQue *pCurrent = m_pFirst;
while (pCurrent->pNext)
pCurrent = pCurrent->pNext;
pCurrent->pNext = pNew;
}
SetEvent(m_hDataInQueue);
ReleaseMutex(m_hQueueMutex);
}
return SH_SMEM_SUCCESS;
case WAIT_OBJECT_0 + 1:
ReleaseMutex(m_hSMemMutex[m_nOtherInstanceID]);
return SH_SMEM_ERROR_OTHERPARTY;
case WAIT_ABANDONED_0 + 1:
ReleaseMutex(m_hSMemMutex[m_nOtherInstanceID]);
return SH_SMEM_ERROR_OTHERPARTY;
case WAIT_FAILED:
if (!m_hQueueMutex)
return SH_SMEM_ERROR_CLOSED;
return SH_SMEM_ERROR_UNKNOWN;
}
return SH_SMEM_ERROR_UNKNOWN;
}
int SH_SMem::Read(void *pData, int nDataSize, DWORD dwTimeOut)
{
HANDLE hWait[3];
hWait[0] = m_hDataWrit[m_nInstanceID];
hWait[1] = m_hClosed;
hWait[2] = m_hSMemMutex[m_nOtherInstanceID];
DWORD dwWaitResult = WaitForMultipleObjects(3, hWait, FALSE, dwTimeOut);
switch(dwWaitResult)
{
case WAIT_OBJECT_0:
if (nDataSize > *m_pSize)
return SH_SMEM_ERROR_DATASIZE;
memcpy(pData, m_pSMem[m_nInstanceID], nDataSize);
SetEvent(m_hDataRead[m_nInstanceID]);
return SH_SMEM_SUCCESS;
case WAIT_OBJECT_0 + 1:
return SH_SMEM_ERROR_CLOSED;
case WAIT_OBJECT_0 + 2:
ReleaseMutex(m_hSMemMutex[m_nOtherInstanceID]);
return SH_SMEM_ERROR_OTHERPARTY;
case WAIT_ABANDONED_0 + 2:
ReleaseMutex(m_hSMemMutex[m_nOtherInstanceID]);
return SH_SMEM_ERROR_OTHERPARTY;
case WAIT_FAILED:
if (!m_hDataWrit[m_nInstanceID])
return SH_SMEM_ERROR_CLOSED;
return SH_SMEM_ERROR_UNKNOWN;
case WAIT_TIMEOUT:
return SH_SMEM_ERROR_TIMEOUT;
}
return SH_SMEM_ERROR_UNKNOWN;
}
void SH_SMem::EmptyWriteQueue()
{
while (m_pFirst && WaitForSingleObject(m_hQueueMutex, INFINITE) == WAIT_OBJECT_0)
{
if (m_pFirst)
{
SH_WriteQue *pQueue = m_pFirst;
m_pFirst = pQueue->pNext;
delete pQueue;
}
ReleaseMutex(m_hQueueMutex);
}
}
void SH_SMem::QueueThread(void *pArg)
{
SH_SMem *pThis = (SH_SMem*)pArg;
HANDLE hWait[2] = {pThis->m_hClosed, pThis->m_hDataInQueue};
bool bQuit = false;
while (!bQuit)
{
switch (WaitForMultipleObjects(2, hWait, FALSE, INFINITE))
{
case WAIT_OBJECT_0 + 1:
{
BYTE *pData = NULL;
while (pThis->m_pFirst && WaitForSingleObject(pThis->m_hQueueMutex, INFINITE) == WAIT_OBJECT_0)
{
if (pThis->m_pFirst)
{
// First get the first element of the queue
SH_WriteQue *pQueue = pThis->m_pFirst;
pData = new BYTE[*pThis->m_pSize];
memcpy(pData, pThis->m_pFirst->pData, *pThis->m_pSize);
pThis->m_pFirst = pQueue->pNext;
delete pQueue;
ReleaseMutex(pThis->m_hQueueMutex);
pThis->Write(pData, *pThis->m_pSize, INFINITE);
delete [] pData;
}
else
ReleaseMutex(pThis->m_hQueueMutex);
}
}
break;
case WAIT_OBJECT_0:
bQuit = true;
break;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -