Archived

This forum has been archived. Please start a new discussion on GitHub.

Difference between: IceUtil::Handle<> and IceInternal::Handle<>

Hi,

What's the difference between a IceUtil::Handle<> and IceInternal::Handle<> ?

The slice code generator seems to be be generating IceInternal::Handle<> typedefs for the interfaces defined in slice files.

When does one use each class? And what's the use for each?

For example, for one's own implementation of slice interfaces, which one should be used?

I am asking this, because I have defined a factory object in slice and the implementation class for the factory also derives from Ice::ServantLocator (which is a local interface - maybe inheriting from slice (remotable) interfaces and local interfaces at the same time is a no no?).
Now when I tried using IceUtil::Handle for this implementation class I kept getting a compiler error (Using BC++ 2006: [C++ Error] Handle.h(148): E2014 Member is ambiguous: 'IceInternal::GCShared::__incRef' and 'Shared::__incRef'), despite using virtual inheritance everywhere.
If I change to using IceInternal::Handle (and implementing the right incRef and decRef functions for MyClass*) the compiler was satisfied. But I am in the blind if I'm doing the right thing or not. This in particular is because I do not know which base object's __incRef/__decRef to call within the global incRef and decRef functions as below:


namespace IceInternal
{


void
IceInternal::incRef(MyClass* p)
{
//should this be called:
((Ice::Object*)p)->__incRef();

//or this:
//((Ice::ServantLocator*)p)->__incRef();
}

void
IceInternal::decRef(MyClass* p)
{
//should this be called?
((Ice::Object*)p)->__decRef();

//or this:
((Ice::ServantLocator*)p)->__decRef();
}

}

Any pointers?
Tks - Adrian.

Comments

  • bernard
    bernard Jupiter, FL
    Hi Adrian,

    The problem is that you're inheriting from the generated class for a distributed Slice interface/class, and also from the generated class for a local interface. Currently, this does not work, at the ref-counting bases classes are unrelated and incompatible (IceInternal::GCShared and IceUtil::Shared).

    In general, IceUtil::Handle and IceInternal::Handle are very similar. The main difference is that IceUtil::Handle needs to see the full declaration of its parameter, while you can use a forward declared-class and a couple global functions with IceInternal::Handle.

    Also, IceUtil classes are part of the Ice public API, while IceInternal classes aren't; whenever possible, I recommend to use only our public API.

    Cheers,
    Bernard
  • You may also want to read "Who's Counting?" in Issue 25 of Connections. That article discusses smart pointers in quite some detail.

    Cheers,

    Michi.
  • Hi Michi,

    Thanks for pointing me to that article. Most useful.

    - Adrian.
  • Hi Bernard,

    bernard wrote: »
    Hi Adrian,

    The problem is that you're inheriting from the generated class for a distributed Slice interface/class, and also from the generated class for a local interface. Currently, this does not work, at the ref-counting bases classes are unrelated and incompatible (IceInternal::GCShared and IceUtil::Shared).

    In general, IceUtil::Handle and IceInternal::Handle are very similar. The main difference is that IceUtil::Handle needs to see the full declaration of its parameter, while you can use a forward declared-class and a couple global functions with IceInternal::Handle.

    Also, IceUtil classes are part of the Ice public API, while IceInternal classes aren't; whenever possible, I recommend to use only our public API.

    Cheers,
    Bernard


    Thanks for you answer. That clarified a few things. I'll be using IceUtil::Handle for my classes from now on.

    One other question on this...

    As I said, I have a factory class defined in slice which also inherits from Ice::ServantLocator because this implements the evictor pattern. This has caused the problem I mentioned in my original post.

    Now, I can restructure things so that I remove this inheritance and have an encapsulated class that inherits from ServantLocator and implements the evictor pattern within the Factory class, but having the Factory class inherit from and implement ServantLocator seems to be a very viable and natural thing to do design wise (humbly, I stand to be corrected). If I had to proceed so, a possible workaround would be to implement __incRef and __decRef in my own Factory class and have those methods call the relevant inherited functions from the slice defined bass class - effectively decoupling the ServantLocator reference mechanism as below:

    class MyFactoryI : virtual public MyFactory, //MyFactory is defined in slice
    virtual public Ice::ServantLocator
    {
    public:

    //.............other stuff

    MyFactoryI() {
    Ice::ServantLocator::__incRef();

    //note the call above to increment the ref count in Ice::ServantLocator 'context'
    //so that Ice::ServantLocator's refcount never gets to zero
    //and hence the destructor for this class (MyFactoryI) is never called
    //in Ice::ServantLocator ref counting context
    }

    void __incRef() {
    MyFactory::_incRef();
    }

    void __decRef() {
    MyFactory::_decRef();
    }
    };
    typedef IceUtil::Handle<MyFactoryI> MyFactoryIPtr;


    That should work no? (see the note in MyFactory constructor regarding calling ServantLocator::__incRef). That way, all reference counting done via MyFactoryIPtr would effectively only be using the slice defined class' ref counting and not Ice::ServantLocator's (or to be more correct I guess, Ice::ServantLocatorPtr's) no? And the call in the constructor to Ice::ServantLocator::__incRef would ensure that the ref count in Ice::ServantLocator never gets to zero.

    This seems like a solution to me, but if you still recommend me restructuring things so that I avoid the above mentioned inheritance model, I'd proceed to do so.

    Any comments would be very much appreciated.

    Tks - Adrian.
  • bernard
    bernard Jupiter, FL
    Hi Adrian,

    I recommend to split your class and avoid this multiple inheritance: I am sure it's easy and this will simplify your code.

    Your work-around may work, but it's not worth the complexity -- now and in the future when you or somebody reads this code and tries to understand what it's all about.

    Cheers
    Bernard