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

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

result->s_mem = obj->string_op();

// No exceptions occured -- return. vls_out = temp_out._retn();

return result._retn();

}

Notice the lack of any try or catch blocks in the revised example. As described in Section 9.7.5, you can use _var types within a servant method to manage dynamically allocated instances until they are ready to return to the caller. In this modified example, we first use a Vls_var to temporarily store what will become the out parameter, initializing it as before. We then do the same for the return value. If the second call to string_op (used to initialize the string in the result structure) were to throw an exception, the C++ run time would invoke the destructor for the temp_out instance, which would free the dynamically allocated out parameter. If no exception occurs, we use the _retn function on the temp_out variable to take ownership of the out value and assign it to the vls_out parameter, and we then use _retn on the result variable to set up the return value.

Overall, it can be difficult to write error-free code that properly deals with exceptions. Using _var types to hold pointers to dynamically allocated instances that can later be taken away using the _retn function helps you ensure that your servant methods do not leak the resources they acquire.

9.9 Tie Classes

In general, skeletons are an implementation of the Adapter pattern documented in [4]. The skeleton classes we describe in Section 9.3 rely on inheritance to adapt servant class interfaces to the request-dispatching interfaces expected by the ORB and the POA. Using inheritance in this fashion is a realization of the class form of the Adapter pattern.

In this chapter we have used only skeletons that realize the class form of the Adapter pattern. For completeness, we must also point out that servant classes that provide the other form of the Adapter pattern, called the object form, can also be generated by IDL compilers. Such automatically generated servant classes are called tie classes. In this section we briefly explain tie classes, describe how you can use them to incarnate CORBA objects, and then evaluate their usefulness.

9.9.1 Details of Tie Classes

A tie class is a C++ class template that you can instantiate to create a concrete servant. A tie-based servant implements all methods by delegating them to another C++ object. The tie class for our MyObject interface, originally defined in Section 9.3, the IDL compiler generates the following class definition.

template<class T>

341

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

class POA_MyObject_tie : public POA_MyObject { public:

// Constructors and destructor. POA_MyObject_tie(T & tied_object); POA_MyObject_tie(

T &

tied_object,

PortableServer::POA_ptr poa

);

POA_MyObject_tie(T * tied_object, CORBA::Booleanrelease = 1);

POA_MyObject_tie(

tied_object,

T *

PortableServer::POA_ptr poa,

CORBA::Boolean

release = 1

);

 

~POA_MyObject_tie();

 

// Functions to set

and get tied object.

T * _tied_object()

{ return m_tied_object; }

void _tied_object(T

& obj);

void _tied_object(T

* obj, CORBA::Boolean release = 1);

// Functions to set

and check tied object ownership.

CORBA::Boolean

_is_owner();

void

_is_owner(CORBA::Boolean b);

// Override IDL methods. virtual CORBA::Long get_value()

throw(CORBA::SystemException);

// Override PortableServer::ServantBase operations. PortableServer::POA_ptr

_default_POA();

private:

// Pointer to tied object.

T *

m_tied_object;

CORBA::Boolean

m_owner;

PortableServer::POA_var m_poa;

// copy and assignment not allowed POA_MyObject_tie(const POA_MyObject_tie &); void operator=(const POA_MyObject_tie &);

};

The tie class template looks more complicated than it really is. To use a tie class, follow these steps.

Step 1.

Instantiate the template with a class type that supplies a get_value member function.

Step 2.

Create an instance of the instantiated tie template, passing its constructor a pointer or reference to an instance of the template parameter class type. This template parameter class type instance is called the tied object because it is "tied" into the tie instance.

Step 3.

342

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

Register the tie instance with the POA as a servant for a CORBA object.

When the POA invokes the tie servant's get_value method to carry out a request, the tie servant merely delegates the invocation to its tied object, as shown here:

template<class T> CORBA::Long POA_MyObject_tie<T>::

get_value() throw(CORBA::SystemException)

{

return m_tied_object->get_value();

}

The rest of the member functions of the tie class template serve to set or get the tied object and help with managing its memory.

9.9.2 Incarnation with Tie Servants

To create a transient CORBA object using a tie servant, you can invoke _this on the tie instance, just as with any other servant. However, you must ensure that before it receives any requests, the tie servant has a tied object to which it can delegate those requests.

When you register a tied object with a tie instance for delegation—using either a tie class constructor or via the _tied_object modifier function— you have two memory management options.

Step 1.

You can maintain ownership of the tied object yourself.

Step 2.

You can pass a true value for the release parameter of the appropriate constructor or of the _tied_object modifier function. The tie instance will adopt the tied object and call delete on it in its destructor.

In the following example we show how to use a tied object and a tie instance together to implement a servant. We first create the tied object and then pass a pointer to it to the tie constructor. In this example we have decided to allocate the tied object on the heap and have the tie servant adopt it. We then invoke _this on the tie servant to create a new CORBA object and register the tie servant as its implementation, as with the preceding example.

//Create a C++ class instance to be our tied object.

//Assume MyLegacyClass also supports the get_value() method. MyLegacyClass * tied_object = new MyLegacyClass;

//Create an instance of the tie class template, using

//MyLegacyClass as the template parameter. Pass our tied_object

//pointer to set the tied object. The release parameter defaults

//to true, so the tie_servant adopts the tied_object.

POA_MyObject_tie<MyLegacyClass> tie_servant(tied_object);

// Create our object and register our tie_servant as its servant.

343

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

MyObject_var my_object = tie_servant._this();

As indicated in this example, it is the tie instance, and not the tied object, that is the servant that you register with the POA.

9.9.3 Evaluation of Tie Classes

Historically, tie classes have been touted as a way to integrate existing C++ class hierarchies into CORBA applications. This claim is based on the fact that the classes of the tied objects, unlike servant classes, need not inherit from any skeleton classes. However, this claim is questionable because a tie servant assumes that its tied object supports exactly the same IDL methods it does, all with the same signatures and exception specifications. This assumption is therefore not very likely to be true for any legacy software that you designed and implemented without regard for CORBA.

One alternative for integrating tied object classes when they do not support the necessary methods or correct function signatures is to use template specialization. If a given tied object class for the POA_MyObject_tie does not provide a get_value member function, you can specialize the POA_MyObject_tie<T>::get_value method to supply your own delegating implementation. For example, assume that our tied object class, MyLegacyClass, provides a member function named counter_value that returns an unsigned short:

#ifndef LEGACY_H_ #define LEGACY_H_

class MyLegacyClass

{

public:

unsigned short counter_value(); // ...

};

#endif

We can specialize the POA_MyObject_tie<T>::get_value method instantiation for MyLegacyClass to instead call counter_value.

#include "legacy.h" #include "my_objectS.hh"

template<>

CORBA::Long POA_MyObject_tie<MyLegacyClass>:: get_value() throw(CORBA::SystemException)

{

return _tied_object()->counter_value();

}

344