Archived

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

Error in Section 6.15.5 of the User Manual

Hi,

The User Manual v3.4.0, Section 6.15.5 contains a puzzling sentence: "Note how this code creates two instances of type Callback_Employees_getNamePtr".

However, the code that this refers to does not seem to do this (it does create a single Callback_Employees_getNamePtr and a single Callback_Employees_getNumberPtr).

Regards, Sidney

Comments

  • mes
    mes California
    Thanks Sidney, we'll correct this in the next release.

    Regards,
    Mark
  • Great!

    It would also be helpful to update the documentation to show that it is possible to provide a naked T* to the newCallback() functions -- both in the generic and type-safe interface.

    I was very happy to find that you defined this, since this makes it possible to define the callback functions as member functions of the class that does the begin_call(), without having to define a separate Callback class.

    In general, the use of IceUtil::Handle<T> across the API is inconvenient in places where one would like to use a naked T* pointer (i.e., where you don't want to abdicate responsibility for delete()ing the object pointed to, for example when you only have "this" available). In the case of specifying callbacks you did provide a method overload that takes a dumb pointer, but I wonder if this was done in other places in the API as well?
  • mes
    mes California
    Hi,

    A callback object (the first argument to the newCallback_XXX function) must always be an instance of a class derived from IceUtil::Shared, and therefore is a reference-counted object. As such, you must not delete this object manually. The overload that accepts a naked pointer is generated simply as a convenience. Without this overload, you would be forced to always pass a smart pointer, as shown below:
    MyCallbackPtr cb =  new MyCallback;
    Callback_Hello_sayHelloPtr c = newCallback(cb, ...);
    
    The overload allows the caller to pass an argument such as this (assuming this is an instance of IceUtil::Shared) or new MyCallback instead; note however that these arguments are used to construct smart pointers.

    Ice's smart pointer API makes it possible for you to pass a pointer to a reference-counted object where a smart pointer is expected, causing the compiler to instantiate a temporary smart pointer when necessary. In the case of the newCallback_XXX template function, however, the compiler isn't clever enough to do this on its own so we had to generate the extra overload.

    I hope that's a little clearer.

    Regards,
    Mark
  • Hi Mark,

    I'm afraid the background of my question/remark wasn't entirely clear, but still your explanation helped. I understood that the IceUtil::Handle<T> are reference counted smart pointers, but I saw a potential problem passing naked pointers (such as "this") and have them implicitly converted to smart pointers.

    My mental model erroneously had the reference count as a part of the IceUtil::Handle side of things, rather than as a part of the IceUtil::Shared object, which is where they properly belong (this is the entire reason of having the IceUtil::Shared, of course). In the model I had in my mind, things would go wrong if you constructed two smart pointers to a single naked pointer, since both would take responsibility for deleting the object on hitting refcount==0, and with two Handles each having refcount>0 in existence, things would be bound to go wrong sooner or later.

    So, that was a bit of a "doh" moment for me, right there ... :-) Thanks for the explanation.

    Sidney