Here's a sample of the new VOS OTD format I'm working on.  This serves 
three purposes:

 a) Define the method call interface of a given vobject type.  This can 
then be used to generate calling stubs which marshal the method call and 
unmarshal the reply.

 b) Generate framework code that unmarshals the message and calls the 
actual method on the local site.  Also generate interceptors that filter 
messages outgoing to remote vobjects (basically the role of remote 
vobjects in s4) and updaters (same as s4, cache-update messages sent 
back to cached remote vobjects).

 c) Specify the legal set of child vobjects on the vobject type.  This 
will work with the interface generator to simplify accessing child 
vobjects, make it possible to generate vobject structures automatically 
and support validating existing structures.  With some other changes 
I'll discuss later, this will hopefully set us up to do some 
optimizations to the storage and access of vobjects.

So here's a slighty annotated sample file (commented with ;; because 
<!-- --> looks stupid).  This is all subject to change, in particular 
since the C++ code generator is not even done yet.

<?xml version="1.0"?>
<interfaces>  ;; root element
  <namespace name="property">  ;; vos namespace
    ;; vobject type name, so this would be property:int32
    ;; however this isn't my final decision on how the
    ;; new properties will work
    <vobjecttype name="int32">
      ;; directives are instructions to specific code
      ;; generator modules for each language to control
      ;; the output.  This says to generate the framework code
      ;; into which you would implement the type as a local
      ;; vobject
      <directives>
        <generatelocal languages="cpp" />
      </directives>

      ;; specify the get method
      <method name="get">
        <directives>
          ;; Have the c++ version generate an interceptor,
          ;; which is called when "get" is called on a vobject
          ;; on a remote site.  The interceptor has the option
          ;; of servicing the request out of the cache or passing
          ;; it on.
          <generateinterceptor languages="cpp" />
        </directives>
        ;; return a 32 bit signed integer
        <return name="value" type="int32" />
      </method>

      ;; Set the value.  Takes a 32 bit signed integer as a parameter.
      <method name="set">
        <param name="value" type="int32" />
      </method>

      ;; The sending vobject asks to start listening to changes
      ;; of this property.
      <method name="start-listening">
        <directives>
          <generateinterceptor languages="cpp" />
        </directives>
      </method>

      ;; The sending vobject asks to stop listening to changes
      ;; of this property.
      <method name="stop-listening">
        <directives>
          <generateinterceptor languages="cpp" />
        </directives>
      </method>

      ;; This vobject type has an update mesage that is sent back from 
      ;; the actual vobject to the remote stub
      <updater languages="cpp" name="set">
        <param name="value" type="int32" />
      </updater>

      ;; This vobject type emits a message with method value-changed
      <emits name="value-changed">
        <param name="value" type="int32" />
      </emits>
    </vobjecttype>
  </namespace>

  ;; sample vobject with children
  <namespace name="a3dl">
    <vobjecttype name="object3d">
      ;; there is a child named "position", its type is an array
      ;; of floats, and this child name only occurs once.
      <child name="position" type="property:array.float" 
             occurs="once" />
      <child name="orientation" type="property:array.float" 
             occurs="once" />
    </vobjecttype>
</interface>


Here's the sample header file generated from this.  The idea is to have 
two sets of files.  There is the automatically generated interface 
header and C++ stubs file, which the user should never touch.  The user 
subclasses in a separate file from the automatically generated files to 
fill in the actual implementations of the method interface (for local 
vobjects) or interceptors and updaters (for remote vobjects).

property.hh:
#include <vos/vos/basictypes.h>

namespace VOS { namespace Interfaces {
    namespace Property {
        class IInt32 {
        public:
            virtual ~IInt32() = 0;
            virtual int32_t get() = 0;
            virtual void set(int32_t value) = 0;
            virtual void start_listening() = 0;
            virtual void stop_listening() = 0;
        };

        class Int32 : public IInt32 {
        public:

            virtual int32_t get();
            virtual vos_msgid_t nonblocking_get();
            void unmarshal_get_result(vos_vobject_t* msg, 
                                      int32_t* out_result);

            void marshal_set(vos_vobject_t** msg, int32_t value);

            virtual void set(int32_t value);
            virtual vos_msgid_t nonblocking_set(int32_t value);


            virtual void start_listening();
            virtual vos_msgid_t nonblocking_start_listening();


            virtual void stop_listening();
            virtual vos_msgid_t nonblocking_stop_listening();

        };

        class LocalInt32 : public IInt32 {
        public:
            vos_message_t* execute_get(vos_vobject_t* msg);

            void unmarshal_set(vos_vobject_t* msg, int32_t* out_value);
            vos_message_t* execute_set(vos_vobject_t* msg);

            vos_message_t* execute_start_listening(vos_vobject_t* msg);

            vos_message_t* execute_stop_listening(vos_vobject_t* msg);

        };

        class RemoteInt32 : public IInt32 {
        public:
            vos_message_t* intercept_get(vos_vobject_t* msg);

            vos_message_t* intercept_start_listening(vos_vobject_t* msg);

            vos_message_t* intercept_stop_listening(vos_vobject_t* msg);

        };

    }
} }

A few things to notice: every call will have blocking and nonblocking 
(asynchronous) variations.  If you issue a nonblocking call, you get 
back the message id, and then the reply is delivered to the sender at a 
later date.  You can use the message id to identify the reply.

Also, I currently have the marshal/unmarshal calls as part of the public 
API.  However, I have not decided to what extent we will want to have 
the application deal with messages directly.  It seems to me that 
ideally the interface generator should be able to handle every cases, so 
that the application developer would never deal with actual VOS messages 
in normal usage.  Given that is the case, is it still better to provide 
a trapdoor for the user to drop down and deal with lower level messages 
when the interface generator won't cut it, or should access to the lower 
level interface be discouraged, so as to encourage expanding the 
interface generator to cover every case?  This was one reason I 
introduced directives into the file, so that there would be a way to 
communicate extended features to a particular code generator.  Something 
to think about.

This is all still very much a work in progress.  Comments welcome.

[   Peter Amstutz  ][ [EMAIL PROTECTED] ][ [EMAIL PROTECTED] ]
[Lead Programmer][Interreality Project][Virtual Reality for the Internet]
[ VOS: Next Generation Internet Communication][ http://interreality.org ]
[ http://interreality.org/~tetron ][ pgpkey:  pgpkeys.mit.edu  18C21DF7 ]

Attachment: signature.asc
Description: Digital signature

_______________________________________________
vos-d mailing list
vos-d@interreality.org
http://www.interreality.org/cgi-bin/mailman/listinfo/vos-d

Reply via email to