#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <malloc.h>
#include <io.h>
#include <process.h>
#include <time.h>
#define DATA_SIZE 256
#ifdef _UNICODE
#define _tstrrchr wcsrchr
#else
#define _tstrrchr strrchr
#endif
#ifdef _UNICODE
#define _tstrstr wcsstr
#else
#define _tstrstr strstr
#endif
#ifdef _UNICODE
#define _memtchr wmemchr
#else
#define _memtchr memchr
#endif
typedef struct MSG_BLOCK_TAG
{
CRITICAL_SECTION mGuard;
DWORD fReady, fStop;
volatile DWORD nCons, mSequence;
DWORD nLost;
time_t mTimestamp;
DWORD mChecksum;
DWORD mData[DATA_SIZE];
} MSG_BLOCK;
MSG_BLOCK mBlock = {0,0,0,0,0};
unsigned int WINAPI Produce (void *);
unsigned int WINAPI Consume(void *);
void MessageFill (MSG_BLOCK *);
void MessageDisplay( MSG_BLOCK *);
DWORD _tmain( DWORD argc, LPTSTR argv[] )
{
DWORD status;
HANDLE hProduce, hConsume;
InitializeCriticalSection( &mBlock.mGuard );
hProduce = (HANDLE) _beginthreadex( NULL, 0, Produce, NULL, 0, NULL );
hConsume = (HANDLE) _beginthreadex( NULL, 0, Consume, NULL, 0, NULL );
status = WaitForSingleObject( hConsume, INFINITE );
status = WaitForSingleObject( hProduce, INFINITE );
DeleteCriticalSection ( &mBlock.mGuard );
_tprintf(_T("Producer and consumer thread have terminated \n"));
_tprintf(_T("Message produced : %d, Consumed : %d Lost : %d \n"), mBlock.mSequence, mBlock.nCons, mBlock.mSequence - mBlock.nCons );
return 0;
}
unsigned int WINAPI Produce (void * arg)
{
srand ( (unsigned int) time(NULL) );
while( !mBlock.fStop )
{
Sleep(rand() / 100 );
EnterCriticalSection( &mBlock.mGuard );
__try
{
if( !mBlock.fStop )
{
mBlock.fReady = 0;
MessageFill( &mBlock );
mBlock.fReady = 1;
InterlockedIncrement( &mBlock.mSequence );
}
}
__finally
{
LeaveCriticalSection ( &mBlock.mGuard );
}
}
return 0;
}
unsigned int WINAPI Consume( void * arg )
{
CHAR command, extra;
while( !mBlock.fStop )
{
_tprintf(_T("\n ** Enter 'c' for Consume; 's' to Stop : "));
_tscanf("%c%c", &command, &extra);
if( command == 's' )
{
mBlock.fStop = 1;
}
else if( command == 'c' )
{
EnterCriticalSection( &mBlock.mGuard );
__try
{
if( mBlock.fReady == 0)
{
_tprintf(_T("No New Message. Try Again later \n"));
}
else
{
MessageDisplay(&mBlock );
mBlock.nLost = mBlock.mSequence - mBlock.nCons + 1;
mBlock.fReady = 0;
InterlockedIncrement( &mBlock.nCons );
}
}
__finally
{
LeaveCriticalSection( &mBlock.mGuard );
}
}
else
{
_tprintf(_T("Illegal Command, Try Again \n"));
}
}
return 0;
}
void MessageFill( MSG_BLOCK * msgBlock)
{
DWORD i;
msgBlock->mChecksum = 0;
for( i = 0; i< DATA_SIZE; i++)
{
msgBlock->mData[i] = rand();
msgBlock->mChecksum ^= msgBlock->mData[i];
}
msgBlock->mTimestamp = time( NULL );
return;
}
void MessageDisplay( MSG_BLOCK * msgBlock )
{
DWORD i, tcheck = 0;
for( i = 0; i < DATA_SIZE; i++)
{
tcheck ^= msgBlock->mData[i];
}
_tprintf(_T("\n Message number %d generated at : %s \n"), msgBlock->mSequence, _tctime( &( msgBlock->mTimestamp )));
_tprintf(_T("First and last entries : %x %x \n"), msgBlock->mData[0], msgBlock->mData[DATA_SIZE - 1 ]);
if( tcheck == msgBlock->mChecksum )
{
_tprintf(_T("GOOD -> mChecksum was validated. \n"));
}
else
{
_tprintf(_T("BAD -> mCheckSum failed. message Corrupted \n"));
}
return;
}