3.5 Class TclClass

This compiled class (TclClass../Tcl/Tcl.h) is a pure virtual class. Classes derived from this base class provide two functions: construct the interpreted class hierarchy to mirror the compiled class hierarchy; and provide methods to instantiate new TclObjects. Each such derived class is associated with a particular compiled class in the compiled class hierarchy, and can instantiate new objects in the associated class.

As an example, consider a class such as the class RenoTcpClass. It is derived from class TclClass, and is associated with the class RenoTcpAgent. It will instantiate new objects in the class RenoTcpAgent. The compiled class hierarchy for RenoTcpAgent is that it derives from TcpAgent, that in turn derives from Agent, that in turn derives (roughly) from TclObject. RenoTcpClass is defined as

        static class RenoTcpClass: public TclClass {
                RenoTcpClass() : TclClass("Agent/TCP/Reno") {}
                TclObject* create(int argc, const char*const* argv) {
                        return (new RenoTcpAgent());
        } class_reno;
We can make the following observations from this definition:
  1. The class defines only the constructor, and one additional method, to create instances of the associated TclObject.
  2. ns will execute the RenoTcpClass constructor for the static variable class_reno, when it is first started. This sets up the appropriate methods and the interpreted class hierarchy.
  3. The constructor specifies the interpreted class explicitly as Agent/TCP/Reno. This also specifies the interpreted class hierarchy implicitly.

    Recall that the convention in ns is to use the character slash ('/') is a separator. For any given class A/B/C/D, the class A/B/C/D is a sub-class of A/B/C, that is itself a sub-class of A/B, that, in turn, is a sub-class of A. A itself is a sub-class of TclObject.

    In our case above, the TclClass constructor creates three classes, Agent/TCP/Reno sub-class of Agent/TCP sub-class of Agent sub-class of TclObject.

  4. This class is associated with the class RenoTcpAgent; it creats new objects in this associated class.
  5. The RenoTcpClass::create method returns TclObjects in the class RenoTcpAgent.
  6. When the user specifies new Agent/TCP/Reno, the routine RenoTcpClass::create is invoked.
  7. The arguments vector (argv) consists of

    -- argv[0] contains the name of the object.

    -- argv[1...3] contain $self, $class, and $proc.Since create is called through the instance procedure create-shadow, argv[3] contains create-shadow.

    -- argv[4] contain any additional arguments (passed as a string) provided by the user.

The Trace../ns-2/trace.cc illustrates argument handling by TclClass methods.
        class TraceClass : public TclClass {
                TraceClass() : TclClass("Trace") {}
                TclObject* create(int args, const char*const* argv) {
                        if (args \>= 5)
                                return (new Trace(*argv[4]));
                                return NULL;
        } trace_class;
A new Trace object is created as
        new Trace "X"
Finally, the nitty-gritty details of how the interpreted class hierarchy is constructed:
  1. The object constructor is executed when ns first starts.
  2. This constructor calls the TclClass constructor with the name of the interpreted class as its argument.
  3. The TclClass constructor stores the name of the class, and inserts this object into a linked list of the TclClass objects.
  4. During initialization of the simulator, Tcl_AppInit../ns-2/ns_tclsh.cc::Tcl_AppInit invokes TclClass::bind../Tcl/Tcl.ccTclClass::bind
  5. For each object in the list of TclClass objects, []bind invokes []register../Tcl/tcl-object.tclTclObject::register, specifying the name of the interpreted class as its argument.
  6. []register establishes the class hierarchy, creating the classes that are required, and not yet created.
  7. Finally, []bind defines instance procedures create-shadow and delete-shadow for this new class.

Tom Henderson 2011-11-05