Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Advanced CORBA Programming wit C++ - M. Henning, S. Vinoski.pdf
Скачиваний:
65
Добавлен:
24.05.2014
Размер:
5 Mб
Скачать

IT-SC book: Advanced CORBA® Programming with C++

Chapter 11. The Portable Object Adapter

11.1 Chapter Overview

This chapter explains the POA in detail. After the introduction in Section 11.2, Section 11.3 provides a high-level overview of the POA. In Section 11.4 we provide details of the various policies that you use to control POA behavior. After that, we describe the process of creating POAs in Section 11.5. Section 11.6 defines servants and discusses how you implement them, and Section 11.7 explains how you create and activate CORBA objects using the POA. Section 11.8 details operations that convert between object references, object identifiers, and servants. In Section

11.9 we explain how to deactivate objects and reclaim servant resources. We describe the control of the flow of requests into a POA in Section 11.10. In Section 11.11 we briefly depart from our presentation of the POA to discuss issues related to ORB-level request flow control and server shutdown. Section 11.12 explains POA activation, and we describe POA destruction in Section 11.13. Finally, in Section 11.14 we discuss certain combinations of POA policies along with the types of applications that they are best suited for.

11.2 Introduction

We explain in Chapter 9 that the POA provides fundamental services such as object creation, servant registration, and request dispatching. However, that chapter presents only those POA features needed to explain the server-side C++ mapping. Specifically, it introduces only the Root POA, thereby allowing us to illustrate the most basic object creation and servant registration facilities. Our examples in Chapter 9 do not even use all the features supplied by the Root POA, which itself provides only a small subset of all possible POA features.

The POA specification provides a full suite of features and services intended to allow developers to write scalable, high-performance server applications. Because of this, the POA figures prominently in the ability of application developers to properly control the resources required for implementing CORBA objects and delivering requests to them. Although server applications have a finite amount of memory, CPU power, and network connections available to them, they must appear to provide the best possible service to every client. Thus, understanding POA features and the relationships between them and knowing when to use them are critical to making the trade-offs necessary for creating high-performance server applications.

11.3 POA Fundamentals

In a server application, a POA is responsible for creating object references, activating objects, and dispatching requests made on objects to their respective servants. It is in the POA that the world of CORBA objects intersects the world of programming language

379

IT-SC book: Advanced CORBA® Programming with C++

servants. Therefore, the POA is involved in all aspects of an object's life cycle, from creation to destruction.

Naturally, an object does not exist until it has been created. An object reference always results from creating a CORBA object. Once created, an object can alternate between being activated and being deactivated. While activated, the object is capable of receiving and carrying out requests. To have requests delivered to it, the object must be incarnated, or given bodily form, by a servant. The lifetimes of servants are completely separate from the lifetimes of CORBA objects. A given object is incarnated by only a single servant at any given point in time, but over time, many servant instances can be created to incarnate a single CORBA object. Eventually, each servant is etherealized to break the bond between it and its CORBA object. (To distinguish between servant life cycles and CORBA object life cycles, remember that the terms incarnate and etherealize apply to servants, whereas create and destroy apply to CORBA objects.) Finally, the CORBA object is destroyed, and it returns to the non-existent state. Figure 11.1 shows the life cycle states of CORBA objects and their servants.

Figure 11.1 The states of CORBA object and servant life cycles.

To be useful for the widest possible variety of applications, POAs maintain no persistent state. If a POA were required to keep track of its objects between different executions of a server application, it would require persistent storage. This requirement would greatly hamper deployment of POA-based applications in several ways. For example, it might require ORB vendors either to supply or to require certain databases for use with their ORB products, and those databases might not integrate well with other databases you already employ. Alternatively, the database the ORB vendor chooses might not scale appropriately for the needs of certain applications. For example, it would be impractical,

380

IT-SC book: Advanced CORBA® Programming with C++

if not impossible, to deploy a large-scale relational database on an embedded industrial control sensor.

The POA maintains no persistent state, so it is the responsibility of the application to determine whether, at any point in time, each of its CORBA objects still exists. Ultimately, the application determines the existence of an object by supplying a servant to incarnate the object.

Because of its key role in object creation and request dispatching, the POA plays a critical part in ensuring that CORBA applications can scale and perform well even when handling many thousands of requests for many thousands of CORBA objects. A great deal of the flexibility of the POA in the area of scalability comes from its strong separation between servant lifetimes and CORBA object lifetimes. We discuss servant and CORBA object lifetime issues throughout this chapter and in Chapter 12.

