2011年3月21日 星期一

在ns中使用delay_bind() bind var (export var form c++ to tcl space)

.

想要將一個tcl的var和c++的var綁定(binding),按照NS by Example的範例,要在c++ clas的constructor中將想要bind的var透過bind這個function將c++的var address export到tcl space(畢竟兩個是在不同的記憶體空間)

但是ns的us manual 24.4.2中提到,在C++中使用bind()會使你創建的每個物件都消耗記憶體,若你創建許多相同的物件時,使用bind的代價太高。將bind()代換成delay_bind(),使得所需要的記憶體降到per-class level而非每個物件,從ns/object.cc參考如何binding的範例

那要如何使用delay_bind?

google了一下,其實沒有答案(中文的我就不期待了)

自己試了一下,簡單的說
1.在class對應的header file(.h)中,在protected下宣告兩個virtual function:
2.在class的實作中(.cc)實作此兩function
delay_bind_init_all的實作中,要call delay_bind_init_one() initialize tcl space的var,最後要記得call繼承者的delay_bind_init_all()
delay_bind_dispatch的實作中,要call delay_bind()來實現binding,最後同樣要記得call繼承者的delay_bindl()

我提供了一個範例(download),這個範例是從NS by Example的ex-linkage.cc改過來
可以直接放到ns的目錄中,將ex_link_delaybind.o加入Makefile的object list(OBJ_CC)中,重新make

make

再下載script file(download),同樣的,這個script file也是從NS by Example的ex-linkage.tcl改過來的,執行即可看到binding結果,結果就是在tcl中任意改var,class中對應的var也會變

ns ex_link_delaybind.tcl


大概解釋一下程式,我的C++ class為:MyAgentDelBind,繼承自Agent,該class中有兩個private data member:my_var1_、my_var2_想要跟tcl的data member連結
c++的my_var1_要跟tcl的my_var1_otcl連結
c++的my_var2_要跟tcl的my_var2_otcl連結

具體做法為
1.在class對應的header file(.h)中,在protected下宣告兩個virtual function:

virtual void delay_bind_init_all();
virtual int delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer);




2.在class的實作中(.cc)實作此兩function

delay_bind_init_all()的實作如下,這裡是主要initialize tcl space的var,因為此class是繼承自Agent,所以最後要記得call agent的delay_bind_init_all()

void MyAgentDelBind::delay_bind_init_all()
{
delay_bind_init_one("my_var1_otcl");
delay_bind_init_one("my_var2_otcl");
// MyAgent inherit from Agent => remember to call the ancestor's delay_bind_init_all()
Agent::delay_bind_init_all();
}


delay_bind_dispatch的實作如下,delay_bind就是在這裡被call來做tcl space跟C++ space var的連結,因為此class是繼承自Agent,所以最後要記得call agent的delay_bind_dispatch(),如此,就完成了cl space跟C++ space var的連結,跟以前在class constructor中call binding的做法不同

int MyAgentDelBind::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer)
{
if (delay_bind(varName, localName, "my_var1_otcl", &my_var1_, tracer))
return TCL_OK;
if (delay_bind(varName, localName, "my_var2_otcl", &my_var2_, tracer))
return TCL_OK;

// MyAgent inherit from Agent
// if delay_bind_dispatch matches none of above => remember to call the ancestor's delay_bind_dispatch()
return Agent::delay_bind_dispatch(varName, localName, tracer);
}
}


然後我在BTSim注意到,BTSim的parameters在tcl跟c++ space的var name相同,驗證了一下
確實tcl的var name可以跟c++ binding的var name同名(其實蠻理所當然的,兩個var在不同space,事實上addr也不同,也各自有自己的instance)

另一個問題是,針對export出去的var,若同時在c++ constructor給定初始值,又在script file中assign該export var,那麼結果會是怎樣?
同樣的,做了一下實驗
結果是,C++的constructor會先被執行,script file會接著overwirte該var
所以當script file有assign value時,以script file的value為準,否則,就是constructor assign的value為準

另外,delay_bind還有其他一些變化
delay_bind_bool:用來將c++的int連結到tcl的booling值 (FullTcpAgent有用到),但是實驗顯示,其連結的變數型態只能是int,只是可以在tcl裡設定true或是false而已
delay_bind_time:用來連結c++的double到tcl的time value(FullTcpAgent有用到,但型態還是dobule)
delay_bind_bw:用來連結c++的double到tcl的bandwidth value(雖沒人用到,但我試過,這個api是存在的,且有用)

.

沒有留言: