Page #116 (Just-in-Time (JIT) Activation)

< BACK  NEXT >
[oR]

Object Pooling

The concept of object pooling is simple. Using the Component Services snap-in, the administrator marks a component as pooled. The relevant property page for the component is shown earlier in Figure 11.4. When the COM+ application containing the component is first activated, COM+ creates a bunch of objects (the exact number is specified as the minimum pool size) and holds them in a pool. When a client creates an object, by calling CoCreateInstance, for example, COM+ first checks the pool to see if the object of the specified type is available. If so, COM+ activates the object from the pool instead of creating a new one. If the object is not available, COM+ will create a new one, up to the maximum specified size of the pool. When the object is released, either through a direct client request or as a result of the JIT deactivate-on-return bit set, the object goes back to the pool for reuse.

If all the objects up to the maximum specified limit are already in use when a new object creation request comes in, COM+ waits for a specified timeout interval (configurable through the Component Services snap-in) to see if any of the used objects become available for reuse. If not, the object creation fails with the error, CO_E_ACTIVATIONFAILED_TIMEOUT.

Note that so far in this chapter, and at many places in the earlier chapters, we deliberately chose the words object activation and deactivation, as opposed to object creation and destruction. The semantic difference between the two should now become clear. When an object is activated, it either gets created or fetched from a pool of existing objects. When an object is deactivated, it either gets destroyed or placed back in the pool.

When an object is being deactivated, it needs a way to know this so that it can release its resources. Likewise, an object needs to know when it is being activated so that it can initialize its state. To accomplish this, COM defines a standard interface, IObjectControl. The following is its definition:

 IObjectControl : IUnknown  {   HRESULT Activate();    void Deactivate();    BOOL CanBePooled();  }; 

Any coclass whose objects are interested in receiving activation and deactivation notifications should support IObjectControl.

graphics/01icon02.gif

Implementing IObjectControl is not mandatory for object pooling. Implement it only if you wish to receive activation and deactivation notifications.


When an object is being activated, COM+ queries the object for the IObjectControl interface and calls its Activate method before handing the object over to the client. This gives the object a chance to do any necessary initialization.

graphics/01icon02.gif

When an Activate call comes in, you can obtain a reference to the object s context object and store it as a member variable. This way, you don t have to acquire the context object each time you want to use it.


The Activate method can also be used to obtain the security credentials of the caller (see Chapter 7) and either allow or deny access to the caller.

When the object is being deactivated, COM+ calls the Deactivate method. This is the object s chance to perform whatever cleanup is necessary, such as releasing any held resources, before it is destroyed or recycled.

graphics/01icon02.gif

If you are holding the context object as a member variable, do not forget to release it when Deactivate is called.


Immediately after calling Deactivate, COM+ calls the CanBePooled method on the object to check if the object is willing to be pooled for reuse. If the object returns FALSE, COM+ destroys the object. Otherwise, COM+ places (or may place) the object back into the pool.

Note that returning TRUE from CanBePooled does not guarantee that the object will be recycled; it only gives COM+ the permission to recycle it. Returning FALSE, however, guarantees that the object will be destroyed.

Requirements for Poolable Objects

With object pooling, a specific instance of a poolable object can be used by multiple clients. In order to work properly with multiple clients, poolable objects have to meet certain requirements.

Stateless

To maintain security, consistency, as well as isolation, poolable objects must not hold any client-specific state from one client to another. Otherwise, for example, a resource opened with the security token of one client may inadvertently get used with another client. Therefore, a per-client state should be managed using IContextControl, performing client-specific context initialization with Activate, and cleaning up any client state with Deactivate.

No Thread Affinity

It is possible that a poolable object gets created on one thread (at startup time) but gets activated on another thread (when it is taken from the pool and connected to the client). Therefore, the object should be designed so that it doesn t care which thread it receives calls on. This means the object must live in either an MTA or neutral apartment, which implies the component cannot be marked with ThreadingModel=Apartment. [1] In addition, poolable objects should not use thread local storage (TLS), nor should they aggregate the FTM (see Chapter 5).

[1] Though ThreadingModel=both is supported, the Apartment part of the threading model never gets used. The objects are always created from an MTA thread.

Aggregatable

When COM+ activates a pooled object, it aggregates the actual object to manage its lifetime. Therefore, the object implementation should support aggregation. This is not such a terrible problem as the code generated by the ATL wizard supports aggregation by default.

Transactional Components

Poolable objects that participate in transactions must turn off the automatic enlistment of managed resources (Chapter 8). The transactional resources must be enlisted manually. Otherwise, if an object holds managed resources between clients, there will be no way for the resource manager to automatically enlist in a transaction when the object is activated in a given context.

Note that this is not an issue if the managed resource gets loaded when Activate is called. However, for performance optimization, many components load the managed resource during the construction phase of the object. Such components should add the logic to disable automatic enlistment of the managed resource during the construction phase and enable it each time Activate is called.

The steps for automatic or manual enlistment of a managed resource are very specific to the resource manager of the resource in question. You should consult the documentation for your resource manager. See the MSDN article, COM+ Technical Series: Object Pooling, [MSDN-00] for a code example on manually enlisting an ODBC resource.

COM+ treats transactional objects in a special way when they are pooled. Generally, when a client requests a pooled object, COM+ may fetch any object from the available pool. However, for transactional objects, COM+ uses a different algorithm. It scans the pool for an available object that is already associated with the current transaction. If an object with the transaction affinity is found, it is returned to the client; otherwise, an object from the general pool is returned. When the object with the transaction affinity is used, the object must have already enlisted its resources. Therefore, before enlisting a resource, you should first check for transaction affinity and enlist the resource only if the object was fetched from the general pool.


< BACK  NEXT >


COM+ Programming. A Practical Guide Using Visual C++ and ATL
COM+ Programming. A Practical Guide Using Visual C++ and ATL
ISBN: 130886742
EAN: N/A
Year: 2000
Pages: 129

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net