一、Protocol Interaction:actor 间的交互协议
注意:这一部分为高阶内容,使用上较复杂。建议不要轻易尝试。
Celluloid 使用的异步消息协议可以让你直接为 actors 添加某些行为。
想要发送一个原始的异步消息(raw asynchronous message)给 actor,使用Celluloid::Mailbox#<<;
-
actor.mailbox << MyMessage.new
使用 Celluloid#receive 来接收消息。
-
class MyActor
-
include Celluloid
-
-
def initialize
-
async.wait_for_my_messages
-
end
-
-
def wait_for_my_messages
-
loop do
-
message = receive { |msg| msg.is_a? MyMessage }
-
puts "Got a MyMessage: #{message.inspect}"
-
end
-
end
-
end
#receive 方法后跟一个 block,当收到消息后就会将其发送到这个 block 进行逻辑判断,直到收到的消息符合条件,才会返回。
#receive 一被调用即进入睡眠状态,直到接收到符合条件(block 进行判断)的消息。
在 actor 外部使用 #receive 方法基本起不了什么作用。要小心设置 #recevie ,将其放倒发送消息的事务之前,否则你可能会丢失一些 message。
customized actor behaviors:未来可能会实现客户化actor 定制行为。
二、Finite State Machines:有限状态机
Celluloid 描述有限状态机有很多种模式。
1、内建的 FSM 模块:
Celluloid::FSM 是模仿 Erlang语言中的 gen_fsm。功能相对来说较少(某种角度看未尝不是好事),这个模块直接集成在 Celluloid 功能集中,比如 Timer(超时后状态转移)。
示例程序:
-
class Connection
-
default_state :connected
-
-
state :connected, :to => :disconnected do
-
puts "Connected!"
-
end
-
-
state :disconnected
-
end
2、第三方的 RubyGems
三、Finalizers
使用 finalizer 类方法可以在 actor 退出时设置一个回调函数,进行收尾工作:
-
class Foo
-
include Celluloid
-
finalizer :my_finalizer
-
-
def my_finalizer
-
...
-
end
-
end
在 finalizer 中的代码应该进行简单快速,不要涉及复杂的逻辑,不要同其他 actors 进行复杂的交互。滥用 finalizer 可能导致你的 Celluloid 程序无法正常终止。
如果在 finalizer 中调用了其他 actor ,必须采用异步方式。同步调用可能无法返回到正确的 actor 上下文中,因为当前的 actor 很可能已经执行完毕终止了,其 mailbox 也失效了。
-
class Foo
-
include Celluloid
-
finalizer :my_finalizer
-
-
def my_finalizer
-
Actor[:server].some_method # 代码不好, 可能会崩溃
-
Actor[:server].async.some_method # 很好,可以正常工作
-
end
-
end
其他:
使用 Celluloid.kill(actor)时 finalizer 不会被调用。
当前只允许一个 finalizer ,未来版本的 Celluloid 可能允许多个 finalizer。
已废弃功能:
旧版本的 Celluloid 允许你简单的通过 def finalizer 定义 finalizer 。新版本不行,要通过以上方式,调用类方法 finalizer 来定义。
阅读(1370) | 评论(0) | 转发(0) |