Continuations 是一种非常强大的控制流机制。一个 Continuation 代表了调用栈和词法变量的特定状态。它是 Ruby 代码执行过程中特定点的一个快照。不幸的是,在 Ruby1.8 的实现中 Continuations 是如此的慢以至于对于许多的应用来说根本无法使用。在即将到来的 Ruby1.9 虚拟机中情况可能会有所改善,但最好不要期望在使用了 Ruby1.8 的 Continuation 的情况下能够获得好的性能。尽管如此,Continuations 仍然是非常有用的概念,基于 Continuations 的 web 框架提供了 Rails 的一些有趣的选择,因此在这里我们会对它们做一下考察。
Continuations之所以非常强大有下面几个原因:
- Continuations其实就是一些对象;它们可以被传递在函数之间。
- 可以从任何位置调用Continuations。只要持有对Continuation的引用,就可以对其进行调用。
- Continuations是可重入的。可以使用Continuations从一个函数多次返回。
Continuations常常被描述为“结构化的GOTO“。因此,它们应该像任何类型的GOTO概念一样被谨慎的对待。在应用代码中不应该出现或者应该极少出现Continuations;它们通常应该被封装在库文件中。我不这么说是因为我认为开发人员应该被与它们隔离开来。
Continuations是如此普遍的一个概念,以至于通常来说在其之上建立抽象比直接使用它更合理。程序员在构建应用软件的时候应考虑使用”外部迭代(external iterator)“或者”协同程序(coroutine)“(两个都是在Continuations之上的抽象)而不是”continuation“。
SeaSide是一个基于Continuations的Smalltalk Web应用框架。Continuations 在SeaSide 中用于管理会话状态。每个用户的会话都对应一个服务器端的Continuation。当一个请求到达的时候Continuation将被调用而且更多的代码被执行。其结果是整个的事务能够被编写为单独的一段代码流,即使它们跨越了多个HTTP请求。这种能力是由于Smalltalk的Continuation能够被序列化;它们可以被写到一个数据库或者文件系统,然后被取出和反序列化,并在请求中重新调用。Ruby的Continuation不能被序列化。在Ruby中,Continuation只能被装载到内存中而不能被转换为一个字节流。
Borges(http://borges.rubyforge.org/)是直接移植到Ruby的Seaside 2实现。SeaSide与Borges的最根本的区别就是Borges必须将所有当前的Continuations保存在内存中,因为它们不能被序列化。这个巨大的限制很不幸地阻止了Borges在任何规模的Web应用中被成功使用。只要Continuation在任何一种Ruby实现中被支持,这个限制就可以被克服了。
Continuation的能力可以通过下面的Borges示例代码来见证,它用于渲染在线商店的一系列条目:
class SushiNet::StoreItemList < Borges::Component
def choose(item)
call SushiNet::StoreItemView.new(item)
end
def initialize(items)
@batcher = Borges::BatchedList.new items, 8
end
def render_content_on(r)
r.list_do @batcher.batch do |item|
r.anchor item.title do choose item end
end
r.render @batcher
end
end # class SushiNet::StoreItemList
Action的功能render_content_on方法中完成,使用了BatchedList(一个分页器)来渲染一组分页的产品链接。有趣的地方在于anchor方法的调用,它存储了choose方法,当相应的链接被点击时调用。
但是,关于Continuations在Web编程中有多大的用处仍然存在着很大争议,HTTP被设计为无状态的协议,使用Continuations来实现Web事务与无状态的想法正好相反。所有的Continuations都被存在服务器端,这需要占用额外的内存和硬盘空间。需要粘性会话(sticky session)来将一个用户始终导向同一台服务器。因此,如果一台服务器当机,它的所有会话都会丢失。最流行的基于Seaside的应用DabbleDB(http://dabbledb.com)事实上很少使用Continuations。


















发表留言