11.3.1 Basic Request Dispatching

Figure 11.2 provides a high-level view of the client and server ORB subsystems involved in dispatching a request. First, the server application somehow exports an object reference for a CORBA object. The client obtains the exported object reference for the object, perhaps via the Naming Service or the Trading Service or by receiving it from another request invocation. As Figure 11.2 shows, the object reference logically "points" to the target CORBA object, much as a C++ pointer points to its underlying C++ object. Underneath the application, the client ORB uses the object reference to determine where the object resides and how to contact it, and then it sends the request to the server ORB. The server ORB receives the request and dispatches it to the POA hosting the target object, and finally the POA continues the dispatch by up-calling the servant that incarnates the target object.

Figure 11.2 ORB subsystems involved in request dispatching.

In Figure 11.2, the arrow between the object reference and the CORBA object represents the logical connection over which the client ORB sends the request, and the

381

IT-SC book: Advanced CORBA® Programming with C++

curved arrow shows the actual request flow. Note the distinction between the CORBA object and the servant; the CORBA object is a "virtual" entity that does not really exist unless incarnated by a servant. We provide many more details concerning the request dispatching process later in this chapter and in Chapter 14.

11.3.2 Key POA Entities

There are three key entities that a POA deals with:

Object references POAs are responsible for creating object references. An application can create new objects, and thus object references, either with or without also creating servants to incarnate the new objects.

Object identifiers Within the scope of its host POA, each object is identified by a sequence of octet called an object identifier. The application can choose whether to supply its own object identifiers or to allow the POA to create them on its behalf. Either way, an object identifier must uniquely identify its object within the scope of its POA. When a POA creates a new CORBA object, it typically embeds the object identifier in the object key portion of the object reference.

Servants An application can create and register servants directly with a POA to incarnate objects. Alternatively, it can supply servant manager objects to the POA that can create servants when needed to carry out a request. An application can even provide a default servant that can carry out all requests directed to a given POA regardless of which object the request is for. Depending on POA policies, a single servant can be registered with a POA to incarnate one or more CORBA objects at any given time.

Many of the tasks that a POA performs require mapping from one of these entities to another. For example, POAs dispatch requests by mapping the object identifier of the target object to the appropriate servant. Another example is the invocation of _this on a servant to implicitly create a new CORBA object and register a servant for it, as we show in Section 9.5. This task requires a POA to be able to map from a servant to the object reference for the object it incarnates.

However, not all POAs can map freely between all these entities. An application controls the capabilities of each POA related to these entities by assigning certain policies to each POA at creation time. We detail these various policies in the next section. Understanding these policies, both separately and in combination, is key to being able to use the POA to build reliable, scalable server applications.

11.4 POA Policies

A key feature of the POA specification is that an application can contain multiple POA instances. Each POA instance represents a grouping of objects that have similar characteristics. These characteristics are controlled via POA policies that are specified when a POA is created. All server applications have at least one POA, the Root POA, which has a standard set of policies.

382

IT-SC book: Advanced CORBA® Programming with C++

Policies are objects that you use to define the characteristics of a POA and the objects created within it. Like the POA and POAManager interfaces, the CORBA specification defines the POA policy interfaces in the standard PortableServer module.

As with all policy interfaces, POA policy types derive from the CORBA::Policy interface.

module CORBA {

typedef unsigned long PolicyType;

interface Policy {

readonly attribute PolicyType policy_type;

Policy copy(); void destroy(); };

typedef sequence<Policy> PolicyList; // ...

};

The Policy interface and its associated types provide basic management operations. The policy_type read-only attribute allows you to determine the actual derived type of a policy through the base Policy interface. PolicyType is a tag value that is controlled by the OMG to ensure that all standard policy types have unique tags.

The copy operation allows you to clone a Policy object. The returned reference refers to a completely new copy of the target Policy object.

The destroy operation allows you to destroy the target Policy object. PolicyList allows you to group references to various derived Policy objects to form sets of policies. The POA creation operation accepts an argument of type PolicyList that allows policies to be set for the new POA. We cover POA creation in detail in Section 11.5.

Policy objects are ocality-constrained objects. This means that even though they look and act just like regular objects, any attempt to pass their references as arguments to normal CORBA operations or to convert them to strings via

ORB::object_to_string will result in a CORBA::MARSHAL exception. Such objects can be accessed only in the context of the local ORB under which they were created.

Some objects are locality-constrained because they supply access to fundamental services such as the ORB or the POA, whereas others are locality-constrained because allowing access to them from remote processes provides no benefit. For example, allowing a process to register a local servant in a remote POA makes no sense because servants are not CORBA objects. A number of POA-related interfaces, including the POA itself, are locality-constrained.

383

IT-SC book: Advanced CORBA® Programming with C++

As we show in the next few sections, all POA policies have the same form: their values are specified using an enumerated type, and all the policy interfaces have a read-only attribute of that enumerated type that can be used to get the policy value.

11.4.1 CORBA Object Life Span

One feature of CORBA that sets it apart from other distributed application development platforms is that it provides transparent and automatic activation of objects. If a client application issues a request to a target object that is currently not running or not activated, the ORB implementation activates a server process for the object if necessary and then activates the object itself. Any activation of server processes and target objects is transparent to the requesting client. (See Chapter 14 for details concerning this transparent object location and activation process.) CORBA objects that can live beyond any particular process in which they are created or activated are called persistent objects. These objects are so named because they persist across the lifetimes of multiple server processes.

Despite the utility of persistent objects, application developers using CORBA before the adoption of the POA discovered that they also required another type of object that had a shorter lifetime. Specifically, they found it valuable to use proprietary extensions provided by several ORB vendors to create objects whose lifetimes were bounded by that of the process or even the object adapter in which they were created. For example, one application might send a reference to one of its objects to another application with the intent of having the second application eventually call it back. However, if the first application exits, it may no longer want the callback information. In that case, it does not want the callback to be delivered, and it does not want the ORB to reactivate the callback object.

As we explain in Chapter 9, the POA supports two types of CORBA objects: the persistent object originally specified by CORBA, and a new shorter-lived object called a transient object. The lifetime of a transient object is bounded by the lifetime of the POA in which it is created. Thus, transient objects are useful in situations requiring temporary objects, such as the callback scenario just described.

One additional benefit of transient objects is that they require less book-keeping by the ORB. After you deactivate the POA used to create a transient object, the object cannot be reactivated. This means that the ORB does not need to keep track of how to locate the object if it is not active when a request is made on it, nor how to activate it within a new server process. This in turn typically means less overhead in administering the CORBA application itself.

A single POA must support either persistent objects or transient objects; it cannot support both. If an object is created using a POA that supports persistent objects, that object will be persistent; otherwise, it will be transient. To support both transient and persistent objects in a single server, the server must have at least two POAs: one for each kind of object. One reason for this, as we explain in Chapter 14, is that persistent objects

384

IT-SC book: Advanced CORBA® Programming with C++

require more support from the ORB infra-structure for location and activation than transient objects. Another reason is that without this distinction, many POA operations would have to come in two flavors—one for persistent objects and one for transient objects—and that would serve only to make the POA interface confusing.

Object life span is controlled via the LifespanPolicy:

module PortableServer {

enum LifespanPolicyValue { TRANSIENT, PERSISTENT

};

interface LifespanPolicy : CORBA::Policy { readonly attribute LifespanPolicyValue value;

}; // ...

};

For the Root POA, the standard life span policy value is TRANSIENT. This implies that any application that needs to support persistent objects must create at least one other POA with the PERSISTENT life span policy. If you do not specify a value for the LifespanPolicy when you create a POA, it defaults to a value of TRANSIENT.

11.4.2 Object Identifiers

A POA identifies each object via its object identifier. Object identifiers are specified using the ObjectId type, which is defined in the PortableServer module as a sequence of octet.

Because it is a sequence of octet, an ObjectId allows virtually any type of data to be used to identify an object. For example, an application that stores the state of each of its objects in a database might use database keys as identifiers. Another application that handles employee records might use some form of employee identifiers to identify its objects. Yet another application might choose to identify its objects using only numbers.

As shown in Figure 11.3, the object identifier is normally stored within the object key portion of the object reference. When we created this object reference, we used the string MyObject as the object identifier. Using strings for object identifiers is common, but because ObjectId is a sequence of octet, almost any data can be used. When a client invokes a request using this object reference, the client ORB uses the object reference to determine the communication endpoints where the target object can be found, and it sends the request there. The client ORB sends the object key from the object reference with the request to identify the target object. The server ORB uses this object key, which it previously created as part of creating the object reference for the target object, to determine which POA in the server hosts the target object. It then redirects the request, including the object key, to that POA. Finally, the POA extracts the ObjectId from the object key, looks up the servant incarnating the target object, and dispatches the request

385

IT-SC book: Advanced CORBA® Programming with C++

to it. See Chapter 14 for more details concerning the binding and request delivery process.

Figure 11.3 Object identifier portion of an object reference.

An application can either choose to explicitly supply its own object identifiers or have the POA create object identifiers for it. Typically, an application that uses persistent objects supplies its own identifiers because it uses them to keep track of where it stores the persistent state of the object. Applications that use transient objects, however, usually let the POA create identifiers for them.

Keep in mind that the main difference between object references and object identifiers is that an object identifier is meaningless outside the scope of the POA in which it names an object. As shown in Figure 11.2, clients use object references, and not object identifiers, to invoke operations. Because object references are opaque, clients cannot extract the object identifier from an object reference, nor can they create an object reference by knowing only the object identifier of the target object.

Note that within the scope of a single POA, all object identifiers must be unique. In other words, two objects created by the same POA cannot have the same ObjectId value. However, the same ObjectId can be used for objects created via different POAs. Each POA enforces the uniqueness of object identifiers. If you use a POA with the SYSTEM_ID policy value, the POA automatically generates unique IDs. If you use a POA with the USER_ID policy value, it prevents duplicate IDs by raising an exception.

Object identification is controlled by the IdAssignmentPolicy:

module PortableServer {

enum IdAssignmentPolicyValue { USER_ID, SYSTEM_ID

};

interface IdAssignmentPolicy : CORBA::Policy { readonly attribute IdAssignmentPolicyValue value;

}; // ...

};

386

IT-SC book: Advanced CORBA® Programming with C++

For the Root POA, the standard object identification policy value is SYSTEM_ID. The Root POA therefore guarantees that it will generate identifiers that are unique for each CORBA object that it creates. SYSTEM_ID is also the default value used for POAs you create without explicitly specifying a value for this policy.

11.4.3 Mapping Objects to Servants

An application that has only a few transient CORBA objects may want to create separate servants for each of those objects and register them with the POA before it starts listening for requests. This approach is especially useful for transient objects whose state is normally stored directly within each servant. By using distinct servants for each object, you can maintain the state of each transient object separately.

At the other end of the spectrum, applications that have many persistent CORBA objects may want to use only one servant to incarnate all of them. For example, an application that provides access to a large database can first create, without servant incarnation, a separate CORBA object representing each database entry and then advertise the object references for the new objects in a Naming or Trading Service. Then, rather than create a servant for each database entry object every time it starts up, the database access application can use a single servant to handle all requests for all database entry objects. Because the state of each object is kept in the database, the servant has no need to keep state of its own.

The separation of servant and CORBA object life cycles (see Figure 11.1) provided by the POA is necessary for scalability. If a servant could incarnate only a single object, server applications hosting many thousands of objects would be difficult to execute because of the required memory resources. Furthermore, if a CORBA object lived only as long as the servant that incarnated it, support for persistent objects, which outlive any single server process, would not be possible.

A POA either allows a single servant to incarnate multiple CORBA objects, or it restricts servants to incarnating only a single object. The mapping of objects to servants is controlled by the IdUniquenessPolicy:

module PortableServer {

enum IdUniquenessPolicyValue { UNIQUE_ID, MULTIPLE_ID

};

interface IdUniquenessPolicy : CORBA::Policy { readonly attribute IdUniquenessPolicyValue value;

}; // ...

};

Figure 11.4 shows how object identifiers are mapped to servants in a POA created with the UNIQUE_ID policy value. When dispatching a request, the POA extracts the

387

IT-SC book: Advanced CORBA® Programming with C++

ObjectId, which is normally embedded in the object reference for the target object, and uses it to look up the servant for the target object in its Active Object Map. Each entry in the Active Object Map consists of an association between an ObjectId and a pointer to a servant. Each POA that retains ObjectId-to-servant associations has its own Active Object Map, as we describe in Section 11.4.6.

Figure 11.4 Mapping object IDs to servants in a UNIQUE_ID POA.

