3.4.2 Variable Bindings

In most cases, access to compiled member variables is restricted to compiled code, and access to interpreted member variables is likewise confined to access via interpreted code; however, it is possible to establish bi-directional bindings such that both the interpreted member variable and the compiled member variable access the same data, and changing the value of either variable changes the value of the corresponding paired variable to same value.

The binding is established by the compiled constructor when that object is instantiated; it is automatically accessible by the interpreted object as an instance variable. ns supports five different data types: reals, bandwidth valued variables, time valued variables, integers, and booleans. The syntax of how these values can be specified in OTcl is different for each variable type.

The following example shows the constructor for the ASRMAgent3.3.

        ASRMAgent::ASRMAgent() {
                bind("pdistance_", &pdistance_);      /* real variable /
                bind("requestor_", &requestor_);      /* integer variable /
                bind_time("lastSent_", &lastSessSent_); /* time variable /
                bind_bw("ctrlLimit_", &ctrlBWLimit_); /* bandwidth variable /
                bind_bool("running_", &running_);     /* boolean variable /
        }
Note that all of the functions above take two arguments, the name of an OTcl variable, and the address of the corresponding compiled member variable that is linked. While it is often the case that these bindings are established by the constructor of the object, it need not always be done in this manner. We will discuss such alternate methods when we describe the class InstVarSectionsec:InstVar in detail later.

Each of the variables that is bound is automatically initialised with default values when the object is created. The default values are specified as interpreted class variables. This initialisation is done by the routing []init-instvar, invoked by methods in the class Instvar, described laterSectionsec:InstVar. []init-instvar checks the class of the interpreted object, and all of the parent class of that object, to find the first class in which the variable is defined. It uses the value of the variable in that class to initialise the object. Most of the bind initialisation values are defined in ~ns/tcl/lib/ns-default.tcl.

For example, if the following class variables are defined for the ASRMAgent:

        Agent/SRM/Adaptive set pdistance_ 15.0
        Agent/SRM set pdistance_ 10.0
        Agent/SRM set lastSent_ 8.345m
        Agent set ctrlLimit_    1.44M
        Agent/SRM/Adaptive set running_ f
Therefore, every new Agent/SRM/Adaptive object will have pdistance_ set to 15.0; lastSent_ is set to 8.345m from the setting of the class variable of the parent class; ctrlLimit_ is set to 1.44M using the class variable of the parent class twice removed; running is set to false; the instance variable pdistance_ is not initialised, because no class variable exists in any of the class hierarchy of the interpreted object. In such instance, []init-instvar will invoke []warn-instvar, to print out a warning about such a variable. The user can selectively override this procedure in their simulation scripts, to elide this warning.

Note that the actual binding is done by instantiating objects in the class InstVar. Each object in the class InstVar binds one compiled member variable to one interpreted member variable. A TclObject stores a list of InstVar objects corresponding to each of its member variable that is bound in this fashion. The head of this list is stored in its member variable instvar_ of the TclObject.

One last point to consider is that ns will guarantee that the actual values of the variable, both in the interpreted object and the compiled object, will be identical at all times. However, if there are methods and other variables of the compiled object that track the value of this variable, they must be explicitly invoked or changed whenever the value of this variable is changed. This usually requires additional primitives that the user should invoke. One way of providing such primitives in ns is through the []command method described in the next section.

Tom Henderson 2011-11-05