Using Threads

Rationale
After reading the Pthreads Primer, and attempting to apply it to eCS, I found a need for an introduction to the API and explanations on how to use it. This is an attempt to fill that void. --Myrkraverk 03:19, 4 November 2007 (CET)

Use of C++ in the Examples
I am a C++ programmer and frequently run into "small differences" when attempting to use a plain C compiler. These are mostly differences in automatic variable declaration and initialization which are leveraged somewhat with C99. However, I do not want to spend my time battling "plain C" syntax peculiarities or C99 feature command line switches, so I simply compile all my examples as C++.

The only "especially C++" feature I use is std::cout instead of printf which any reasonably proficient C programmer can translate on the spot.

Creating Threads
Thread creation can be done with the DosCreateThread system call, or the C runtime library _beginthread function.

The DosCreateThread system call is inherently low level and does not initialize the C/C++ runtime environment. In particular:
 * You can not assume C++ Exceptions will work. VisualAge C++ has #pragma handler for this but it can not be relied upon with OpenWatcom or GCC.
 * You can not rely on the state of the floating point unit. You can however, reset it with _fpreset.
 * You can not rely on DosExit to clear up thread specific data and/or the runtime environment; use _endthread instead.
 * That is, the C/C++ runtime environment may be initialized on first use (this is documented for VisualAge C++ but apparently not for OpenWatcom or GCC). Also:
 * From the OpenWatcom C/C++ Programmer's Guide:
 * WARNING! If any thread calls a library function, you must use the _beginthread function to create the thread. Do not use the DosCreateThread API function.


 * From the OS/2 Toolkit 4.5:
 * Note: If you use DosCreateThread, you must explicitly call _endthread to terminate the thread.

None of this is an issue when using _beginthread; it takes care of setting up the runtime environment and tearing it down when the thread function ends.

Hello, Threaded World!
Here is a short example of _beginthread: // file: hello_thread.c++ void hello( void * ) {  std::cout << "Hello from thread." << std::endl; } int main( int argc, char *argv[] ) {  _beginthread( hello, 0, 4096 * 10, 0 ); DosSleep( 10 );                      // Allow the thread to finish. }
 * 1) include
 * 2) include 
 * 1) define INCL_DOSPROCESS
 * 2) include 

This can be compiled with OpenWatcom like so: >wcl386 -cc++ -bm "hello_thread.c++" or with GCC like so: >g++ -Zmt "hello_thread.c++" Here is the same program, using DosCreateThread. Note that it uses a library call, despite the warnings above.

// file: hello_doscreate.c++ void _System hello( long unsigned int ) {  std::cout << "Hello from thread." << std::endl; } int main( int argc, char *argv[] ) {  TID tid = 0; DosCreateThread( &tid, hello, 0, CREATE_READY | STACK_SPARSE, 4096 * 10 ); DosSleep( 10 );  // Allow the thread to finish }
 * 1) include
 * 1) define INCL_DOSPROCESS
 * 2) include 