W tej chwili moj kod wyglada mniej wiecej tak:
MMF::MMF(const string& szMMName):m_szMMName(szMMName),m_hMapFile(NULL)
{
m_pLock = new CIPCReadWriteLock(
sReadWriteLockName,
dwMaxWait);
}
MMF::~MMF(void)
{
CloseMapFile();
if(m_pLock)
delete m_pLock;
}
bool MMF::CreateMapFile()
{
CShareRestrictedSD ShareRestrictedSD;
if(NULL == m_hMapFile)
{
m_hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE,
ShareRestrictedSD.GetSA(),
PAGE_READWRITE,
0,
1000,
m_szMMName.c_str());
}
return NULL != m_hMapFile;
}
bool MMF::OpenMapFile()
{
if(NULL == m_hMapFile)
{
m_hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS,
TRUE,
m_szMMName.c_str());
}
return NULL != m_hMapFile;
}
void MMF::CloseMapFile()
{
if(m_hMapFile)
{
::CloseHandle(m_hMapFile);
m_hMapFile = NULL;
}
}
bool MMF::WriteData(const char* szData,int nLen)
{
LPVOID lpRet = MapViewOfFile(m_hMapFile,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);
if(lpRet && m_pLock->WaitToWrite())
{
memcpy((char*)lpRet,szData,nLen);
::UnmapViewOfFile(lpRet);
m_pLock->Done();
return true;
}
else
{
return false;
}
}
bool MMF::ReadData(string& szData)
{
LPVOID lpRet = MapViewOfFile(m_hMapFile,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);
if(lpRet && m_pLock->WaitToRead())
{
int nCopyLen = strlen((char*)lpRet);
char *pBuffer = new char[nCopyLen];
memset(pBuffer,0,nCopyLen);
memcpy(pBuffer,lpRet,nCopyLen);
szData = string(pBuffer,nCopyLen);
::UnmapViewOfFile(lpRet);
return true;
}
else
{
return false;
}
}
Uzyta klasa CIPCReadWriteLock, ktora ma niby zapewniac synchronizacje pochodzi stad: http://69.10.233.10/KB/threads/ipc_tute.aspx
Jak testuje: writer w petli tworzy dwa obiekty wspoldzielone i je usuwa po 500 ms. Reader co 500 ms probuje odczytac i raportuje czy mu sie udalo.
Rezultaty? Bez synchronizacji: Jezeli writer umiesci jakies dane w pamieci, to reader moze je caly czas odczytywac. Kilka readerow - takze. Nawet jezeli writer sprobuje usunac dane z pamieci, to i tak sa one dostepne dla readera. Dopiero jak zamkne readera i uruchomie jeszcze raz, dostepnych danych juz nie ma.
Uzywajac tej klasy do synchronizacji: reader moze odczytac kazda wartosc tylko raz, niezaleznie od wszystkiego.
Natomiast writer moze zapisywac i usuwac zasoby w nieskonczonosc, kilka writerow takze. Ale jezeli rownoczesnie uruchomie readera, to po jednym odczytaniu zasobu przez niego juz ani writer ani reader nie moga nic zrobic. Nawet po zakonczeniu readera uruchomiony writer nie moze nic zapisywac.
Wedlug mnie to pierwszy wariant jest prawidlowy. Reader nie usuwa zasobu, tylko czyta raz za razem to samo.
W praktyce bedzie to wygladalo tak, ze komunikacja bedzie tylko dwustronna. Czyli proces "nasluchuje", czy nie ma dla niego zadnych wiadomosci (obojetnie od kogo), a rozpoznawalby to po nazwie zasobu. Raczej nie przewiduje sytuacji, w ktorej kilka procesow zapisywaloby ten sam zasob roznymi wartosciami. Jezeli nawet cos takiego dzialoby sie rownoczesnie, to zapisywane by byly (lub tworzone) zasoby o roznych nazwach.