本节主要是关于信道(channel)的相关知识。
信道封装了与连接关联的参数和行为,信道与简单模块类似,在它们背后就是C++类,在默认情况下,类名与NED的类型名相同,除非有一个@class属性(@namespace也需要注意),例如,下面的信道类型需要一个名为CustomChannel 的C++ 类。
channel CustomChannel // needs a CustomChannel C++ class
{
}
跟简单模块不同的是,一般情况下不需要自己来定义信道类型,只需要从系统中已经预定义好的信道类型进行特殊化即可,内建的类型有: ned.IdealChannel, ned.DelayChannel and ned.Datarate-Channel。 (“ned” 是包名,和Java类似的是可以用import ned.* 来导入所有这三种类型,这样就不用写前缀ned)。
IdealChannel
DelayChannel
- 有两个参数。
- delay是一个double类型的参数,代表传播时延,可以用s,ms,us来指定。
- Disabled是一个布尔值,默认为false,当设为true时,信道对象会丢弃所有的信息。
DatarateChannel
- 与DelayChannel相比,它有更多的参数。
- datarate是一个double型的参数,代表信道的数据率,可以用bps,Kbps,Mbps,Gbps来指定,默认值是0,代表无限带宽。
- ber和per分别代表比特错误率和包错误率,并且允许基本的错误建模。它们是随机生成的范围在0到1之间的数值。通过在包对象中设置一个错误的标记(error flag),接收的模块进行检查并丢弃标记为冲突的数据包。它们的默认值都是0。
注意: There is no channel parameter that would decide whether the channel deliversthe message object to the destination module at the end or at the start of the reception; that is decided by the C++ code of the target simple module. See the setDeliverOn-ReceptionStart() method of cGate.
Read more…
struct vs class
在 C++ 中class 和 struct 只有两点主要区别:
- 默认继承权限。默认情况下,class的继承是以private来继承而struct则是按照public进行继承。
- 成员的默认访问权限。class的成员默认是private权限,struct默认是public权限。
而其它的特性,struct和class基本上,甚至严格来说是一样的:
//一个不常见的示例,将 struct 直接改为class也能编译通过。
//编译环境为 GCC 4.4.1
#include <iostream>
#include <string>
using namespace std;
struct bar
{
private: // 访问权限修饰符
int y;
public:
bar(){}; //无参构造函数
bar(int a){ y = a;}//带参数的构造函数
~bar(); //虚构函数
void say();
virtual void func1() = 0; //纯虚函数
};
struct foo: protected bar // 继承
{
private:
int x;
public:
foo(){};
void say(string msg) {cout<<msg<<endl;}
virtual int func2();//虚函数
};
int main() {
return 0;
}
可以看到:
- 都可以有成员函数:struct可以包含和class中一样的构造函数,析构函数,重载的运算符,友元类,友元结构,友元函数,虚函数,纯虚函数,静态函数;
- 尽管默认访问权限不同,但都可以拥有public/private/protected修饰符;
- 都可以进行复杂的继承和多重继承,一个struct可以继承自一个或多个class,反之亦可。
- 注意这里与C语言并不相同,C 语言中的 struct 从本质上来说只是一个包装数据的语法机制。
Read more…
本节内容是复合模块,即 Compound modules。
一个复合模块可以拥有gates和参数,但是并没有C++代码与之关联。如果想要为一个复合模块添加代码,可以将代码封装为一个简单模块,然后以子模块的方式来添加到复合模块中。
一个复合模块的声明可以包含若干部分,它们都是可选的:
module Host
{
types: // 在这里定义内部类型,如模块和信道类型等,仅在本地使用
...
parameters:
...
gates:
...
submodules: // 子模块,可以创建子模块向量,子模块的类型可以来自参数
...
connections:// 可以通过循环,条件等创建连接,连接的行为可以通过将信道与连接联系来定义,信道的类型也可以来自参数
...
}
复合模块可以通过继承来扩展,继承时不仅可以加入参数和gates,还可以加入新的子模块和新的连接,但是不能对子模块或连接进行“de-inherit”,或者修改所继承的模块或类型。
Read more…
本文是《Programming Scala》第一章的笔记,Scala 是一门很有趣也很简练的语言。
Scala为并行,简洁,可伸缩性而设计,它是一种函数式和面向对象的混合式语言,提供了基于actor的消息传递模型以去除并行带来的复杂性。使用这个模型,可以编写简洁的多线程代码(synchoroize关键字可以从词汇中消除了),而不用担心线程之间的数据连接以及处理锁和释放所带来的问题。
然而Scala也能用来编写单线程的应用程序,或者作为多线程应用的单线程模块,它的函数式风格有利于单线程和多线程的应用。Scala的并行模型与Erlang的风格很相似,但Scala的优点是:它是强类型而Erlang是弱类型,能在JVM上运行,与Java很好的进行交互。
下图展示了Scala在企业应用中适合的地方:

Scala in Enterprise Environment
注意到,可以将Java代码包装在Scala的actor库中提供线程的隔离,如果要在线程之间通讯,则使用Scala轻量级API来传递信息。在Scala中不用在创建线程时马上用同步来限制其并行,而是在不使用锁的情况下进行真正的并行操作,这就能更关注应用逻辑而不是低层次的线程。
Scala是静态类型的,但与Java 不同的是,不必明确反复地指定类型,很多情况下编译器可以进行类型推断,这一特性在简化函数的参数和返回值时很有用。
Scala的内核是很小的,其它包含操作符,Actor,都仅仅只是Scala库的一部份,可扩展性是极强,完全可以自行写一个实现。函数式编程是一种声明式的风格,在这种风格中指明的是“做什么”而不是“应该怎样做”,在XSLT,规则引擎,或者ANTLR中使用的就是函数式风格。
在一个数组中寻找最大值的函数式编程如下:
def findMax(temperatures : List[Int]) = {
temperatures.foldLeft(Integer.MIN_VALUE) {
Math.max
}
}
将列表中的每个元素乘以2:
val values = List(1, 2, 3, 4, 5)
val doubleValues = values.map( _ * 2)
计算一个数的阶乘:
def fact(n: Int) = 1 to n reduceLeft (_*_)
Read more…
本节介绍简单模块。
简单模块是在模型中活动的组件,它用关键字 simple 来定义。
simple Queue
{
parameters:
int capacity;
@display("i=block/queue");
gates:
input in;
output out;
}
Parameters和gates部分都是可选的,即是说如果没有parameter或gate的话就可以不写。而且parameters关键字本身也是可选的,就算参数和属性存在也可以忽略它。
NED定义不包含模块的任何操作,操作是用C++来定义的,默认情况下OMNet将查找与NED类型同名的C++类(在这里是Queue)。
可以用@class 属性直接指定C++类,类也可以包括命名空间,如下例使用了mylib::Queue
simple Queue
{
parameters:
int capacity;
@class(mylib::Queue);
@display("i=block/queue");
gates:
input in;
output out;
}
如果几个模块都在相同的命名空间里,那最好用@namespace代替@class属性,例如下面的例子会自动添加命名空间mylib作为前缀:
@namespace(mylib);
simple App {
...
}
simple Router {
...
}
simple Queue {
...
}
Read more…
评论