You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bounce.c is a sample multithread program that creates a new thread each time the letter a or A is typed. Each thread bounces a happy face of a different color around the screen. Up to 32 threads can be created. The program's normal termination occurs when q or Q is typed. For information about compiling and linking Bounce.c, see Compiling and Linking Multithread Programs.
Example
Code
// sample_multithread_c_program.c // compile with: /c // // Bounce - Creates a new thread each time the letter 'a' is typed. // Each thread bounces a happy face of a different color around // the screen. All threads are terminated when the letter 'Q' is // entered. // #include<windows.h>#include<stdlib.h>#include<string.h>#include<stdio.h>#include<conio.h>#include<process.h>#defineMAX_THREADS 32
// The function getrandom returns a random number between // min and max, which must be in integer range. #definegetrandom( min, max ) (SHORT)((rand() % (int)(((max) + 1) - \
(min))) + (min))
intmain( void ); // Thread 1: main voidKbdFunc( void ); // Keyboard input, thread dispatch voidBounceProc( void*MyID ); // Threads 2 to n: display voidClearScreen( void ); // Screen clear voidShutDown( void ); // Program shutdown voidWriteTitle( intThreadNum ); // Display title bar information HANDLEhConsoleOut; // Handle to the console HANDLEhRunMutex; // "Keep Running" mutex HANDLEhScreenMutex; // "Screen update" mutex intThreadNr; // Number of threads started CONSOLE_SCREEN_BUFFER_INFOcsbiInfo; // Console information intmain() // Thread One
{
// Get display screen information & clear the screen. hConsoleOut=GetStdHandle( STD_OUTPUT_HANDLE );
GetConsoleScreenBufferInfo( hConsoleOut, &csbiInfo );
ClearScreen();
WriteTitle( 0 );
// Create the mutexes and reset thread count. hScreenMutex=CreateMutex( NULL, FALSE, NULL ); // Cleared hRunMutex=CreateMutex( NULL, TRUE, NULL ); // Set ThreadNr=0;
// Start waiting for keyboard input to dispatch threads or exit. KbdFunc();
// All threads done. Clean up handles. CloseHandle( hScreenMutex );
CloseHandle( hRunMutex );
CloseHandle( hConsoleOut );
}
voidShutDown( void ) // Shut down threads
{
while ( ThreadNr>0 )
{
// Tell thread to die and record its death. ReleaseMutex( hRunMutex );
ThreadNr--;
}
// Clean up display when done WaitForSingleObject( hScreenMutex, INFINITE );
ClearScreen();
}
voidKbdFunc( void ) // Dispatch and count threads.
{
intKeyInfo;
do
{
KeyInfo=_getch();
if ( tolower( KeyInfo ) =='a'&&ThreadNr<MAX_THREADS )
{
ThreadNr++;
_beginthread( BounceProc, 0, &ThreadNr );
WriteTitle( ThreadNr );
}
} while( tolower( KeyInfo ) !='q' );
ShutDown();
}
voidBounceProc( void*pMyID )
{
charMyCell, OldCell;
WORDMyAttrib, OldAttrib;
charBlankCell=0x20;
COORDCoords, Delta;
COORDOld= {0,0};
DWORDDummy;
char*MyID= (char*)pMyID;
// Generate update increments and initial // display coordinates. srand( (unsigned int) *MyID*3 );
Coords.X=getrandom( 0, csbiInfo.dwSize.X-1 );
Coords.Y=getrandom( 0, csbiInfo.dwSize.Y-1 );
Delta.X=getrandom( -3, 3 );
Delta.Y=getrandom( -3, 3 );
// Set up "happy face" & generate color // attribute from thread number. if( *MyID>16)
MyCell=0x01; // outline face elseMyCell=0x02; // solid face MyAttrib=*MyID&0x0F; // force black background do
{
// Wait for display to be available, then lock it. WaitForSingleObject( hScreenMutex, INFINITE );
// If we still occupy the old screen position, blank it out. ReadConsoleOutputCharacter( hConsoleOut, &OldCell, 1,
Old, &Dummy );
ReadConsoleOutputAttribute( hConsoleOut, &OldAttrib, 1,
Old, &Dummy );
if (( OldCell==MyCell ) && (OldAttrib==MyAttrib))
WriteConsoleOutputCharacter( hConsoleOut, &BlankCell, 1,
Old, &Dummy );
// Draw new face, then clear screen lock WriteConsoleOutputCharacter( hConsoleOut, &MyCell, 1,
Coords, &Dummy );
WriteConsoleOutputAttribute( hConsoleOut, &MyAttrib, 1,
Coords, &Dummy );
ReleaseMutex( hScreenMutex );
// Increment the coordinates for next placement of the block. Old.X=Coords.X;
Old.Y=Coords.Y;
Coords.X+=Delta.X;
Coords.Y+=Delta.Y;
// If we are about to go off the screen, reverse direction if( Coords.X<0||Coords.X >= csbiInfo.dwSize.X )
{
Delta.X=-Delta.X;
Beep( 400, 50 );
}
if( Coords.Y<0||Coords.Y>csbiInfo.dwSize.Y )
{
Delta.Y=-Delta.Y;
Beep( 600, 50 );
}
}
// Repeat while RunMutex is still taken. while ( WaitForSingleObject( hRunMutex, 75L ) ==WAIT_TIMEOUT );
}
voidWriteTitle( intThreadNum )
{
enum {
sizeOfNThreadMsg=80
};
charNThreadMsg[sizeOfNThreadMsg];
sprintf_s( NThreadMsg, sizeOfNThreadMsg,
"Threads running: %02d. Press 'A' ""to start a thread,'Q' to quit.", ThreadNum );
SetConsoleTitle( NThreadMsg );
}
voidClearScreen( void )
{
DWORDdummy;
COORDHome= { 0, 0 };
FillConsoleOutputCharacter( hConsoleOut, ' ',
csbiInfo.dwSize.X*csbiInfo.dwSize.Y,
Home, &dummy );
}