### Calls to Nonreentrant Functions

All functions in the C++ Complex Mathematics Open Class Library are reentrant; those in the I/O Stream Library are not.

To use these I/O Stream objects in a multithread environment, you must provide your own serialization either using the OS/2 semaphore API function or the IResourceLock, IPrivateResource, and ISharedResource classes from the User Interface Class Library.

Other nonreentrant library functions can access data or resources that are common to all threads in the process, including files, environment variables, and I/O resources. To prevent any interference among themselves, these functions use semaphores, provided by the Windows operating system, to serialize access to data and resources.

Operations involving file handles and standard I/O streams are serialized so that multiple threads can send output to the same stream without intermingling the output.

Specific restrictions:

- The getc, getchar, putc, and putchar file I/O operations are implemented as macros in the single-thread C libraries. In the multithread libraries, they are redefined as functions to implement any necessary serialization of resources.
- Use the _fcloseall function only after all file I/O has been completed.
- When you use printf or vprintf and the subsystem libraries, you must provide the necessary serialization for stdout.

Example of Serialized I/O

If thread1 and thread2 execute the calls in the example below, the output could appear in several different ways, but never garbled as shown at the end of the example.

     #include <stdio.h>

    int done_1 = 0;
    int done_2 = 0;

    void _Optlink thread1(void)
    {
       fprintf(stderr,"This is thread 1\n");
       fprintf(stderr,"More from 1\n");
       done_1 = 1;
    }

    void _Optlink thread2(void)
    {
       fprintf(stderr,"This is thread 2\n");
       fprintf(stderr,"More from 2\n");
       done_2 = 1;
    }

    int main(void)
    {
       _beginthread(thread1, NULL, 4096, NULL);
       _beginthread(thread2, NULL, 4096, NULL);

       while (1)
       {
          if (done_1 && done_2)
             break;
       }
       return 0;
    }

    /* Possible output could be:

            This is thread 1
            This is thread 2
            More from 1
            More from 2
    or
            This is thread 1
            More from 1
            This is thread 2
            More from 2
    or
            This is thread 1
            This is thread 2
            More from 2
            More from 1

       The output will never look like this:

            This is This is thrthread 1
            ead 2
            More froMore m 2
            from 1                            */

Multithreaded Applications

Reentrant Functions