PreviousNext

Use of Thread Handles in Memory Management

There are two situations where control of memory management requires the use of thread handles. The more common situation is when the manager thread spawns additional threads. The less common situation is when a program transitions from being a client to being a server, then reverts to being a client.

Spawning Threads
When a remote procedure call invokes the manager code, the manager code may wish to spawn additional threads to complete the task for which it was called. To spawn additional threads that are able to perform memory management, the manager code must first call the rpc_ss_get_thread_handle( ) routine to get its thread handle and then pass that thread handle to each spawned thread. Each spawned thread that uses the rpc_ss_allocate( ) and rpc_ss_free( ) routines for memory management first calls the rpc_ss_set_thread_handle( ) routine by using the handle obtained by the original manager thread.

These routine calls allow the manager and its spawned threads to share a common memory management environment. This common environment enables memory allocated by the spawned threads to be used in returned parameters, and causes all allocations in the common memory management environment to be released when the manager thread returns to the server stub.

The main manager thread must not return control to the server stub before all the threads it spawned complete execution; otherwise, unpredictable results may occur.

The listener thread can cancel the main manager thread if the remote procedure call is orphaned or if a cancellation occurs on the client side of the application. You should code the main manager thread to terminate any spawned threads before it exits. The code should anticipate exits caused by an unexpected exception or by being canceled.

Your code can handle all of these cases by including a TRY/FINALLY block to clean up any spawned threads if a cancellation or other exception occurs. If unexpected exceptions do not concern you, then your code can perform two steps. They are disabling cancelability before threads are spawned followed by enabling cancelability after the join operation finishes and after testing for any pending cancel operations. Following this disable/enable sequence prevents routine pthread_join( ) from producing a cancel point in a manager thread that has spawned threads which, in turn, share thread handles with the manager thread.

Transitioning from Client to Server to Client
Immediately before the program changes from a client to a server, it must obtain a handle on its environment as a client by calling rpc_ss_get_thread_handle( ). When it reverts from a server to a client, it must reestablish the client environment by calling the rpc_ss_set_thread_handle( ) routine, supplying the previously obtained handle as a parameter.

Syntax for Thread Routines
The syntax for the rpc_ss_get_thread_handle( ) routine is as follows:

rpc_ss_thread_handle_t rpc_ss_get_thread_handle(void);

The syntax for the rpc_ss_set_thread_handle( ) routine is as follows:

void rpc_ss_set_thread_handle (
rpc_ss_thread_handle_t
id
);

The rpc_ss_thread_handle_t( ) value identifies the thread to the RPC stub support library. The id parameter indicates the thread handle passed to the spawned thread by its creator, or the thread handle returned by the previous call to rpc_ss_get_thread_handle( ).