Rogue Wave banner
Previous fileTop of DocumentContentsIndexNext file

3.4 Using Threads

This section uses a simple example to introduce and explain the concepts and classes involved in creating threads. You can find more examples in examples\thr0200osfam\thread. The following list gives the names of those examples and the classes and functions that they exercise:

The scope and completeness of some examples in this guide are limited to insure readability and satisfy size constraints. For this reason, you should also review the example programs distributed with the Threading package. See the workspace directory table in the Build Guide for the exact location of the examples for your build.

3.4.1 Creating Threads

Example 1 creates a second thread of execution (main() is the first thread) and uses that thread to call a global function that prints the message "Hello World!" to the console.

Example 1 -- Creating threads

//1Include the header file containing the RWThreadFunction class declaration used in the example.
//2Define a global function to produce the message.
//3Use a Threading package global function to construct an RWThreadFunction runnable that executes the hello() function when started. That runnable object is bound to a local handle named myThread.
//4Start the runnable. This results in the creation of a new thread that then executes the hello() function.
//5Wait for the newly created thread to finish execution.

The following sections take a closer look at some of the key components of this example.

3.4.2 Introducing the Runnable

In the Threading package, the runnable family of classes includes the basic mechanisms used to create, control, and monitor the threads of execution within your application. The RWThreadFunction class used in the example is a member of the runnable family; Figure 2 shows its relationship to the other runnable classes.

All runnable objects have a start() member and a virtual run() member. The run() member defines the work or activity to be performed by the runnable object. The start() member defines the form of dispatching to be used in executing the run() member. The dispatching is performed either synchronously by executing within the calling thread, or asynchronously by creating a new thread. Regardless of the dispatching mechanism, the run() member is always executed as a consequence of calling start().

The RWThreadFunction class used in the example is one of the asynchronous or threaded runnable classes. Instances of this class create a new thread of execution when start() is called. The RWThreadFunction class uses a functor to indicate to the new thread what to execute after it starts; in this case, the hello() function.

See Section 3.5, "The Runnable Object Classes," for more information.

3.4.3 Runnable Make Functions

In the example, a convenience function called rwtMakeThreadFunction() constructs an RWThreadFunction instance. This "make" function is actually one of a family of template functions that uses the signature of a function to select, construct, and initialize an instance of the appropriate runnable class.

The rwtMakeThreadFunction() function call performs a two-step service. First, it constructs and initializes a functor object that is compatible with the specified function. Then, it uses the static make() function from RWThreadFunction to construct an RWThreadFunctionImp instance, passing it a handle to the newly constructed functor instance. For more information on make functions, see Section 3.5.2.1, "Global Template Functions."

3.4.4 Explicitly Constructing Functors and Runnables

In the following code segment, the rwtMakeThreadFunction() function is left out, and a functor and threaded runnable instance are explicitly constructed:

Example 2 -- Constructing a threaded runnable from a functor

//1Construct a handle instance for a functor object.
//2Use another convenience function to construct and initialize a functor instance that is compatible with the hello() function. Bind that instance to the handle instance, myFunctor.
//3Construct an empty RWThreadFunction handle instance.
//4Construct and initialize an RWThreadFunctionImp body instance. Bind that instance to the handle instance, myThread.

The code creates a threaded runnable that, when started, launches a thread that invokes the functor instance to execute the hello() function.

3.4.4.1 Functor Make Functions

The rwtMakeFunctor0() function used in //2 is a template function that uses the signature of the function you list to select, construct, and initialize an instance of the appropriate functor class.

As with the runnable "make" functions, these functor "make" functions are included for convenience and might not be 100% portable. To use them, your compiler must be able to extract template argument types from a function signature.

The next section describes an alternative to the functor "make" functions.

3.4.4.2 Using Macros

If your compiler cannot handle these "make" functions, you can use a macro to replace the rwtMakeFunctor() function call with the equivalent code, as in Example 3.

Example 3 -- Constructing a functor with a macro

//1Constructs a handle instance for a functor object.
//2Constructs and initializes a functor body instance that is compatible with the hello() function. Binds that body instance to the handle instance, myFunctor.

The macro can also be replaced with an explicit call to a static make function included by the functor body class:


Previous fileTop of DocumentContentsIndexNext file

©Copyright 2000, Rogue Wave Software, Inc.
Contact Rogue Wave about documentation or support issues.