2009年3月31日星期二

Nebula3基础层-消息子系统


Message子系统是Nebula3实现多线程架构的核心。

Port:1.消息接收端口。消息被立即处理并且程序将被阻塞直到消息处理完成。消息是通过增加到Port中的Handler来处理的,Port可以增加一个或多个Handler。当接收到一个消息,增加到Port中的每个Handler将被调用来处理消息,直到有一个Handler处理完消息后返回true,这意味着消息处理完成了。

2.Port::RegisterMessage(const Id& msgId)方法用来注册该Port能处理的消息类型。

AsyncPort:在一个分开的线程中调用handlers来处理消息,因此不会阻塞主线程。AsyncPort的子类覆写AsyncPort::OnCreateHandlers()方法,在这个方法中创建Handler并把它添加到AsyncPort中。

Handler:实际处理消息的类。用户需要继承Handler类并覆写Handler::HandleMessage()方法。

Id:消息类型标识符。在消息中使用DeclareMsgId和ImplementMsgId宏来实现。

Message:包装数据并可以被发送到Port和AsyncPort。这实现了一个通用的通信机制,不仅可以用于相同线程,线程之间,甚至还可以用在不同机器之间的通讯。Message作为一个普通的C++对象,可以被持久化。用户继承Message类实现自己需要的不同消息。

Dispatcher:是一个特殊的消息接收端口。Dispatcher把消息分发到能处理该消息的端口上。具体实现可以参考类图和以下图示:

Nebula3基础层-线程子系统


线程子系统主要是对各种平台的多线程部分进行抽象和封装。

Thread:对平台线程的封装,调用Thread::Start()开启一个新的线程。用户需要在子类覆写Thread::DoWork()方法来执行自己需要的操作,当用户需要在子类的DoWork()方法中执行循环操作时就必须调用Thread::ThreadStopRequested()方法来判断线程是否停止。调用Thread::Stop()停止一个线程,线程会等待DoWork()方法处理完成后才退出。

Event:用来处理线程同步。当一个线程调用Event::Wait()时,线程将处于等待状态。调用Event::Signal()将激活一个等待的线程。Event::Peek()用来检查线程当前的状态,并立即返回结果。

CriticalSection:同步代码块,处于CriticalSection::Enter()和CriticalSection::Leave()之间的代码,同时只能由一个线程来执行。

Interlocked:提供一些简单的原子操作。

2009年3月30日星期一

Nebula3基础层-IO子系统


Io子系统的整个设计主要是参考了.net的io设计。一个比较重要的设计是对路径的抽象。

Stream:一个抽象的数据流,接着分别实现了文件流和内存流,zip流。用户可以根据自己的需要实现其它类型的流。

StreamReader,StreamWriter:提供了读写流的抽象。

FSWrapper:包装了不同平台的io操作。

IoServer:Io子系统对外提供服务的接口,主要有以下操作:

1.根据不同的URI scheme关联到不同的流类。
2.根据给定的URI创建正确的流。
3.对于ZIP压缩包提供透明的支持。
4.路径别名管理。
5.提供全局的文件系统操作和查询方法。

2009年3月6日星期五

Lua程序设计 第九章 协同程序

1.协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈,局部变量和指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。

2.线程与协同程序的主要区别在于,一个具有多线程的程序可以同时运行几个线程,而协同程序却需要彼此协作地运行。就是说,一个具有多个协同程序的程序在任何时刻只能运行一个协同程序,并且正在运行的协同程序只会在其显示地挂起时,它的执行才会暂停。

3.当一个协同程序A唤醒另一个协同程序B,协同程序A就处于一个特殊状态,既不是挂起状态(无法继续A的执行),也不是运行状态(B在运行)。所以将这时的状态称为“正常”状态。

4.Lua提供的是一种“非对称的协同程序(asymmetric coroutine)”。也就是说,Lua提供了两个函数来控制协同程序的执行,一个用于挂起执行,另一个用于恢复执行。而一些其它的语言则提供了“对称的协同程序(symmetric coroutine)“,其中只有一个函数用于转让协同程序之间的执行权。

