[omniORB] Comparing object references

Duncan Grisby dgrisby@uk.research.att.com
Fri, 01 Jun 2001 14:37:01 +0100


On Thursday 31 May, Kevin Bailey wrote:

> I would like to compare object references but, according to H&V,
> I can't. Two references may claim to be unequal, using either
> _is_equivalent() or object_to_string(), even when they refer to
> the same object.

This is true.

[...]
> Given an object reference, will _duplicates() of it compare
> equal via _is_equivalent() if the original and all duplicates
> are within the same process ?

Yes.

> Given an object reference, will object_to_string() ever return
> different values for it at different times in the same process ?

It can do. The stringified object reference is a hex version of the
data used to transmit an IOR. Some of the values in the IOR have
padding separating them for alignment purposes. Since the contents of
the padding are not specified, and are not explicitly set in the
marshalling process, stringified versions of the same IOR may differ
in their pad bytes. IORs also depend on the byte order of the machine
which creates them.

You should never ever compare object references by looking at the
stringified versions of them.

> Will copies of an object reference repeatedly pulled out of a
> name server into the same process ever return not
> _is_equivalent() ?

It's possible for that to happen too. If you just do

  ref1 = ns->resolve(name);
  ref2 = ns->resolve(name2);
  if (ref1->_is_equivalent(ref2)) ...

then I think you'll be OK with the current implementation. However, if
you invoke an operation on ref1 before calling _is_equivalent(), you
might find that it returns false. This is because the invocation may
have resulted in a location forward, causing ref1 to refer to a
different object internally.

The only solution if you reliably need to compare object references is
to have an operation in your interface which allows you to do a remote
test for equivalence. One solution is to assign all your objects a
unique id:

  typedef octet UUID[16];

  interface Identifiable {
    readonly attribute UUID uu_id;
  };

Then you can compare two object references based on their uuids. That
approach has the disadvantage that it requires two remote calls, one
to each object.

The alternative is to have a query operation:

  interface Comparable {
    boolean is_identical(in Comparable o);
  };

Then, you can do ref1->is_identical(ref2). The way to implement the
operation is to use poa->reference_to_servant:

  CORBA::Boolean Comparable_i::is_identical(Comparable_ptr o) {
    try {
      PortableServer::Servant s = my_poa->reference_to_servant(o);
      if (s == (PortableServer::Servant)this)
        return 1;
    }
    catch (PortableServer::POA::ObjectNotActive&) { }
    catch (PortableServer::POA::WrongAdapter&) { }
    catch (PortableServer::POA::WrongPolicy&) { }
    return 0;
  }


Cheers,

Duncan.

-- 
 -- Duncan Grisby  \  Research Engineer  --
  -- AT&T Laboratories Cambridge          --
   -- http://www.uk.research.att.com/~dpg1 --