学习NS2重要要把握几个重要的类一

NS2中Tcl类与TclObject类解析
本文详细介绍了NS2中Tcl类的功能及其操作方法,并深入探讨了TclObject类的创建与销毁流程,以及与TclClass类的关系。

学习NS2重要要把握几个重要的类。现在简单分析下。

1.Tcl类

这个类封装是OTcl解释器的真正实例,可以当成解释器理解。 其中定义了解释器访问及通信的方法。这个类是在~tclcl/tclcl.h和~tclcl/tcl.cc中定义的,提供了以下的操作方法:

1.1 获得 Tcl 实例的一个指针

   在类定义有 static Tcl instance_;获取的方法是通过一个静态的内联函数static inline Tcl& instance() { return (instance_); }实现的。

1.2 通过解释器调用 OTcl 过程

    通过解释器实例tcl来调用OTcl命令,他们在调用参数方面有本质的区别。每个函数都传递一个字串(string)给解
释器,然后解释器通过一个全局文本来识别这个字符串。如果解释器返回TCL_OK,则这些函数将会返一个相应的OTcl
过程。反过来,如果解释器返回TCL_ERROR,则这些函数将调用tkerror{}。用户可以重载(overload)个过程,以便有选
择地忽略某些类型的错误。

1.3 取出或将结果返回解释器

    //tcl的解释器
    Tcl_Interp* tcl_; Tcl_Interp是在~include/tcl.h中的定义的,

    typedef struct Tcl_Interp {
        char *result;        /*指向命令的返回值*/
        void (*freeProc) _ANSI_ARGS_((char *blockPtr));
        int errorLine;              /* 当返回TCL_ERROR时,该值指示出出现错误的行数(从1开始) */
    } Tcl_Interp;

    结果就保存在tcl_->result中。

    取出结果:tcl.result(void)必须用于取回结果。注意这里的结果是一个字符串,它必须被转化成一个适合结果类型的内部格式。

     结果传给解释器,即设置tcl_->result的值,a)tcl.result(const char* s),b)tcl.resultf(const char* fmt, . . . )

1.4 报告错误状态并以统一的方法退出

    编译代码中提供了一种统一的报告错误的方法。

    tcl.error(const char* s)执行以下功能:  将s写入stdout;将tcl_->result写入stdout;退出,并将错误代码(error code)置1。
    tcl.resultf("cmd = %s", cmd);
    tcl.error("invalid command specified");
 

1.5 存储并查找“TclObjects“

    ns将每个TclObject在编译层次的一个指针(reference)存在一个hash表中;这样就能快速地访问该对象了。该hash
表在解释器的内部。Ns用户以TclObject的名字为关键字(key)在hash表中进行插入、查找或者删除TclObject的操作。

    tcl.enter(TclObject* o)将在hash表插入一个指向TclObject o的指针(pointer)。它被TclClass::create_shadow()
用来在对象建立时,将其插入表中。

    tcl.lookup(char* s)将取回名为s的TclObject。可以这样被使用:TclObject::lookup()。

    tcl.remove(TclObject* o)将删除hash表中TclObject o的指针。可以用TclClass::delete_shadow()来移出hash表中
存在的入口,此时该对象已经被删除。

2.TclObject类

    TclObject类是解释和编译层次大多数其它类的基类(base class)。TclObject类中的每个对象都由用户从解释器中创
建。编译层次中同时有一个与之对应的影子对象(shadow object)被创建。这两个对象相互紧密联系。下一小节描述的
TclClass类,包含了执行这种投射(shadowing)的机制。
    TclObject类包含了早期的NsObject类的函数。因此,它储存了变量绑定(bindings)接口,这些变量绑定绑定了解释对象中的实例变量(instance variables)和相应的编译对象中的C++成员变量(member variables)。这种绑定比ns版本1要强,因为OTcl变量的任何变化都是被跟踪(trapped)的,而且每次当前的C++和OTcl的值被解释器访问后都要保持一致。这种一致性是由InstVar类来完成的。同样,和ns版本1不同的是,tclObject类的对象不再存储在一个全局链表(link list)中。而是存储在Tcl类的一个hash表中。

2.1 创建(creating)和撤销(Destroying)TclObjects

    当用户创建一个新的TclObject时,通常调用new{}和delete{}过程 (procedures) 这些过程定义在~tclcl/tcl-object.tcl中。  它们可以用于创建和撤销所有类的对象。

    创建TclObjects 用户可以调用new{}来创建一个解释类的TclObject。这时解释器将执行这个对象的构造函数
(constructor)init{},同时给它传递用户提供的任何参数。ns自动创建相应的编译对象。  shadow对象是通过基类TclObject
的构造函数被创建的。因此,新的TclObject的构造函数必须首先调用父类的构造函数。new{}方法返回一个对象的handle,
用户可以通过这个handle对对象进行进一步的操作。
    如下面是Agent/SRM/Adaptive的构造函数:
    Agent/SRM/Adaptive instproc init args {
    eval $self next $args
    $self array set closest_ "requestor 0 repairor 0"
    $self set eps_ [$class set eps_]
    }

    创建一个gent/SRM/Adaptive对象时执行的步骤:

    2.1.1 从TclObject的名字空间(name space)获取一个惟一的新的对象的handle。这个handle将返回给用户。ns中大多数handle都是以_o<NNN>的形式出现的,这里的<NNN>是一个整数。这个handle由getid{}创建。它可以从C++中的name(){}的方法获得。
    在TclObject类中定义:

    #if 0
    /* allocate in-line rather than with new to avoid pointer and malloc overhead. */
    #define TCLCL_NAME_LEN 12
    char name_[TCLCL_NAME_LEN];
    #else /* ! 0 */
    char *name_;
    #endif /* 0 */
    inline const char* name() { return (name_); }
    void name(const char*); 

    2.2.2 执行新对象的构造函数。任何的特定的用户输入参数都将作为构造函数的参数传入。这个构造函数必调用其父类的构造函数。
    在上面的例子里,Agent/SRM/Adaptive在第一行就调用了其父类。
    需要注意的是,每个构造函数,依次调用其父类的构造函数。 那么ns中的最后一个构造函数就是TclObject的构造函数。
这个构造函数用来创建对应的shadow对象,并执行其它的初始化工作与绑定。因此最好在构造函数先调用父类的构造函数,然后再初始化。这样可以使shadow对象先被建立,从而有变量可以绑定。

   2.2.3 TclObject的构造函数为Agent/SRM/Adaptive类调用create-shadow{}实例过程。

   2.2.4 当shadow对象建立以后,ns为编译对象调用所有的构造函数,它们每个都有可能为类中的对象建立相应的变量绑定,同时执行其它的必要的初始化工作。因此我们最好把调用父类的构造函数的语句放在类初始化语句之前。

   2.2.5 在shadow对象成功创建后。这样就通过create_shadow(void)将创建的TclObject对象添加到tcl类的hash表中,如上文。使cmd{}成为一个新创建的解释对象的实例化过程。这个实例化过程会调用编译对象中的command()方法。在接下来的一节里,我们将介绍command方法是如何定义并被调用的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值