Previous Table of Contents Next


21.4.4 Use of Portable Interceptor Current


   21.4.4.1 Client-side use of PICurrent

   PICurrent is merely a slot table. Before a request, a service’s Current can store its context specific data into a slot in PICurrent. When a request begins, PICurrent’s context transitions from a thread context to a request context. (That is, the ORB logically makes a copy of the current PICurrent and places that copy on the request. Note that this could be a lazy copy. A copy would only be necessary if PICurrent were modified. Since a copy may never actually be made, the term “logical copy? is used in this section.) Each service’s Interceptor now has access to the data that its Current put into PICurrent’s slot table. In other words, each service’s Interceptor now has access to the data within the calling client’s thread context even though the request processing may be in a different thread.

   For example, see the following pseudo-code. Within its ORBInitializer (see Section 21.7.1, “ORBInitializer Interface,? on page 21-50), the transaction service allocates a slot:

   PortableInterceptor::SlotId mySlotId =orb_init_info.allocate_slot_id ();

   When a transaction begins, the Transaction’s Current is called, which can place its context information in a slot on PICurrent:

   any myData = ...; // get data from Transaction’s Current

   PortableInterceptor::Current pic = orb.resolve_initial_references (“PICurrent?);

   pic.set_slot (mySlotId, myData);

   When an operation invocation begins, the ORB logically copies PICurrent from the thread context to the request context and the slots are available to Interceptors via the ClientRequestInfo object. So the transaction service’s Interceptor could look like:

   any myData = info.get_slot (mySlotId);IOP::ServiceContext sc = ...;// convert myData to a SCinfo.add_request_service_context (sc);

   The request scope PICurrent slots are read-only on the client. There is no set_slot on the ClientRequestInfo object.

   21.4.4.2 Example of PICurrent to Handle Client-side Recursion

   If an Interceptor itself makes an operation invocation, it shall have some means of breaking infinite recursion. For example: the client calls operation X; send_request is called, which calls operation Y; send_request is called, which again calls operation Y; and so on unless the implementation of send_request breaks the recursion.

   Recursion can be broken using PICurrent. If an Interceptor knows it will recurse, it allocates a slot in PICurrent in its ORBInitializer (see Section 21.7.1, “ORBInitializer Interface,? on page 21-50) that it will use for recursion:

   PortableInterceptor::SlotId recurseId =orb_init_info.allocate_slot_id ();

   At the point at which it recurses, say in send_request, it does so in a manner similar to the following:

   any recurse = info.get_slot (recurseId);

   // if we haven’t yet recursed, then the slot will be empty.if (recurse.type () == tk_null){

   // Fill in the recurse slot before making// the recursive call.any recurseFlag = new any;recurseFlag.insert_boolean (true);PortableInterceptor::Current pic =

   orb.resolve_initial_references (“PICurrent?);

   pic.set_slot (recurseId, recurseFlag);

   // Now make the recursive call.someObject.someOperation ();

   }

   When a client calls operation X, send_request is invoked for operation X. The recurse slot is empty, so the if block is executed: the recurse slot is set to true for this thread’s PICurrent and the recursive call to someOperation is made. send_request is again invoked, this time for someOperation. This time the recurse slot is not empty, so the if block is not executed and the recursive call is not made, thus breaking the recursion.

   21.4.4.3 Server-side use of PICurrent

   The service contexts associated with the request may be propagated, using PICurrent, to the context of the thread that will execute the operation. The request’s PICurrent is read and written via the get_slot and set_slot operations on ServerRequestInfo.

   receive_request_service_contexts shall populate the slots of the request scope PICurrent. The ORB logically copies this PICurrent to the thread scope after processing the receive_request_service_contexts list.

   When the operation invocation completes, the send interception points still have read/write access to the request scope PICurrent.

   For example, within its ORBInitializer (see Section 21.7.1, “ORBInitializer Interface,? on page 21-50), the transaction service allocates a slot:

   PortableInterceptor::SlotId mySlotId =orb_init_info.allocate_slot_id ();

   The Transaction Interceptor can move the transaction information from the service context list to PICurrent:

   IOP::ServiceContext sc =

   info.get_request_service_context (transactionId);

   any myData = // convert SC to an any

   info.set_slot (mySlotId, myData);

   Within a server thread, the Transaction service can transfer its information from PICurrent to the TransactionCurrent:

   PortableInterceptor::Current pic =

   orb.resolve_initial_references (“PICurrent?);

   any myData = pic.get_slot (mySlotId);

   // Copy myData into the current context.

   21.4.4.4 Request Scope vs Thread Scope

   The thread scope PICurrent is the PICurrent that exists within a thread’s context. A request scope PICurrent is the PICurrent associated with the request. On the client-side, the thread scope PICurrent is logically copied to the request scope PICurrent from the thread’s context when a request begins and is attached to the ClientRequestInfo object. On the server-side, the request scope PICurrent is attached to the ServerRequestInfo and follows the request processing. It is logically copied to the thread scope PICurrent after the list of receive_request_service_contexts interception points are processed.

   21.4.4.5 Flow of PICurrent between Scopes

   For the following, TSC means Thread Scope PICurrent; and RSC means Request Scope PICurrent. Refer to Figure 21-7 on page 21-39 for a graphical representation of the following discussion. The numbered points below correspond to the numbers in Figure 21-7.

   Before operation invocation, the client thread may read and write the TSC. On an operation invocation, the flow proceeds as follows:

   - though modifying the RSC at this point has no affect on the TSC. Since these points execute in the same thread as the target operation invocation, these points may modify the server-side TSC.


   Figure 21-7 Thread Scope vs Request Scope

   Figure 21-7 Legend

   Dotted Line Flow of control (between the thread scopes and the request scopes, the dotted arrows indicate a logical copy).

   Solid Line Access; single arrow is readonly, double arrow is read/write.

   Thick Dotted Line Boundary between client and server.

   21.4.4.6 Notes on PICurrent and Scopes

   Since an Interceptor is running in a thread, it is running with a thread context and there is a PICurrent on that context. If the Interceptor calls ORB::resolve_initial_references (“PICurrent?), it gets the PICurrent within its thread scope. This PICurrent is different than the request scope PICurrent that the Interceptor obtains via calls to the Client-or Server- RequestInfo object. So if an Interceptor makes an operation call, it is the Interceptor’s thread scope PICurrent that will be logically copied to the request scope of that operation, not the PICurrent from the original operation invocation.

   Even if a client-side Interceptor happens to be running in the same thread from which the invocation was made (this is vendor dependent), the request scope PICurrent and the thread scope PICurrent are still different. The request scope PICurrent is a copy of the thread scope PICurrent at the point when the invocation began. So even if an Interceptor changed the data in its thread scope PICurrent, that does not change the request scope PICurrent.

   Interceptors shall assume that each client-side interception point logically runs in its own thread, with no context relationship between it and any other thread. While an ORB implementation may not actually behave in this manner, it is up to the ORB implementation to treat PICurrent as if it did.

   Interceptors shall assume that all server-side interception points except receive_request_service_contexts run in the same thread as the target operation invocation, thereby sharing thread context information. receive_request_service_contexts, like all client-side interception points, logically runs in its own thread, with no context relationship between it and any other thread.