Knowledge Base Nr: 00115 DataExchangeClass.cpp - http://www.swe-kaiser.de

Downloads:

Win32: Klasse zum Datenaustausch zw. Prozessen mittels Memory Mapped File und Mutex

  
////////////////////////////////////////////////////
///beispielanwendung
////////////////////////////////////////////////////

#include "DataExchange.h"

CMyDataExchange g_de("lulli");

void CMmfmutextestDlg::OnButton1() //lesen
{
char szData[100];

int nRes = g_de.Read(szData, sizeof(szData));
}

void CMmfmutextestDlg::OnButton2() //schreiben
{
char szData[100];
strcpy(szData, "the quick brown fox jumps over the laszy dog...");

int nRes = g_de.Write(szData, sizeof(szData));
}

////////////////////////////////////////////////////
///definition DataExchange.h
////////////////////////////////////////////////////

class CMyDataExchange
{
public:
CMyDataExchange(const char* lpszName);
virtual ~CMyDataExchange();

int Read(void* pData, int nSize);
int Write(void* pData, int nSize);

protected:
int InitMMFData();
int CleanupMMFData();
int ReadWriteMMFData(void* pData, int nSize, bool bWriteOrRead);

private:
HANDLE m_hFileMap;
CMyMutex* m_pMutex;
char m_szMMFName[100];
char m_szMutexName[100];
};

class CMyMutex
{
public:
CMyMutex(const char* lpszName);
virtual ~CMyMutex();

bool Lock(int nWaitmSec); //true = ok; false = error
bool Unlock();

private:
HANDLE m_hMutex;
bool m_bLocked;
};

////////////////////////////////////////////////////
///implementierung DataExchange.cpp
////////////////////////////////////////////////////

CMyDataExchange::CMyDataExchange(const char* lpszName)
{
m_hFileMap = NULL;
m_pMutex = NULL;

sprintf(m_szMMFName, "%sMMF", lpszName);
sprintf(m_szMutexName, "%sMutex", lpszName);
}

CMyDataExchange::~CMyDataExchange()
{
CleanupMMFData();
}

int CMyDataExchange::Read(void* pData, int nSize)
{
return ReadWriteMMFData(pData, nSize, false);
}

int CMyDataExchange::Write(void* pData, int nSize)
{
return ReadWriteMMFData(pData, nSize, true);
}

int CMyDataExchange::InitMMFData()
{
if (m_hFileMap == NULL) //noch nicht offen
{
m_pMutex = new CMyMutex(m_szMutexName);
}

if (m_pMutex == NULL)
return -1;

m_hFileMap = CreateFileMapping((HANDLE)0xffffffff,
NULL,
PAGE_READWRITE,
0,
sizeof(WORD),
m_szMMFName);

if (m_hFileMap == NULL)
return ::GetLastError();

if (GetLastError() == ERROR_ALREADY_EXISTS)
{
//file existiert bereits -> es kann z.b. gelesen werden
}

return 0;
}

int CMyDataExchange::CleanupMMFData()
{
if (m_hFileMap != NULL) //nur wenn offen
{
BOOL bSucc = ::CloseHandle(m_hFileMap);
if (!bSucc)
return ::GetLastError();
}

return 0;
}

int CMyDataExchange::ReadWriteMMFData(void* pData, int nSize, bool bWriteOrRead)
{
InitMMFData(); //wenn schon initialisiert kehrt die funktion sofort zurück

if (m_hFileMap == NULL) //memory mapped file konnte nicht angelegt/gemappt werden
return -4711;

if (m_pMutex == NULL) //mutex konnte nicht angelegt/gemappt werden
return -4712;

if (!m_pMutex->Lock(5000)) //max. 5 sekunden warten
return -4713;

LPVOID lpView = MapViewOfFile(m_hFileMap,
FILE_MAP_READ | FILE_MAP_WRITE,
0,
0,
0);

if (lpView == NULL)
{
CleanupMMFData();
return ::GetLastError();
}

WORD* lpShared = (WORD*) lpView;

if (bWriteOrRead) //schreiben
memcpy(lpShared, pData, nSize);
else //lesen
memcpy(pData, lpShared, nSize);

if (!m_pMutex->Unlock())
return -4714;

BOOL bSucc = UnmapViewOfFile(lpView);
if (!bSucc)
{
CleanupMMFData();
return ::GetLastError();
}

return 0;
}


//////////////////////////////////////////////////////////////////////
// CMyMutex
//////////////////////////////////////////////////////////////////////

CMyMutex::CMyMutex(const char* lpszName)
{
m_bLocked = false;

m_hMutex = ::CreateMutex(NULL, // no security attributes
FALSE, // initially not owned
lpszName); // name of mutex

if (m_hMutex == NULL)
{
::MessageBox(NULL, "CreateMutex failed!", "ERROR", MB_OK);
DWORD dw = ::GetLastError();
}
}

CMyMutex::~CMyMutex()
{
if (m_hMutex)
::CloseHandle(m_hMutex);
}

bool CMyMutex::Lock(int nWaitmSec)
{
if (!m_hMutex)
return false;

if (m_bLocked)
return true;

DWORD dwWaitResult = ::WaitForSingleObject(m_hMutex, nWaitmSec);

switch (dwWaitResult)
{
case WAIT_OBJECT_0:
m_bLocked = true;
return true;

case WAIT_TIMEOUT: // Cannot get mutex ownership due to time-out.
return false;

case WAIT_ABANDONED: // Got ownership of the abandoned mutex object.
return false;
}

return false; //never reached?!
}

bool CMyMutex::Unlock()
{
if (!m_hMutex)
return false;

if (!m_bLocked)
return true;

if (!::ReleaseMutex(m_hMutex))
{
return false;
}

m_bLocked = false;
return true;
}