Threads Module User's Guide : PART II Concurrency Packages : Chapter 3 The Threading Package : The Runnable Object Classes : Execution Nesting
Execution Nesting
When an active runnable starts a second, synchronous runnable, the second runnable is executing or nested inside the first. Each runnable that is executing a nested runnable maintains an internal reference or link to that runnable. These links are traversed to find the innermost runnable currently executing under a thread.
Execution nesting is implemented by the following functions:
RWRunnable RWRunnableSelf::getNestedRunnable(void) const
RWRunnableSelf RWRunnable::getNestedRunnable(void) const
RWRunnableSelf rwRunnable(void)
RWThreadSelf rwThread(void)
The rwThread() function can be used to get a handle to the threaded runnable that originated the calling thread. If the calling thread was not started by a Threading package runnable class, as is the case with the main thread, then the handle returned by this function is empty. Whenever the source of a thread is in question, you should use the isValid() function to test the handle returned by rwThread() before using it, as shown Example 19.
Example 19 – Testing the source of a thread
RWThreadSelf thread = rwThread();
if (thread.isValid()) {
// OK, this thread was created by a runnable
}
Starting Synchronous Runnables
When a thread created by a threaded runnable starts a synchronous runnable, the thread eventually enters the run() member of that runnable. At that point, the thread is considered to be executing inside of the synchronous runnable as well.
In this situation, the synchronous runnable is nested inside of the threaded runnable. A nested runnable registers itself with the enclosing parent runnable for the purpose of supporting cancellation and other operations.
Starting a threaded runnable from within another runnable does not produce a nesting relationship because the threaded runnable launches its own thread of execution. No nesting relationship is formed when a synchronous runnable is started by a thread that does not originate from a Threading package runnable.
A handle to the nested runnable can be retrieved from an enclosing runnable by calling the getNestedRunnable() member. If a runnable does not have a nested runnable executing within it, an empty handle is return. This operation allows nested runnables to be traversed to find the innermost runnable.
Using the Nested Runnable Information
When a parent runnable is canceled, the cancellation request uses the nested runnable information to recursively propagate the request down to the innermost nested runnable. In the present version of the Threading package, cancellation is the only operation that propagates in this manner.
The nesting information can also be used to determine the current enclosing runnable for any thread that originated from a threaded runnable. Although it is possible to do this yourself by using the rwThread() and getNestedRunnable() functions, you can also use the Threading package function rwRunnable(). As was the case with the handle returned by rwThread(), the handle returned from rwRunnable() is empty if the current thread was not created by a Threading package runnable class.