Lua程序设计 第八章 编译,执行与错误

1.区别解释型语言的主要特征并不在于是否能编译它们,而是在于编译器是否是语言运行时库的一部分,即是否有能力执行动态生成的代码。

2.Lua提供的所有关于动态库的功能都聚集在一个函数中,即package.loadlib。

3.由于Lua是一种扩展语言,通常嵌入到应用程序中,因此在发生错误时不能简单地崩溃或退出。相反,只要发生一个错误,Lua就应该结束当前程序块并返回应用程序。

4.对于大多数应用程序而言,无须在Lua代码中作任何错误处理,应用程序本身会负责这类问题。

2009年3月5日星期四

Lua程序设计 第六章 深入函数

1.Lua支持匿名函数。

2.函数存储在table字段中可以支持许多Lua的高级应用,例如:模块和面向对象编程。

3.若将一个函数写在另一个函数中,那么这个位于内部的函数便可以访问外部函数中的局部变量,这项特性称之为“词法域”。

4.函数不仅可以存储在全局变量中,还可以存储在table的字段中和局部变量中。

5.Lua函数支持“尾调用消除(tail-call elimination)”。所谓“尾调用”就是一种类似goto的函数调用。当一个函数调用是另一个函数的最后一个动作,该调用才算是一条“尾调用”。在进行“尾调用”时不耗费任何栈空间。

Lua程序设计 第五章 函数

1.在Lua中,函数是一种对语句和表达式进行抽象的主要机制。

2.一个函数若只有一个参数,并且此参数是一个字符串或table构造式,那么圆括号便可有可无。

3.调用时提供的实参数量可以与形式参数数量不同。Lua会自动调整实参的数量,以匹配参数表的要求。原则是:若实参多于形参,则舍去多于的实参;若实参不足,则多余的形参初始化为nil。

4.Lua允许函数返回多个结果。

5.return后面的内容是不需要圆括号的。在该位置上书写圆括号会导致不同的行为。例如:return(f(x)),将只返回一个值,而无关f返回几个值。

6.Lua中的函数还可以接受不同数量的参数。

7.Lua用...参数表式函数可以接受不同数量的实参。

8.Lua中的参数传递机制是具有“位置性”的,但有时通过名称来指定实参也是很有用的。

2009年3月3日星期二

Lua程序设计 第四章 语句

1.Lua允许多重赋值,也就是将多个值赋予多个变量。

2.Lua用local语句来创建局部变量。

3.尽可能地使用局部变量,局部变量可以避免将一些无用的名称引入全局环境,避免搞乱了全局环境。

4.在需要时才声明变量,可以使这个变量在初始化时刻就拥有一个有意义的初值,缩短变量的作用域有助于提高代码的可读性。

Lua程序设计 第三章 表达式

1.算术操作符:“+”(加法),“-”(减法),“*”(乘法),“/”(除法),“^”(指数),“%”(取模),“-”(负号)

2.关系运算符:“<”(小于),“>”(大于),“<=”(小于等于),“>=”(大于等于),“==”(相等性测试),“~=”(不等性测试)

3.逻辑操作符:and,or,not

4.Lua中使用操作符“..”(两个点)连接两个字符串。

5.构造式是用于创建和初始化table的表达式。

2009年3月2日星期一

Lua程序设计 第二章 类型与值

1.Lua在条件测试中,将数字0和空字符串视为“真”。

2.Lua能够高效处理长字符串,在Lua程序中操作100k或1M的字符串是很常见的。

3.Lua提供运行时的数字与字符串的自动转化,但到现在还不能确定在Lua的设计中,这些自动转化是否是算一项好的设计,建议最好不要依赖它们。

4.定义a为table,a.x和a[x]是不同的,前者表示a["x"],以字符串"x"来索引table。而或者是以变量x的值来索引table。

5.就Lua习惯而言,数组通常以1作为索引的起始值。

6.在Lua中,函数是作为“第一类值”来看待的。这表式函数可以存储在变量中,可以通过参数传递给其它函数,还可以作为其它函数的返回值。

7.userdata用于表式一种由应用程序或C语言库所创建的新类型。