VisiBroker for C++ Developer’s Guide : Using the tie mechanism

Using the tie mechanism
This section describes how the tie mechanism may be used to integrate existing C++ code into a distributed object system. This section will enable you to create a delegation implementation or to provide implementation inheritance.
How does the tie mechanism work?
Object implementation classes normally inherit from a servant class generated by the idl2cpp compiler. The servant class, in turn, inherits from PortableServer.Servant::Servant. When it is not convenient or possible to alter existing classes to inherit from the VisiBroker servant class, the tie mechanism offers an attractive alternative.
The tie mechanism provides object servers with a delegator implementation class that inherits from PortableServer::Servant. The delegator implementation does not provide any semantics of its own. The delegator implementation simply delegates every request it receives to the real implementation class, which can be implemented separately. The real implementation class is not required to inherit from PortableServer::Servant.
With using the tie mechanism, two additional files are generated from the IDL compiler:
<interface_name>POATie defers implementation of all IDL defined methods to a delegate. The delegate implements the interface <interface_name>Operations. Legacy implementations can be trivially extended to implement the operations interface and in turn delegate to the real implementation.
<interface_name>Operations defines all of the methods that must be implemented by the object implementation. This interface acts as the delegate object for the associated <interface_name>POATie class when the tie mechanism is used.
Example program
Location of an example program using the tie mechanism
A version of the Bank example using the tie mechanism can be found in:
<install_dir>\vbe\examples\basic\bank_tie
Looking at the tie template
The idl2cpp compiler will automatically generate a _tie_Account template class, as shown in the code sample below. The POA_Bank_Account_tie class is instantiated by the object server and initialized with an instance of AccountImpl. The POA_Bank_Account_tie class delegates every operation request it receives to AccountImpl, the real implementation class. In this example, the class AccountImpl does not inherit from the POA_Bank::Account class.
...
template <class T> class POA_Bank_Account_tie :
public POA_Bank::Account {
private:
CORBA::Boolean _rel;
PortableServer::POA_ptr _poa;
T *_ptr;
POA_Bank_Account_tie(const POA_Bank_Account_tie&) {}
void operator=(const POA_Bank_Account_tie&) {}
public:
POA_Bank_Account_tie (T& t): _ptr(&t), _poa(NULL),
_rel((CORBA::Boolean)0) {}
POA_Bank_Account_tie (T& t,
PortableServer::POA_ptr poa): _ptr(&t),
_poa(PortableServer::_duplicate(poa)), _rel((CORBA::Boolean)0) {}
POA_Bank_Account_tie (T *p, CORBA::Boolean release= 1) : _ptr(p),
_poa(NULL), _rel(release) {}
POA_Bank_Account_tie (T *p, PortableServer::POA_ptr poa,
CORBA::Boolean release =1): _ptr(p),
_poa(PortableServer::_duplicate(poa)), _rel(release) {}
virtual ~POA_Bank_Account_tie() {
CORBA::release(_poa);
if (_rel) {
delete _ptr;
}
}
T* _tied_object() { return _ptr; }
void _tied_object(T& t) {
if (_rel) {
delete _ptr;
}
_ptr = &t;
_rel = 0;
}
void _tied_object(T *p, CORBA::Boolean release=1) {
if (_rel) {
delete _ptr;
}
_ptr = p;
_rel = release;
}
CORBA::Boolean _is_owner() { return _rel; }
void _is_owner(CORBA::Boolean b) { _rel = b; }
CORBA::Float balance() {
return _ptr->balance();
}
PortableServer::POA_ptr _default_POA() {
if ( !CORBA::is_nil(_poa) ) {
return _poa;
} else {
return PortableServer_ServantBase::_default_POA();
}
}
};
Changing the server to use the _tie_account class
The code sample below shows the modifications to the Server.C file required to use the _tie_account class.
#include "Bank_s.hh"
#include <math.h>
. . .
int main(int argc, char* const* argv) {
try {
// Initialize the ORB.
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
// get a reference to the root POA
PortableServer::POA_var rootPOA = PortableServer::POA::_narrow(
orb->resolve_initial_references("RootPOA"));
CORBA::PolicyList policies;
policies.length(1);
policies[(CORBA::ULong)0] = rootPOA->create_lifespan_policy(
PortableServer::PERSISTENT);
// get the POA Manager
PortableServer::POAManager_var poa_manager =
rootPOA->the_POAManager();
// Create myPOA with the right policies
PortableServer::POA_var myPOA = rootPOA->create_POA(
"bank_agent_poa", poa_manager, policies);
// Create the servant
AccountManagerImpl managerServant(rootPOA);
// Create the delegator
POA_Bank_AccountManager_tie<AccountManagerImpl>
tieServer(managerServant);
// Decide on the ID for the servant
PortableServer::ObjectId_var managerId =
PortableServer::string_to_ObjectId("BankManager");
// Activate the servant with the ID on myPOA
myPOA->activate_object_with_id(managerId, &tieServer);

// Activate the POA Manager
poa_manager->activate();
cout << myPOA->servant_to_reference(&tieServer) << " is ready" << endl;
// Wait for incoming requests
orb->run();
} catch(const CORBA::Exception& e) {
cerr << e << endl;
return 1;
}
return 0;
}
Building the tie example
The instructions described in “Developing an example application with VisiBroker” are also valid for building the tie example.