[omniORB] From COM to CORBA...
Duncan Grisby
dgrisby@uk.research.att.com
Fri, 16 Feb 2001 16:55:57 +0000
On Tuesday 13 February, "Len Holgate \(Mail List Account\)" wrote:
> I'm a COM guy at heart, but recently I've been doing some stuff with
> OmniORB. It's pretty cool, but I found that my COM oriented designs were
> pretty hard to do in CORBA, so I sat down and worked through the pain... The
> first part of the results can be found at
> http://www.jetbyte.com/Source/Corba/corba.htm. It's mostly "I miss my
> reference counting" and "sequences suck" kinda stuff, but be gentle...
> Constructive criticism welcome... If what I'm doing is wrong, or stupid,
> please let me know, I like to learn!
I don't want to sound rude, but the impression I get from reading your
articles is that you have started trying to learn about CORBA from the
wrong viewpoint. You have taken your knowledge of some very specific
low-level concepts in COM, and tried to directly map those concepts to
CORBA. I think that that approach will only lead to awkward and
inefficient CORBA designs. Also, the problems with your early
refcounting examples stem from a basic lack of knowledge about how
CORBA manages servant life-times, rather than from any difference
between COM and CORBA.
>From a million miles away, COM and CORBA look pretty similar, but you
don't have to look much closer before you see some very significant
differences. The differences start with the high-level view of the
object model. In starting to learn about CORBA by concentrating on the
very lowest levels, you have obscured your view of the fundamental
differences higher up in the system.
To look at your specific examples, the issue of reference counting is
strongly tied to the differences between COM and CORBA's object
models. In CORBA, reference counting is only one of many schemes which
can be used to manage objects' life-cycles. In many circumstances,
there are much better schemes to use. Coming from the COM perspective
that everything is reference counted can prevent you from seeing
simpler and better alternatives.
Of course, reference counting is sometimes the best thing to use. In
that case, the conventional CORBA way would be to use interface
inheritance:
interface RefCounted {
void addRef();
void removeRef();
};
interface MyRefCountedObject : RefCounted { ... };
interface AnotherRefCountedObject : RefCounted { ... };
The important thing to realise here is that your implementation code
can also use inheritance to avoid replicating the refcounting code.
Something like this: (All this code is untested, so there are probably
some mistakes...)
class RefCounted_i : public virtual POA_RefCounted,
public virtual PortableServer::RefCountServantBase {
public:
RefCounted_i(PortableServer::POA_ptr poa) : count_(1) {
poa_ = PortableServer::POA::_duplicate(poa);
}
void addRef() {
omni_mutex_lock l(guard_);
++count_;
}
void removeRef() {
omni_mutex_lock l(guard_);
if (--count_ == 0) {
PortableServer::ObjectId_var id = poa_->servant_to_id(this);
poa_->deactivate_object(id);
}
}
private:
omni_mutex guard_;
unsigned count_;
PortableServer::POA_var poa_;
};
Now you can declare your other servant classes like
class MyRefCountedObject_i : public virtual POA_MyRefCountedObject,
public virtual RefCounted_i
{
...
};
However, all of this misses the fundamental difficulty with reference
counting, which is how to deal with misbehaved clients. Coming from a
COM perspective it's easy to ignore, since COM goes to great pains to
hide the problem. (Actually, with COM it isn't hard -- it's DCOM that
has a hard problem to solve.) Sometimes hiding it is a good thing;
other times, it can be problematic.
Imagine that a client on machine A holds a (reference counted)
reference to an object on machine B. Machine A now crashes. How can
the object on B find this out? How about the case that the network
joining A and B breaks temporarily, but comes back later? Should the
object be deleted then? What if A maliciously keeps creating new
objects and holding reference counts to them?
The normal solution (and what DCOM does) is to use some sort of
pinging mechanism, so the server can know that the client is still
alive. That doesn't cope at all well with network failures, though.
You also have to be very careful not to drown under pings if you have
a lot of clients. It all comes down to what you want the semantics of
your application to be, and there are no easy answers.
Iterators (or enumerators if you want to use the COM term) are a good
example of where a pattern other than reference counting can be
useful. A simple timeout or evictor pattern (as described by Henning &
Vinoski) is probably more suitable.
My recommendation is that you resist the temptation to map your COM
knowledge onto CORBA. Learn CORBA as a whole new thing, starting with
the CORBA object model and its approach to system architecture. Then
as you approach the low-level details, you will be able to see the
differences between COM and CORBA in a more productive light.
Cheers,
Duncan.
--
-- Duncan Grisby \ Research Engineer --
-- AT&T Laboratories Cambridge --
-- http://www.uk.research.att.com/~dpg1 --