一、Protocol Interaction:actor 间的交互协议
https://github.com/celluloid/celluloid/wiki/Protocol-Interaction

注意:这一部分为高阶内容,使用上较复杂。建议不要轻易尝试。

Celluloid 使用的异步消息协议可以让你直接为 actors 添加某些行为。

想要发送一个原始的异步消息(raw asynchronous message)给 actor,使用Celluloid::Mailbox#<
  1. actor.mailbox << MyMessage.new
使用 Celluloid#receive 来接收消息。

  1. class MyActor
  2.   include Celluloid

  3.   def initialize
  4.     async.wait_for_my_messages
  5.   end

  6.   def wait_for_my_messages
  7.     loop do
  8.       message = receive { |msg| msg.is_a? MyMessage }
  9.       puts "Got a MyMessage: #{message.inspect}"
  10.     end
  11.   end
  12. end
#receive 方法后跟一个 block,当收到消息后就会将其发送到这个 block 进行逻辑判断,直到收到的消息符合条件,才会返回。
#receive 一被调用即进入睡眠状态,直到接收到符合条件(block 进行判断)的消息。

在 actor 外部使用 #receive 方法基本起不了什么作用。要小心设置 #recevie ,将其放倒发送消息的事务之前,否则你可能会丢失一些 message。
customized actor behaviors:未来可能会实现客户化actor 定制行为。

二、Finite State Machines:有限状态机
https://github.com/celluloid/celluloid/wiki/Finite-State-Machines
Celluloid 描述有限状态机有很多种模式。

1、内建的 FSM 模块:
Celluloid::FSM 是模仿 Erlang语言中的 gen_fsm。功能相对来说较少(某种角度看未尝不是好事),这个模块直接集成在 Celluloid 功能集中,比如 Timer(超时后状态转移)。
Celluloid::FSM 相关文档

示例程序:
  1. class Connection
  2.   default_state :connected

  3.   state :connected, :to => :disconnected do
  4.     puts "Connected!"
  5.   end

  6.   state :disconnected
  7. end

2、第三方的 RubyGems

stately gem

state_machine gem

statemachine gem

三、Finalizers

使用 finalizer 类方法可以在 actor 退出时设置一个回调函数,进行收尾工作:

  1. class Foo
  2.   include Celluloid
  3.   finalizer :my_finalizer

  4.   def my_finalizer
  5.     ...
  6.   end
  7. end
在 finalizer 中的代码应该进行简单快速,不要涉及复杂的逻辑,不要同其他 actors 进行复杂的交互。滥用 finalizer 可能导致你的 Celluloid 程序无法正常终止。

如果在 finalizer 中调用了其他 actor ,必须采用异步方式。同步调用可能无法返回到正确的 actor 上下文中,因为当前的 actor 很可能已经执行完毕终止了,其 mailbox 也失效了。


  1. class Foo
  2.   include Celluloid
  3.   finalizer :my_finalizer

  4.   def my_finalizer
  5.      Actor[:server].some_method # 代码不好, 可能会崩溃
  6.      Actor[:server].async.some_method # 很好,可以正常工作
  7.   end
  8. end
其他:
使用 Celluloid.kill(actor)时 finalizer 不会被调用。
当前只允许一个 finalizer ,未来版本的 Celluloid 可能允许多个 finalizer。

已废弃功能:
旧版本的 Celluloid 允许你简单的通过 def finalizer 定义 finalizer 。新版本不行,要通过以上方式,调用类方法 finalizer 来定义。
09-04 12:37