BEA Logo BEA Tuxedo Release 7.1

  Corporate Info  |  News  |  Solutions  |  Products  |  Partners  |  Services  |  Events  |  Download  |  How To Buy

 

   Tuxedo Doc Home   |   Programming   |   Topic List   |   Previous   |   Next   |   Contents

   Programming a BEA Tuxedo Application Using C

Writing Code to Enable Multicontexting and Multithreading in a Server

Context Attributes

When writing your code, keep in mind the following considerations about contexts:

Coding Rules for a Multicontexted Server

Keep in mind the following rules for coding multicontexted servers:

Initializing and Terminating Servers and Server Threads

To initialize and terminate your servers and server threads, you can use the default functions provided by the BEA Tuxedo system or you can use your own.

Default Functions for Initialization and Termination

To . . .

Use the default function

Initialize a server

tpsvrinit(3c)

Initialize a server thread

tpsvrthrinit(3c)

Terminate a server

tpsvrdone(3c)

Terminate a server thread

tpsvrthrdone(3c)

Programming a Server to Create Threads

You may create additional threads within an application server, although most applications using multicontexted servers use only the dispatched server threads created by the system. This section provides instructions for doing so.

Creating Threads

You may create additional threads within an application server by using OS threads functions. These new threads may operate independently of the BEA Tuxedo system, or they may operate in the same context as one of the server-dispatched threads.

Associating Threads with a Context

Initially, application-created server threads are not associated with any server-dispatched context. If called before being initialized, however, most ATMI functions perform an implicit tpinit(). Such calls introduce problems because servers are prohibited from calling tpinit(). (If a server process calls tpinit(), tpinit() returns -1 and sets tperrno(5) to TPEPROTO.)

Therefore, an application-created server thread must associate itself with an existing context before calling any ATMI functions. To associate an application-created server thread with an existing context, you must write code that implements the following procedure.

  1. Server-dispatched-thread_A gets a handle to the current context by calling tpgetctxt(3c).

  2. Server-dispatched-thread_A passes the handle returned by tpgetctxt(3c) to Application_thread_B.

  3. Application_thread_B associates itself with the current context by calling tpsetctxt(3c), specifying the handle received from Server-dispatched-thread_A.

  4. Application-created server threads cannot call tpreturn() or tpforward(). Before the originally dispatched thread calls tpreturn() or tpforward(), all application-created server threads that have been in that context must switch to TPNULLCONTEXT or another valid context.

    If this rule is not observed, then tpforward() or tpreturn() fails and indicates a service error to the caller.

Sample Code for Creating an Application Thread in a Multicontexted Server

For those applications with a need to create an application thread in a server, the following code sample shows a multicontexted server in which a service creates another thread to help perform its work. Operating system (OS) threads functions differ from one OS to another. In this sample POSIX and ATMI functions are used.

Notes: In order to simplify the sample, error checking code is not included. Also, an example of a multicontexted server using only threads dispatched by the BEA Tuxedo system is not included because such a server is coded in exactly the same way as a single-contexted server, as long as thread-safe programming practices are used.

Code Sample for Creating a Thread in a Multicontexted Server


#include <pthread.h>
#include <atmi.h>

void *withdrawalthread(void *);

struct sdata {
TPCONTEXT_T ctxt;
TPSVCINFO *svcinfoptr;
};

void
TRANSFER(TPSVCINFO *svcinfo)
{
struct sdata transferdata;
pthread_t withdrawalthreadid;

tpgetctxt(&transferdata.ctxt, 0);
transferdata.svcinfoptr = svcinfo;
pthread_create(&withdrawalthreadid, NULL, withdrawalthread, &transferdata);
tpcall("DEPOSIT", ...);
pthread_join(withdrawalthreadid, NULL);
tpreturn(TPSUCCESS, ...);
}


void *
withdrawalthread(void *arg)
{
tpsetctxt(arg->ctxt, 0);
tpopen();
tpcall("WITHDRAWAL", ...);
tpclose();
return(NULL);
}


The previous example accomplishes a funds transfer by invoking the DEPOSIT service in the originally dispatched thread, and WITHDRAWAL in an application-created thread. This example is based on the assumption that the resource manager being used allows a mixed model such that multiple threads of a server can be associated with a particular database connection without all threads of the server being associated with that instance. Most resource managers, however, do not support such a model.

A simpler way to code this example is to avoid the use of an application-created thread. To obtain the same concurrency provided by the two calls to tpcall() in the example, substitute two calls to tpacall() and two calls to tpgetrply() in the server-dispatched thread.

See Also