With UNIQUE_ID, the POA enforces the rule that each object identifier must map to a different servant. In a MULTIPLE_ID POA, however, multiple object identifiers can map to a single servant. Figure 11.5 shows multiple Active Object Map entries pointing to the same servant.

Figure 11.5 Mapping object IDs to servants in a MULTIPLE_ID POA.

For the Root POA, the standard object identifier uniqueness policy value is UNIQUE_ID. In other words, the Root POA requires a separate servant to incarnate each object. This is also the default value used for POAs if you create one without explicitly specifying a value for this policy.

11.4.4 Implicit Activation

388

IT-SC book: Advanced CORBA® Programming with C++

When creating a POA, an application can either specify that the new POA allows CORBA objects to be created and activated implicitly or specify that it allows only explicit CORBA object creation and servant registration. Implicit activation is usually performed through a shortcut function supplied by a language mapping, such as the _this function provided by C++ skeleton classes. The CCS server we show in Section

10.11.2 uses implicit activation to create its CCS::Controller object. Implicit activation is controlled via the ImplicitActivationPolicy:

module PortableServer {

enum ImplicitActivationPolicyValue { IMPLICIT_ACTIVATION, NO_IMPLICIT_ACTIVATION

};

interface ImplicitActivationPolicy : CORBA::Policy { readonly attribute ImplicitActivationPolicyValue value;

}; // ...

};

The main reason for controlling whether or not implicit activation is allowed is to prevent the accidental creation of CORBA objects. For example, in Section 9.5 we show how easily the _this function can be used to implicitly create a CORBA object in the Root POA and incarnate it with a servant. Because of the potential for accidental object creation, we suggest that you do not use the IMPLICIT_ACTIVATION value together with the PERSISTENT policy value in the same POA. Implicitly creating transient objects has few ill consequences because they will be automatically cleaned up by the time your server process exits. However, it is best to avoid implicitly creating persistent objects unless you take steps to ensure that they will eventually be properly destroyed.

For the Root POA, the standard implicit activation policy value is IMPLICIT_ACTIVATION. This is the activation policy we use to introduce the _this function in the example in Section 9.5. The ImplicitActivationPolicy defaults to a value of NO_IMPLICIT_ACTIVATION if you do not specify a value when you create a POA.

11.4.5 Matching Requests to Servants

Controlling the associations between objects and servants is a key aspect of server application scalability. Depending on the number of objects an application contains, it might want to use a separate servant for each one, use a single servant for all of them, dynamically supply a servant for each request, or use a combination of these techniques to best manage its resources.

For example, a CORBA application monitoring a sensor might contain only a single object representing the sensor itself. Such an application will most likely explicitly register a servant for the object, thus explicitly activating and incarnating that object.

389

IT-SC book: Advanced CORBA® Programming with C++

Alternatively, an application containing many thousands of objects is unlikely to want to create and register a separate servant for each of its objects. Instead, it may want to incarnate only those objects that actually receive requests. It does this by registering a servant manager with the POA. Servant managers are local objects that are up-called by a POA if it receives an invocation on an object that has no associated servant. Depending upon the POA's value for the IdUniquenessPolicy, the servant manager can either provide the POA with a newly created servant or reuse an existing one. Either way, it returns the servant as the result of the up-call, which the POA uses to complete the request invocation. After the invocation completes, the POA either retains the association of the servant and the CORBA object in its Active Object Map or throws the association away, meaning that the next invocation on the object will again require the services of the servant manager.

Still another alternative is for applications to supply a default servant to a POA. A default servant incarnates all CORBA objects for a POA, avoiding the need to create a separate servant for each object as well as avoiding the invocation overhead associated with servant manager up-calls. Default servants can be useful when all CORBA objects in a given POA support the same IDL interface type.

The matching of requests to servants is controlled via the

RequestProcessingPolicy:

module PortableServer {

enum RequestProcessingPolicyValue { USE_ACTIVE_OBJECT_MAP_ONLY, USE_DEFAULT_SERVANT, USE_SERVANT_MANAGER

};

interface RequestProcessingPolicy : CORBA::Policy { readonly attribute RequestProcessingPolicyValue value;

};

};

For the Root POA, the standard request processing policy value is USE_ACTIVE_OBJECT_MAP_ONLY. This is also the default value used for POAs you create without explicitly specifying a value for this policy.

