ID Number: Q73516
5.10 6.00 6.00a
OS/2
Summary:
In Microsoft C versions 5.1, 6.0, and 6.0a, with an OS/2 application
that uses the multithreaded C run-time library functions, there are
many tables and data structures that all the threads must share. This
is done by placing a lock on the part of the table or data structure
that must remain unchanged during a particular run-time operation.
Although the run-time code performs all the data locking and unlocking
as necessary, a little planning and forethought is needed when
designing a multithreaded application to ensure that the application
will not have to stop and wait for slower operations because of these
locks.
More Information:
An example of data that all threads must share is the table of file
handles that is maintained for file I/O. If one thread is performing a
read or write to a particular file, all other threads must be blocked
from using or modifying that file handle. If the other threads were
not prevented from modifying that file handle, there is no way to
predict what might occur. For example, a separate thread could close
the file in the middle of an I/O operation.
Likewise, on a larger scale, a file open operation must have a lock on
the entire file handle table if it is to know which file handles are
used and which are available at a particular instant. If none are
available, the operation must fail with the appropriate return code.
To lock the entire table, there must be no individual file handle
locks on the table at the time.
It is especially important to be aware of these interdependencies
between individual field locks and global table locks so that a
program will not spend an inordinate amount of time waiting on blocked
threads. The example program below illustrates one such situation that
can arise if these dependencies are ignored during program design.
In the example, Thread 1 (the main thread) opens a file, spawns a
second thread, and then prompts the user for input. The operation of
prompting the user for input places a lock on the stdin file handle.
Thread 2, meanwhile, attempts to write to the file thread 1 opened.
This proceeds immediately because there is no lock on the table or
that particular file handle. Thread 2 then attempts to open a new
file, but the open operation requires a lock on the entire table.
Because the main thread has a lock on one of the handles in the table
(stdin), the operation must wait until the lock is released. Once the
main thread has released its lock on stdin, the open operation in the
second thread continues and returns the appropriate result. The sample
program output below indicates that this is indeed what happens.
Sample Code
-----------
/* Compile options needed: /MT
*/
#define INCL_DOS
#include <os2.h>
#include <stdio.h>
#include <string.h>
#include <process.h>
void thread(void);
void main(void);
FILE *fptr1;
FILE *fptr2;
void main()
{
int i = 1;
char name[25];
if( NULL != (fptr1 = fopen( "tstfle", "w+" )))
printf( "\nThread one has opened a test file.\n" );
else
printf( "\nThread one has failed to open a test file.\n" );
if( _beginthread( thread, NULL, 4096, NULL ) == -1 )
{
printf( "\nCan not start second thread.\n" );
return( -1 );
}
printf( "Thread one is prompting for five names.\n" );
while( i <= 5 )
{
printf( "\nEnter name %d: ", i );
gets( name );
i++;
}
DosSleep( 500L );
}
void thread( )
{
int count;
DosSleep( 500L );
if( fptr1 != NULL )
{
count = fprintf( fptr1, "This is a test.\n" );
printf( "\n\tThread two has written %d chars to thread one's ");
printf( "test file.\n", count );
}
DosSleep( 500L );
if (NULL != (fptr2 = fopen( "tstfle2", "w+" )))
printf( "\n\tThread two has opened a test file.\n" );
else
printf( "\n\tThread two has failed to open a test file.\n" );
}
Program Output
--------------
Thread one has opened a test file.
Thread one is prompting for five names.
Enter name 1:
Thread two has written 16 characters to thread one's test file.
<name1>
Enter name 2: <name2>
Enter name 3: <name3>
Enter name 4: <name4>
Enter name 5: <name5>
Thread two has opened a test file.
Additional reference words: 5.1 5.10 6.0 6.00 6.0a 6.00a