📄 otcl.tex
字号:
this permits quick access to the objects.The hash table is internal to the interpreter.\ns\ uses the name of the \code{TclObject} as the keyto enter, lookup, or delete the TclObject in the hash table.\begin{list}{\textbullet}{}\item \fcnref{\fcn[TclObject* $o$]{tcl.enter}}{../Tcl/Tcl.cc}{Tcl::enter} will insert a pointer to the TclObject $o$ into the hash table. It is used by \fcnref{\fcn[]{TclClass::create\_shadow}}{../Tcl/Tcl.cc}{TclClass::create\_shadow} to insert an object into the table, when that object is created.\item \fcnref{\fcn[char* $s$]{tcl.lookup}}{../Tcl/Tcl.h}{Tcl::lookup} will retrieve the TclObject with the name $s$. It is used by \fcnref{\fcn[]{TclObject::lookup}}{../Tcl/Tcl.h}{TclObject::lookup}.\item \fcnref{\fcn[TclObject* $o$]{tcl.remove}}{../Tcl/Tcl.cc}{Tcl::remove} will delete references to the TclObject $o$ from the hash table. It is used by \fcnref{\fcn[]{TclClass::delete\_shadow}}{../Tcl/Tcl.cc}{TclClass::delete\_shadow} to remove an existing entry from the hash table, when that object is deleted.\end{list}These functions are used internally bythe class TclObject and class TclClass.\subsection{Other Operations on the Interpreter}\label{sec:otcl:other}If the above methods are not sufficient,then we must acquire the handle to the interpreter,and write our own functions.\begin{list}{\textbullet}{}\item \fcnref{\fcn{tcl.interp}}{../Tcl/Tcl.h}{Tcl::interp} returns the handle to the interpreter that is stored within the class Tcl.\end{list}\section{Class TclObject}\label{sec:TclObject}\clsref{TclObject}{../Tcl/Tcl.h}is the base class for most of the other classesin the interpreted and compiled hierarchies.Every object in the class TclObject is created by the userfrom within the interpreter.An equivalent shadow object is created in the compiled hierarchy.The two objects are closely associated with each other.The class TclClass, described in the next section,contains the mechanisms that perform this shadowing.In the rest of this document, we often refer to an object as a TclObject%\footnote{In the latest release of \ns\ and \nsTcl, this object has been renamed to \code{SplitObjefct}, which more accurately reflects its nature of existence. However, for the moment, we will continue to use the term TclObject to refer to these objects and this class.}.By this, we refer to a particular object that is either in the classTclObject, or in a class that is derived from the class TclObject.If it is necessary, we will explicitly qualify whether that object isan object within the interpreter, or an object within the compiled code.In such cases,we will use the abbreviations ``interpreted object'', and``compiled object'' to distinguish the two.and within the compiled code respectively.\paragraph{Differences from \ns~v1}Unlike \ns~v1, the class TclObjectsubsumes the earlier functions of the NsObject class.It therefore stores the\href{interface variable bindings}{Section}{sec:VarBinds}that tie OTcl instance variables in the interpreted objectto corresponding C++ member variables in the compiled object.The binding is stronger than in \ns~v1 in thatany changes to the OTcl variables are trapped,and the current C++ and OTcl valuesare made consistent after each access through the interpreter.The consistency is done through the\href{class InstVar}{Section}{sec:InstVar}.Also unlike \ns~v1, objects in the class TclObjectare no longer stored as a global link list.Instead, they are stored in a hash table in the\href{class Tcl}{Section}{sec:HashTables}.\paragraph{Example configuration of a TclObject}The following example illustrates the configuration ofan SRM agent (\clsref{Agent/SRM/Adaptive}{../ns-2/srm-adaptive.tcl}).\begin{program} set srm [new Agent/SRM/Adaptive] $srm set packetSize_ 1024 $srm traffic-source $s0\end{program}By convention in \ns,the class Agent/SRM/Adaptive is a subclass of Agent/SRM,is a subclass of Agent, is a subclass of TclObject.The corresponding compiled class hierarchy isthe ASRMAgent, derived from SRMAgent, derived from Agent,derived from TclObject respectively.The first line of the above example shows how a TclObject is \href{created (or destroyed)}{Section}{sec:Creation};the next line configures\href{a bound variable}{Section}{sec:VarBinds};and finally, the last line illustratesthe interpreted object invoking a C++ method\href{as if they were an instance procedure}{Section}{sec:Commands}.\subsection{Creating and Destroying TclObjects}\label{sec:Creation}When the user creates a new TclObject,using the procedures \proc[]{new} and \proc[]{delete};these procedures are defined in \Tclf{tcl-object.tcl}.They can be used to create and destroy objects in all classes,including TclObjects.%\footnote{As an example, the classes Simulator, Node, Link, or rtObject,are classes that are \emph{not} derived from the class TclObject.Objects in these classes are not, therefore, TclObjects.However, a Simulator, Node, Link, or route Object is also instantiatedusing the \code{new} procedure in \ns.}.In this section,we describe the internal actions executed when a TclObjectis created.\paragraph{Creating TclObjects}By using \proc[]{new}, the user creates an interpreted TclObject.the interpreter will execute the constructor for that object, \proc[]{init},passing it any arguments provided by the user.\ns\ is responsible for automatically creating the compiled object.The shadow object gets created by the base class TclObject's constructor.Therefore, the constructor for the new TclObjectmust call the parent class constructor first.\proc[]{new} returns a handle to the object, that can then be usedfor further operations upon that object.The following example illustrates the Agent/SRM/Adaptive constructor:\begin{program} Agent/SRM/Adaptive instproc init args \{ eval $self next $args $self array set closest_ "requestor 0 repairor 0" $self set eps_ [$class set eps_] \}\end{program}The following sequence of actions are performed by the interpreteras part of instantiating a new TclObject.For ease of exposition, we describe the steps that are executedto create an Agent/SRM/Adaptive object.The steps are:\begin{enumerate}\item Obtain an unique handle for the new object from the TclObject name space. The handle is returned to the user. Most handles in \ns\ have the form \code{_o\tup{NNN}}, where \tup{NNN} is an integer. This handle is created by \fcnref{\proc{getid}}{../tclcl/tcl-object.tcl}{TclObject::getid}. It can be retrieved from C++ with the \fcnref{\proc{name()}}{../tclcl/tclcl.h}{TclObject::name()} method.\item Execute the constructor for the new object. Any user-specified arguments are passed as arguments to the constructor. This constructor must invoke the constructor associated with its parent class. In our example above, the Agent/SRM/Adaptive calls its parent class in the very first line. Note that each constructor, in turn invokes its parent class' constructor \textit{ad nauseum}. The last constructor in \ns\ is \fcnref{the TclObject constructor}{../Tcl/tcl-object.tcl}{TclObject::init}. This constructor is responsible for setting up the shadow object, and performing other initializations and bindings, as we explain below. \emph{It is preferable to call the parent constructors first before performing the initializations required in this class.} This allows the shadow objects to be set up, and the variable bindings established.\item The TclObject constructor invokes the instance procedure \proc[]{create-shadow} for the class Agent/SRM/Adaptive.\item When the shadow object is created, \ns\ calls all of the constructors for the compiled object, each of which may establish variable bindings for objects in that class, and perform other necessary initializations. Hence our earlier injunction that it is preferable to invoke the parent constructors prior to performing the class initializations.\item After the shadow object is successfully created, \fcnref{\fcn{create\_shadow}}{../Tcl/Tcl.cc}{TclClass::create\_shadow} \begin{enumerate} \item adds the new object to hash table of TclObjects \href{described earlier}{Section}{sec:HashTables}. \item makes \proc[]{cmd} an instance procedure of the newly created interpreted object. This instance procedure invokes the \fcn[]{command} method of the compiled object. In \href{a later subsection}{Section}{sec:Commands}, we describe how the \code{command} method is defined, and invoked. \end{enumerate}\end{enumerate}Note that all of the above shadowing mechanisms only work whenthe user creates a new TclObject through the interpreter.It will not work if the programmer creates a compiled TclObject unilaterally.Therefore, the programmer is enjoined not to use the C++ new methodto create compiled objects directly.\paragraph{Deletion of TclObjects}The \code{delete} operationdestroys the interpreted object, and the corresponding shadow object.For example,\fcnref{\proc[\tup{scheduler}]{use-scheduler}}{% ../ns-2/ns-lib.tcl}{Simulator::use-scheduler}uses the \code{delete} procedure to remove the default list scheduler,and instantiate an alternate scheduler in its place.\begin{program} Simulator instproc use-scheduler type \{ $self instvar scheduler_ delete scheduler_ \; first delete the existing list scheduler; set scheduler_ [new Scheduler/$type] \}\end{program}As with the constructor, the object destructor must call the destructorfor the parent class explicitly as the very last statement of the destructor.The TclObject destructorwill invoke the instance procedure \code{delete-shadow},that in turn invokes \fcnref{the equivalent compiled method}{% ../Tcl/Tcl.cc}{TclClass::delete\_shadow}to destroy the shadow object.The interpreter itself will destroy the interpreted object.\subsection{Variable Bindings}\label{sec:VarBinds}In most cases,access to compiled member variables is restricted to compiled code,and access to interpreted member variables is likewiseconfined to access via interpreted code;however, it is possible to establish bi-directional bindingssuch that both the interpreted member variableand the compiled member variable access the same data, and changing the value of either variablechanges the value of the corresponding paired variable to same value.The binding is established by the compiled constructorwhen 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 differentfor each variable type.\begin{itemize}\itemsep0pt\item Real and Integer valued variables are specified in the ``normal'' form. For example, \begin{program} $object set realvar 1.2e3 $object set intvar 12 \end{program}\item Bandwidth is specified as a real value, optionally suffixed by a `k' or `K' to mean kilo-quantities, or `m' or `M' to mean mega-quantities. A final optional suffix of `B' indicates that the quantity expressed is in Bytes per second. The default is bandwidth expressed in bits per second. For example, all of the following are equivalent: \begin{program} $object set bwvar 1.5m $object set bwvar 1.5mb $object set bwvar 1500k $object set bwvar 1500kb $object set bwvar .1875MB $object set bwvar 187.5kB $object set bwvar 1.5e6 \end{program}\item Time is specified as a real value, optionally suffixed by a `m' to express time in milli-seconds, `n' to express time in nano-seconds, or `p' to express time in pico-seconds. The default is time expressed in seconds. For example, all of the following are equivalent: \begin{program} $object set timevar 1500m $object set timevar 1.5 $object set timevar 1.5e9n $object set timevar 1500e9p \end{program} Note that we can also safely add a $s$ to reflect the time unit of seconds. \ns\ will ignore anything other than a valid real number specification, or a trailing `m', `n', or `p'.\item Booleans can be expressed either as an integer, or as `T' or `t' for true. Subsequent characters after the first letter are ignored. If the value is neither an integer, nor a true value, then it is assumed to be false. For example, \begin{program} $object set boolvar t \; set to true; $object set boolvar true $object set boolvar 1 \; or any non-zero value; $object set boolvar false \; set to false; $object set boolvar junk $object set boolvar 0 \end{program}\end{itemize}The following example shows the constructor for the ASRMAgent%\footnote{Note that this constructor is embellished to illustrate the features of the variable binding mechanism.}.\begin{program} 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 */ \}\end{program}Note that all of the functions above take two arguments,the name of an OTcl variable,and the address of the corresponding compiled member variablethat is linked.While it is often the case that these bindings are establishedby the constructor of the object, it need not always be done in this manner.We will discuss such alternate methodswhen we describe \href{the class InstVar}{Section}{sec:InstVar}in detail later.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -