⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 otcl.tex

📁 对IEEE 802.11e里的分布式信道接入算法EDCA进行改进
💻 TEX
📖 第 1 页 / 共 4 页
字号:
Each of the variables that is bound is automatically initialisedwith default values when the object is created.The default values are specified as interpreted class variables.This initialisation is done by the routing \proc[]{init-instvar},invoked by methods in the class Instvar,\href{described later}{Section}{sec:InstVar}.\proc[]{init-instvar} checks the class of the interpreted object,and all of the parent class of that object, to find the firstclass 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\nsf{tcl/lib/ns-default.tcl}.For example, if the following class variables are defined for the ASRMAgent:\begin{program}        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\end{program}Therefore, every new Agent/SRM/Adaptive object will have\code{pdistance_} set to 15.0;\code{lastSent_} is set to 8.345mfrom the setting of the class variable of the parent class;\code{ctrlLimit_} is set to 1.44Musing the class variable of the parent class twice removed;\code{running} is set to false;the instance variable \code{pdistance_} is not initialised,because no class variableexists in any of the class hierarchy of the interpreted object.In such instance, \proc[]{init-instvar} will invoke \proc[]{warn-instvar}, to print out a warning about such a variable.The user can selectively override this procedurein their simulation scripts, to elide this warning.Note that the actual bindingis 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 correspondingto each of its member variable that is bound in this fashion.The head of this list is stored in its member variable\code{instvar_} of the TclObject.One last point to consider is that\ns\ will guarantee that the actual valuesof the variable, both in the interpreted object and the compiled object,will be identical at all times.However, if there are methods and other variablesof the compiled object that track the value of this variable,they must be explicitly invoked or changed whenever thevalue of this variable is changed.This usually requires additional primitives that the user should invoke.One way of providing such primitives in \ns\ is throughthe \fcn[]{command} method described in the next section.\subsection{Variable Tracing}\label{sec:VarTrace}In addition to variable bindings, TclObject also supports tracing ofboth C++ and Tcl instance variables.  A traced variable can be createdand configured either in C++ or Tcl.  To establish variable tracing atthe Tcl level, the variable must be visible in Tcl, which means that itmust be a bounded C++/Tcl or a pure Tcl instance variable.  In addition,the object that owns the traced variable is also required to establishtracing using the Tcl \code{trace} method of TclObject.  The firstargument to the \code{trace} method must be the name of the variable.The optional second argument specifies the trace object that isresponsible for tracing that variable.  If the trace object is notspecified, the object that own the variable is responsible for tracingit.For a TclObject to trace variables, it must extend the C++\code{trace} method that is virtually defined in TclObject.  The Traceclass implements a simple \code{trace} method, thereby, it can act as ageneric tracer for variables.\begin{verbatim}class Trace : public Connector {        ...        virtual void trace(TracedVar*);};\end{verbatim}Below is a simple example for setting up variable tracing in Tcl:\begin{small}\begin{verbatim}        # $tcp tracing its own variable cwnd_        $tcp trace cwnd_        # the variable ssthresh_ of $tcp is traced by a generic $tracer        set tracer [new Trace/Var]        $tcp trace ssthresh_ $tracer\end{verbatim}\end{small}For a C++ variable to be traceable, it must belong to a class thatderives from TracedVar.  The virtual base class TracedVar keeps track ofthe variable's name, owner, and tracer.  Classes that derives fromTracedVar must implement the virtual method \code{value}, that takes acharacter buffer as an argument and writes the value of the variableinto that buffer.\begin{small}\begin{verbatim}class TracedVar {        ...        virtual char* value(char* buf) = 0;protected:        TracedVar(const char* name);        const char* name_;      // name of the variable        TclObject* owner_;      // the object that owns this variable        TclObject* tracer_;     // callback when the variable is changed        ...};\end{verbatim}\end{small}The TclCL library exports two classes of TracedVar:  \code{TracedInt} and\code{TracedDouble}.  These classes can be used in place of the basictype int and double respectively.  Both TracedInt and TracedDoubleoverload all the operators that can change the value of the variablesuch as assignment, increment, and decrement.  These overloadedoperators use the \code{assign} method to assign the new value to thevariable and call the tracer if the new value is different from the oldone.  TracedInt and TracedDouble also implement their \code{value}methods that output the value of the variable into string.  The widthand precision of the output can be pre-specified.\subsection{\code{command} Methods: Definition and Invocation}\label{sec:Commands}For every TclObject that is created, \ns\ establishesthe instance procedure, \proc[]{cmd},as a hook to executing methods through the compiled shadow object.The procedure \proc[]{cmd} invokes the method \fcn[]{command}of the shadow object automatically, passing the arguments to \proc[]{cmd}as an argument vector to the \fcn[]{command} method.The user can invoke the \proc[]{cmd} method in one of two ways:by explicitly invoking the procedure, specifying the desiredoperation as the first argument, orimplicitly, as if there were an instance procedure of the same name as thedesired operation.Most simulation scripts will use the latter form, hence, we willdescribe that mode of invocation first.Consider the that the distance computation in SRM is done bythe compiled object; however, it is often used by the interpreted object.It is usually invoked as:\begin{program}        $srmObject distance? \tup{agentAddress}\end{program}If there is no instance procedure called \code{distance?},the interpreter will invoke the instance procedure\proc[]{unknown}, defined in the base class TclObject.The unknown procedure then invokes\begin{program}        $srmObject cmd distance? \tup{agentAddress}\end{program}to execute the operation through the compiled object's\fcn[]{command} procedure.Ofcourse, the user could explicitly invoke the operation directly.One reason for this might be to overload the operation by usingan instance procedure of the same name.For example,\begin{program}        Agent/SRM/Adaptive instproc distance? addr \{                $self instvar distanceCache_                if ![info exists distanceCache_($addr)] \{                        set distanceCache_($addr) [{\bfseries{}$self cmd distance? $addr}]                \}                set distanceCache_($addr)        \}\end{program}We now illustrate how the \fcn[]{command} method using\fcn[]{ASRMAgent::command} as an example.\begin{program}        int ASRMAgent::command(int argc, const char*const*argv) \{                Tcl& tcl = Tcl::instance();                if (argc == 3) \{                        if (strcmp(argv[1], "distance?") == 0) \{                                int sender = atoi(argv[2]);                                SRMinfo* sp = get_state(sender);                                tcl.tesultf("%f", sp->distance_);                                return TCL_OK;                        \}                \}                return (SRMAgent::command(argc, argv));        \}\end{program}We can make the following observations from this piece of code:\begin{itemize}\item The function is called with two arguments:    The first argument (\code{argc}) indicates  the number of arguments specified in the command line to the interpreter.  The command line arguments vector (\code{argv}) consists of    --- \code{argv[0]} contains the name of the method, ``\code{cmd}''.  --- \code{argv[1]} specifies the desired operation.  --- If the user specified any arguments, then they are placed in  \code{argv[2\ldots(argc - 1)]}.  The arguments are passed as strings;  they must be converted to the appropriate data type.\item If the operation is successfully matched,  the match should return the result of the operation  using methods \href{described earlier}{Section}{sec:Result}.\item \fcn[]{command} itself must return either \code{TCL_OK} or \code{TCL_ERROR}  to indicate success or failure as its return code.\item If the operation is not matched in this method, it must  invoke its parent's command method, and return the corresponding result.  This permits the user to concieve of operations as having the same  inheritance properties as instance procedures or compiled methods.  In the event that this \code{command} method   is defined for a class with multiple inheritance,  the programmer has the liberty to choose one of two implementations:  1) Either they can invoke one of the parent's \code{command} method,  and return the result of that invocation, or  2) They can each of the parent's \code{command} methods in some sequence,  and return the result of the first invocation that is successful.  If none of them are successful, then they should return an error.\end{itemize}In our document, we call operations executed through the \fcn[]{command} \emph{instproc-like}s.This reflects the usage of these operations as if they wereOTcl instance procedures of an object,but can be very subtly different in their realisation and usage.\section{Class TclClass}\label{sec:TclClass}This compiled class (\clsref{TclClass}{../Tcl/Tcl.h})is a pure virtual class.Classes derived from this base class provide two functions:construct the interpreted class hierarchyto mirror the compiled class hierarchy; andprovide methods to instantiate new TclObjects.Each such derived class is associated with a particular compiled classin the compiled class hierarchy, and can instantiate new objects in theassociated class.As an example, consider a class such as theclass \code{RenoTcpClass}.It is derived from class \code{TclClass}, andis associated with the class \code{RenoTcpAgent}.It will instantiate new objects in the class \code{RenoTcpAgent}.The compiled class hierarchy for \code{RenoTcpAgent} is thatit derives from \code{TcpAgent}, that in turn derives from \code{Agent},that in turn derives (roughly) from \code{TclObject}.\code{RenoTcpClass} is defined as\begin{program}        static class RenoTcpClass: public TclClass \{        public:                RenoTcpClass() : TclClass("Agent/TCP/Reno") \{\}                TclObject* create(int argc, const char*const* argv) \{                        return (new RenoTcpAgent());                \}        \} class_reno;\end{program}We can make the following observations from this definition:\begin{enumerate}\item The class defines only the constructor, and one additional method,  to \code{create} instances of the associated TclObject.\item \ns\ will execute the \code{RenoTcpClass} constructor  for the static variable \code{class_reno}, when it is first started.  This sets up the appropriate methods and the interpreted class hierarchy.\item The constructor specifies the interpreted class explicitly as  \code{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 \code{A/B/C/D},  the class \code{A/B/C/D} is a sub-class of \code{A/B/C},  that is itself a sub-class of \code{A/B},  that, in turn, is a sub-class of \code{A}.  \code{A} itself is a sub-class of \code{TclObject}.  In our case above, the TclClass constructor creates three classes,  \code{Agent/TCP/Reno} sub-class of \code{Agent/TCP}  sub-class of \code{Agent} sub-class of \code{TclObject}.\item This class is associated with the class \code{RenoTcpAgent};  it creats new objects in this associated class.\item The \code{RenoTcpClass::create} method returns TclObjects in the  class \code{RenoTcpAgent}.\item When the user specifies \code{new Agent/TCP/Reno},  the routine \code{RenoTcpClass::create} is invoked.\item The arguments vector (\code{argv}) consists of  --- \code{argv[0]} contains the name of the object.  --- \code{argv[1\ldots3]} contain  \code{$self}, \code{$class}, and \code{$proc}.  Since \code{create} is called  through the instance procedure \code{create-shadow},  \code{argv[3]} contains \code{create-shadow}.  --- \code{argv[4]}  contain any additional arguments (passed as a string) provided by the user.\end{enumerate}The \clsref{Trace}{../ns-2/trace.cc} illustratesargument handling by TclClass methods.\begin{program}        class TraceClass : public TclClass \{        public:                TraceClass() : TclClass("Trace") \{\}                TclObject* create(int args, const char*const* argv) \{                        if (args >= 5)                                return (new Trace(*argv[4]));                        else                                return NULL;                \}        \} trace_class;\end{program}A new Trace object is created as

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -