Reentrant
Code and Compiler Flags
Depending upon the platform and compiler, it may be necessary to compile
with special flags to indicate that the application is multithreaded. On some
platforms, gcc has the flag -pthread, which
links in the POSIX threading library and defines _REENTRANT. The Solaris Studio compiler has the flag -mt, which performs the same task; only the flag defined is __REENTRANT.
Defining the preprocessor flag includes a set of
“reentrant” functions to go with the usual set. The reentrant versions are
denoted by the _r postfix. The reason these
func-tions exist is that many of the C library functions are stateful, meaning
that a call to the function sets up some state that is then used in later
function calls. This statefulness means that multiple threads cannot call the
function at the same time without the state becoming corrupted. The reentrant
versions of the functions typically use a structure that the calling thread
provides to hold the state for that calling thread. The code in Listing 5.75
uses the readdir() call to
print out the contents of the current directory.
Listing 5.75 Multithread
Unsafe Code for Listing a Directory
#include <dirent.h> #include <stdio.h>
int
main()
{
DIR *
directory = opendir( "." );
while ( 1 )
{
struct dirent
* entry = readdir( directory );
if (entry!=0)
{
printf( "%s\n", entry->d_name );
}
else
{
closedir(
directory );
break;
}
}
}
The code works when compiled as a single-threaded
application but could, on some operating systems, fail if multiple threads were
to use the readdir() function
simultane-ously. The code can easily be modified to use the reentrant version
of readdir(), readdir_r(). Listing 5.76 shows the modified code.
Listing 5.76 Using
Multithread-Safe Code to Print Out a Directory Listing
#include <dirent.h> #include <stdio.h>
#include <stdlib.h>
int main()
{
DIR *
directory = opendir( "." );
struct dirent * entry; struct dirent * result;
entry = (struct dirent*)malloc(
sizeof(struct dirent) + FILENAME_MAX + 1 );
while ( ( readdir_r( directory,
entry, &result ) ==0 ) && result )
{
printf( "%s\n", entry->d_name );
}
closedir(
directory );
free( entry );
}
The reentrant version of readdir() places the results into a dirent structure that is passed into the call. However, not all operating
systems declare the dirent
structure with storage for the filename by default. The code shown will compile
on Solaris with _POSIX_C_SOURCE defined
to be greater than or equal to 199506L.
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.