11.4.6 ObjectId-to-Servant Associations

Except for default servants, a POA either stores associations of objects to servants in its Active Object Map or counts on the application to supply that association each time it attempts to dispatch a request. When a request arrives, a POA that retains its object-to- servant associations can simply use the ObjectId of the target object as an index into its Active Object Map to look up the servant that should process the request. (We illustrate this lookup process in Figure 11.4.) If, however, a POA does not retain object-to-servant associations, it must rely on the application to supply them instead. It

390

IT-SC book: Advanced CORBA® Programming with C++

does this either by calling out to an application-supplied servant manager object when it needs a servant or by relying on the application to supply a default servant.

Controlling the retention of servants is an important aspect of server application memory usage. For example, an application that has many thousands of objects will likely avoid retaining object-to-servant associations in the POA's Active Object Map because of the amount of memory all those associations would require. Instead, the application may register a servant manager object to supply object-to-servant associations to the POA when it requests them, thus buying decreased memory consumption at the cost of a slight increase in request processing overhead due to servant manager invocation.

Servant retention is controlled by the ServantRetentionPolicy:

module PortableServer {

enum ServantRetentionPolicyValue { RETAIN, NON_RETAIN

};

interface ServantRetentionPolicy : CORBA::Policy { readonly attribute ServantRetentionPolicyValue value;

}; // ...

};

For the Root POA, the standard servant retention policy value is RETAIN. This is also the default value used for POAs you create without explicitly specifying a value for this policy.

11.4.7 Allocation of Requests to Threads

It is common for server applications to use multiple threads to service multiple requests concurrently. An application can service each new request in a separate newly created thread, or it can handle all requests for a given object in a separate thread. Or it can employ a fixed-size pool of threads to handle all requests, queuing requests if all threads in the pool are busy. The appropriate threading strategy for an application depends on a number of factors, including the number of objects hosted by the application, the expected request rate, and the multi-threading support provided by the underlying operating system.

An application can create a POA with one of two different threading models. The ORBcontrolled model allows the underlying ORB implementation to choose an appropriate multithreading model, whereas the single-thread model guarantees that all requests for all objects in that POA will be dispatched sequentially.

The ORB-controlled model allows multiple concurrent requests to be processed by multiple threads. Applications using POAs created for this model must be implemented to properly handle reentrant invocations and concurrency because servants registered with such a POA may be required to process multiple CORBA requests simultaneously.

391

IT-SC book: Advanced CORBA® Programming with C++

Servants implemented for single-thread model POAs need not be thread-aware. You can use the sequential request dispatch provided by a single-threaded POA to advantage when integrating existing code not designed for use in a multi-threaded environment.

One key aspect of the single-threaded POA threading model is that it is independent of whether the application uses multiple threads. For example, a multi-threaded application may contain multiple POAs, some of which have the ORB-controlled thread policy and others that are single-threaded. Regardless of whether the application uses multiple threads, all of its single-threaded POAs deliver their requests sequentially. This means that the application as a whole might be multithreaded, with each single-threaded POA running in its own thread. Therefore, depending on your ORB implementation, you may have to take concurrency into account when sharing servants between POAs even when each POA is single-threaded.

Although these POA multithreading models are a vast improvement over the complete lack of multithreading support of CORBA before the introduction of the POA (in CORBA version 2.2), they could be made even more flexible. Specifically, rather than just supply the ORB-controlled model, the POA could provide for finer-grained control over multithreading policies by allowing applications to use policies to specify precise models such as a thread pool model, a thread-per-request model, or a thread-per-object model. Future standard extensions to the POA specification may indeed supply applications with this much-needed flexibility.

The allocation of requests to threads is controlled by the ThreadPolicy:

module PortableServer { enum ThreadPolicyValue {

ORB_CTRL_MODEL, SINGLE_THREAD_MODEL

};

interface ThreadPolicy : CORBA::Policy { readonly attribute ThreadPolicyValue value;

}; // ...

};

For the Root POA, the standard threading policy value is ORB_CTRL_MODEL. This is also the default value used for POAs you create without explicitly specifying a value for this policy.

11.4.8 Policy Factory Operations

You create policies by invoking policy factory operations on a POA. The POA interface supplies a separate factory operation for each of the policy types:

module PortableServer { interface POA {

LifespanPolicy create_lifespan_policy(

392