Archived

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

TimeOfDay example

Hey there,

could you guys from ZeroC please post/ release the TimeOfDay example that you describe in the manual?
Unfortunately, you miss the most interesting part of the factory example, the actual creation and proxy-ing of the TimeOfDay objects (serverside)....

kind regards,

Stephan

Comments

  • Hmmm... I used TimeOfDay in a number of places in the book to explain things. Which example exactly are you talking about?

    If you want an implementation, you can modify the Hello demo. Something like:
    struct TimeOfDay {
        short hour;
        short minute;
        short second;
    };
    
    interface Time {
        TimeOfDay get();
    };
    

    An implementation could be:
    class TimeOfDayI : virtual public TimeOfDay {
    public:
        virtual TimeOfDay get(Ice::Current &) {
            time_t now = time(0);
            struct tm * time_p = gmtime(&time_now);
    
            TimeOfDay tod;
            tod.hour = time_p->tm_hour;
            tod.minute = time_p->tm_min;
            tod.second = time_p->tmn_sec;
    
            return tod;
    }
    

    Cheers,

    Michi.
  • Michi,

    thanks for your answer.
    My question is how I make the TimeOfDay object that get() should return correctly available from the clientside?

    Especially, your variable TimeOfDay tod gets out of scope at the end of the function and should be removed from stack.
    My understanding was that I had to create a new remote object (new TimeOfDayI), create a proxy for that object and return the reference...
    Or am I wrong?

    Stephan
  • You don't need to necessarily return a proxy. The client can construct a proxy to the server directly. Have a look at section 3.2 in the manual. It shows the complete code for a simple application.

    Cheers,

    Michi.
  • Hi Michi!
    Originally posted by michi (with a little correction)
    class TimeI : virtual public Time {
    public:
        virtual TimeOfDay get(Ice::Current &) {
            time_t now = time(0);
            struct tm * time_p = gmtime(&time_now);
    
            TimeOfDay tod;
            tod.hour = time_p->tm_hour;
            tod.minute = time_p->tm_min;
            tod.second = time_p->tmn_sec;
    
            return tod;
    }
    

    Yes, I understand this example and I also know section 3.2.
    Your example will unfortunately only work if your interface (TimeOfDay) has no functions. If they would, you would get (obviously) an error because of pure virtual functions in TimeOfDay. So, let's assume that TimeOfDay looks like:
    struct TimeOfDay {
        short hour;
        short minute;
        short second;
        
        long secondsSince1970();
    };
    
    interface Time {
        TimeOfDay get();
    };
    

    Can you give me an implementation for TimeI::get() in this case? I think, this is all I would need ;)

    regs,

    Stephan
  • Originally posted by stephan
    So, let's assume that TimeOfDay looks like:

    struct TimeOfDay {
        short hour;
        short minute;
        short second;
        
        long secondsSince1970();
    };
    
    interface Time {
        TimeOfDay get();
    };
    

    Can you give me an implementation for TimeI::get() in this case? I think, this is all I would need ;)

    Structures cannot contain operations, so your Slice definition will have to look like this:
    [b]class[/b] TimeOfDay {
        // ...
    };
    

    Your class implementation would look something like this:
    class TimeOfDayI : public virtual TimeOfDay {
    public:
        TimeOfDayI() {
            _secs = time(0);
            struct tm * time_p = gmtime(&time_now);
            hour = time_p->tm_hour;
            minute = time_p->tm_min;
            second = time_p->tmn_sec;
        }
    
        virtual Ice::Long secondsSince1970(const Ice::Current &) {
            return _secs;
        }
    
    private:
        time_t _secs;
    };
    

    The way I wrote this, the class remembers the time when it was instantiated and then returns that time from there on. Of course, you can implement any semantics you want.

    You also must register a class factory because, without that, the Ice run time has no idea that the abstract TimeOfDay class is implemented by the concrete TimeOfDayI class:
    class TimeOfDayIFactory : public virtual Ice::ObjectFactory {
    public:
        virtual Ice::ObjectPtr create(const std::string &type) {
            assert(type == TimeOfDay::ice_id());
            return new TimeOfDayI;
        }
        virtual void destroy() {}
    };
    

    To register the class factory:
    Ice::CommunicatorPtr ic = ...;
    ic->addObjectFactory(new TimeOfDayIFactory, TimeOfDay::ice_id());
    

    And, finally, the interface implementation:
    class TimeI : public virtual Time {
    public:
        virtual TimeOfDayPtr get(const Ice::Current &) {
            return new TimeOfDayI;
        }
    };
    

    BTW -- all of this can be found in the manual ;)

    Cheers,

    Michi.
  • Dear Michi,

    Sorry that it took so long to post this example...
    Example 01 is working as expected and as described in the upper part of this thread.
    However, this example reveals a possible design issue. In example 02 (in the next posting), I added a function which modifies the object that was previously returned by the Time object. This is being done by the refresh() function (ok, this function doesn't make much sense but after all it's just an example :-))= ).
    However, as expected, only the local copy (that was created by the TimeOfDayIFactory on the client side).
    However, this is not a surprising but rather expected result but may not be the result one could be aiming for (actually, this was basically the reason why I started this thread....).
    What I basically did:
    The Time object stores the TimeOfDay instance it created.
    When calling the refresh() function of the Time object, this object checks whether TimeOfDay was already being instantiated and then refreshes this object.

    In the main control flow, I retrieved a TimeOfDay object from Time, then called refresh() on the Time object and again asked the TimeOfDay object I alreay hold for the time.

    regs,

    Stephan
  • Unfortunately I can only upload one attachment per posting, so here is the second one!
  • Originally posted by stephan
    In example 02 (in the next posting), I added a function which modifies the object that was previously returned by the Time object. This is being done by the refresh() function (ok, this function doesn't make much sense but after all it's just an example :-))= ).
    However, as expected, only the local copy (that was created by the TimeOfDayIFactory on the client side).
    However, this is not a surprising but rather expected result but may not be the result one could be aiming for (actually, this was basically the reason why I started this thread....).

    Sorry for not replying sooner -- I somehow missed your post.

    Well, this works exactly as expected: the call to refresh updates the local object (because all operation invocations on class instances run local to the caller and operate on the local instance that was marshaled by value).

    If you want to have an operation on a class go to a remote instance, you can this by creating a proxy for the instance and passing the proxy to the client. When the client invokes on the proxy, the call goes remote as usual.

    Cheers,

    Michi.