Code:
#include <stdio.h>
#include <windows.h>
#include <process.h>
#ifndef _MT
#error "Must link with /MT(d)
#endif
volatile int g_nThreadsRunning = 0;
const char* g_lpszPath = NULL;
CRITICAL_SECTION g_CriticalSection;
#define RECORD_COUNT (1024 * 100)
#define RECORD_SIZE (1024)
#define PATH_SIZE (1024 + 1)
#define CONCURRENT_THREADS 3
// thread:
// open file a
// write to a
// close file a
// open a for reading
// open b for writing
// write a to b
// close a
// close b
// remove a
// rename b to a
// ( remove a to clean up )
unsigned int __stdcall ThreadFunction( void* pThreadnumber )
{
char szFileInput[ PATH_SIZE ];
char szFileOutput[ PATH_SIZE ];
char szBuffer[ RECORD_SIZE ];
int nBlock;
ZeroMemory( szBuffer, RECORD_SIZE );
// zero data to be written
sprintf( szFileInput, "%s\\%d.a", g_lpszPath, (int)pThreadnumber );
sprintf( szFileOutput, "%s\\%d.b", g_lpszPath, (int)pThreadnumber );
printf( "%d: %s -> %s.\n", (int)pThreadnumber, szFileInput, szFileOutput );
FILE* fpInput = NULL;
FILE* fpOutput = NULL;
fpInput = fopen( szFileInput, "w" );
if( fpInput == NULL )
{
printf( "Thread %d: error opening input file for initial writing: \n%s\n%s", (int)pThreadnumber, strerror( errno ),strerror( _doserrno ) );
exit( 0 );
}
for( nBlock = 0 ; nBlock < RECORD_COUNT ; nBlock++ )
{
if( fwrite( szBuffer, RECORD_SIZE, 1, fpInput ) != 1 )
{
printf( "Thread %d: error writing initial input file: \n%s\n%s", (int)pThreadnumber, strerror( errno ),strerror( _doserrno ) );
exit( 0 );
}
if( fflush( fpInput ) != 0 )
{
printf( "Thread %d: error flushing input file: \n%s\n%s", (int)pThreadnumber, strerror( errno ),strerror( _doserrno ) );
exit( 0 );
}
}
fclose( fpInput );
fpInput = fopen( szFileInput, "r" );
if( fpInput == NULL )
{
printf( "Thread %d: error opening input file for reading: \n%s\n%s", (int)pThreadnumber, strerror( errno ),strerror( _doserrno ) );
exit( 0 );
}
fpOutput = fopen( szFileOutput, "w" );
if( fpOutput == NULL )
{
printf( "Thread %d: error opening output file for writing: \n%s\n%s", (int)pThreadnumber, strerror( errno ),strerror( _doserrno ) );
exit( 0 );
}
for( nBlock = 0 ; nBlock < RECORD_COUNT ; nBlock++ )
{
if( fread( szBuffer, RECORD_SIZE, 1, fpInput ) != 1 )
{
printf( "Thread %d: error reading input file: \n%s\n%s", (int)pThreadnumber, strerror( errno ),strerror( _doserrno ) );
exit( 0 );
}
if( fwrite( szBuffer, RECORD_SIZE, 1, fpOutput ) != 1 )
{
printf( "Thread %d: error writing output file: \n%s\n%s", (int)pThreadnumber, strerror( errno ),strerror( _doserrno ) );
exit( 0 );
}
if( fflush( fpOutput ) != 0 )
{
printf( "Thread %d: error flushing output file: \n%s\n%s", (int)pThreadnumber, strerror( errno ),strerror( _doserrno ) );
exit( 0 );
}
}
fclose( fpInput );
fclose( fpOutput );
if( remove( szFileInput ) != 0 )
{
printf( "Thread %d: error removing input file: \n%s\n%s", (int)pThreadnumber, strerror( errno ),strerror( _doserrno ) );
exit( 0 );
}
if( rename( szFileOutput, szFileInput ) != 0 )
{
printf( "Thread %d: error renaming files: \n%s\n%s", (int)pThreadnumber, strerror( errno ),strerror( _doserrno ) );
exit( 0 );
}
if( remove( szFileInput ) != 0 )
{
printf( "Thread %d: error removing renamed file: \n%s\n%s", (int)pThreadnumber, strerror( errno ),strerror( _doserrno ) );
exit( 0 );
}
EnterCriticalSection( &g_CriticalSection );
g_nThreadsRunning--;
LeaveCriticalSection( &g_CriticalSection );
_endthreadex( 0 );
return 0;
}
int main( int argc, char* argv[] )
{
// Initialize the critical section one time only.
InitializeCriticalSection( &g_CriticalSection );
if( argc != 2 )
{
printf( "Usage: %s Path", argv[0] );
return 0;
}
g_lpszPath = argv[1];
int nCount = 0;
while( true )
{
EnterCriticalSection( &g_CriticalSection );
if( g_nThreadsRunning < CONCURRENT_THREADS )
{
unsigned int dwThreadID;
g_nThreadsRunning++;
nCount++;
_beginthreadex( NULL, 0, ThreadFunction, (void*)nCount, 0, &dwThreadID );
}
LeaveCriticalSection( &g_CriticalSection );
Sleep( 100 );
}
// Release resources used by the critical section object.
DeleteCriticalSection( &g_CriticalSection );
return 0;
}
Grill me