0x001 Programming/01. C | C++

[Example] 생산자 | 소비자

KimSangLab 2017. 12. 29. 15:17

#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;

}