Lab 2
Operating systems
If you create threads using CreateThread you are using the sort of direct low level call to create the thread. If we have a multithreaded program and we use the normal C runtime librariy we can run into a number of problems in the the C run time support was not designed for a multithreaded environment. The solution is to create a copy of the static variables used in the C run time library for each thread. There is a shorthand way of doing this. The solution is to make our threads using calls to _beginthreadex rather that directly to CreateThread. _beginthreadex can be thought of a some code that creates a thread but also arranges to have a copy of the static variables of the C runtime library created for the private use of that thread.
unsigned long _beginthread(
void( __cdecl *start_address )( void * ), unsigned stack_size, void *arglist
);
unsigned long _beginthreadex(
void *security, unsigned stack_size, unsigned ( __stdcall
*start_address )( void * ), void *arglist, unsigned initflag, unsigned *thrdaddr );
|
Routine |
Required Header |
Compatibility |
|
_beginthread |
<process.h> |
Win 95, Win NT |
|
_beginthreadex |
<process.h> |
Win 95, Win NT |
For additional
compatibility information, see Compatibility
in the Introduction.
Libraries
|
LIBCMT.LIB |
Multithread static library, retail version |
|
MSVCRT.LIB |
Import library for MSVCRT.DLL, retail version |
To use _beginthread or _beginthreadex,
the application must link with one of the multithreaded C run-time libraries.
Return
Value
If successful, each of
these functions returns a handle to the newly created thread. _beginthread returns –1 on an error, in which case errno is set to EAGAIN if there are too many
threads, or to EINVAL if the argument is invalid or the stack size is
incorrect. _beginthreadex returns 0 on an
error, in which case errno and doserrno are set.
Parameters
start_address
Start
address of routine that begins execution of new thread
stack_size
Stack size
for new thread or 0
arglist
Argument
list to be passed to new thread or NULL
security
Security
descriptor for new thread; must be NULL for Windows 95 applications
initflag
Initial
state of new thread (0 for running or CREATE_SUSPEND for
suspended)
thrdaddr
Points to a
32-bit variable that receives the thread identifier
Remarks
The _beginthread function creates a thread that begins
execution of a routine at start_address. The
routine at start_address must use the __cdecl calling convention and should have no return
value. When the thread returns from that routine, it is terminated
automatically.
_beginthreadex resembles the Win32 CreateThread
API more closely than does _beginthread. _beginthreadex differs from _beginthread
in the following ways:
#include <iostream.h>
//with _beginthreadex
#include <iostream.h>
#include <stdlib.h>
#include <windows.h>
#include <process.h>
DWORD WINAPI ThreadFunc(LPVOID n)
{
int i,j;
for
(i=0;i<10;i++)
{ for
(j=0;j<30;j++)
{
cout
<< (int)n ;
Sleep(10*(int)n);
}
cout << endl
;}
return(0);
}
int
main()
{
HANDLE hThrds[5];
DWORD aThreadID;
int i,j;
//Create 5 threads
reusing
for
(i=0; i<5; i++)
{
hThrds[i] = (HANDLE) _beginthreadex(
0,0,
(unsigned (_stdcall *)(void *)) ThreadFunc,
(LPVOID) i,0, (unsigned *) &aThreadID
);
if (hThrds[i])
{
cout << "Thread
launched" << i<< endl;
}
else
{ cout << "Failed to
launch Thread" << i<< endl;
for (j=0; j<i; i++) CloseHandle(hThrds[j]);
exit(0);}
}
WaitForMultipleObjects(5, hThrds, TRUE, INFINITE);
for
(i=0; i<5; i++) CloseHandle(hThrds[i]);
return(0);
}
A.
1. Create a new WIN32 console application (with a new workspace) in Visual studio.
2. Check that the project settings are correctProject->Settings->C/C++ -> Code Generations ->Debug Multithreaded 3. Add a new C++ source file for and copy the program using _beginthread into it File->new->Files-> C++ source 4. Build it and execute 5. Edit source file and remove comments from Sleep statement in Threadfuncthenbuild it and execute it again.
Question Explain the difference behavior between the first execution and the second.Why is there a run of 0’s at the beginning and a run of 4’s at the end during the second run? B.1. Replace the thread function in the program using _beginthread with voidThreadFunc(LPVOID n)
{ int i,j; int h=*((int*)n); for (i=0;i<10;i++) { for (j=0;j<30;j++) { cout << h ; Sleep(10*h); } cout << endl ;})2. In main procedurechangethe _beginthread call to
hThrds[i] = (HANDLE) _beginthread(
ThreadFunc, 0, &i );
Write 3 programs
Each program should calculate and print out the time required to executes
Discuss any diffences in the times among the executions.
Thread function
(requires #include <time.h>) routine that
computes the value of PI
DWORD
WINAPI ComputePi(LPVOID n)
{
int
i;
int
inside = 0;
double val;
UNREFERENCED_PARAMETER(n);
/* Seed the random-number generator */
srand( (unsigned)time( NULL ) );
for (i=0; i<1000000; i++)
{
double x =
(double)(rand())/RAND_MAX;
double y =
(double)(rand())/RAND_MAX;
if ( (x*x +
y*y) <= 1.0 )
inside++;
}
val
= (double)inside / i;
printf("PI = %.4g\n", val*4);
return 0;
}
1.Make sure you have the following include files
#include <stream.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
2. Check that the project settings are correctProject->Settings->C/C++ -> Code Generations ->Debug Multithreaded
*DWORD is a 32 bit unsigned integer Useful Functions 1. BOOL GetExitCodeThread(HANDLEhThread,// handle to the thread ( value returned by CreateThread)
LPDWORDlpExitCode// address to receive termination status
);
function retrieves the termination
status of the specified thread. If it is still running it will return the code
STILL_ACTIVE in the second
parameter (here named lpExitCode).
2. DWORD GetTickCount( VOID)
The GetTickCount function
retrieves the number of milliseconds that have elapsed since the system was
started. It is limited to the resolution of the system timer.
This function has no parameters. The return value is the number of milliseconds that have elapsed since the system was started.
3.DWORD WaitForSingleObject(
HANDLE hHandle, // handle to object to wait for
DWORD dwMilliseconds // time-out interval in milliseconds
);
The WaitForSingleObject
function returns when one of the following occurs:
a.
The specified object is in the signaled state.
b. The time-out interval elapses.
HHandle Handle to the object. For a list of the object types whose handles can be specified, see the following Remarks section.
dwMilliseconds
Specifies the time-out
interval, in milliseconds. The function returns if the interval elapses, even
if the object's state is nonsignaled. If dwMilliseconds is zero, the function tests the
object's state and returns immediately. If dwMilliseconds
is INFINITE, the function's time-out interval never elapses.