lib/celluloid/actor_proxy.rb in celluloid-0.5.0 vs lib/celluloid/actor_proxy.rb in celluloid-0.6.0

- old
+ new

@@ -1,45 +1,44 @@ module Celluloid # A proxy object returned from Celluloid::Actor.spawn/spawn_link which # dispatches calls and casts to normal Ruby objects which are running inside # of their own threads. class ActorProxy - # FIXME: not nearly enough methods are delegated here attr_reader :mailbox - def initialize(actor, mailbox) - @actor, @mailbox = actor, mailbox + def initialize(mailbox, klass = "Object") + @mailbox, @klass = mailbox, klass end def send(meth, *args, &block) - __call :send, meth, *args, &block + Actor.call @mailbox, :send, meth, *args, &block end def respond_to?(meth) - __call :respond_to?, meth + Actor.call @mailbox, :respond_to?, meth end def methods(include_ancestors = true) - __call :methods, include_ancestors + Actor.call @mailbox, :methods, include_ancestors end def alive? - @actor.alive? + @mailbox.alive? end def to_s - __call :to_s + Actor.call @mailbox, :to_s end def inspect - return __call :inspect if alive? - "#<Celluloid::Actor(#{@actor.class}:0x#{@actor.object_id.to_s(16)}) dead>" + "#<Celluloid::Actor(#{@klass}) dead>" unless alive? + Actor.call @mailbox, :inspect end # Create a Celluloid::Future which calls a given method def future(method_name, *args, &block) - Celluloid::Future.new { __call method_name, *args, &block } + Celluloid::Future.new { Actor.call @mailbox, method_name, *args, &block } end # Terminate the associated actor def terminate raise DeadActorError, "actor already terminated" unless alive? @@ -59,66 +58,13 @@ # method_missing black magic to call bang predicate methods asynchronously def method_missing(meth, *args, &block) # bang methods are async calls if meth.to_s.match(/!$/) unbanged_meth = meth.to_s.sub(/!$/, '') - our_mailbox = Thread.current.mailbox - - begin - @mailbox << AsyncCall.new(our_mailbox, unbanged_meth, args, block) - rescue MailboxError - # Silently swallow asynchronous calls to dead actors. There's no way - # to reliably generate DeadActorErrors for async calls, so users of - # async calls should find other ways to deal with actors dying - # during an async call (i.e. linking/supervisors) - end - - return # casts are async and return immediately + Actor.async @mailbox, unbanged_meth, *args, &block + return end - __call(meth, *args, &block) - end - - ####### - private - ####### - - # Make a synchronous call to the actor we're proxying to - def __call(meth, *args, &block) - our_mailbox = Thread.current.mailbox - call = SyncCall.new(our_mailbox, meth, args, block) - - begin - @mailbox << call - rescue MailboxError - raise DeadActorError, "attempted to call a dead actor" - end - - if Celluloid.actor? - # Yield to the actor scheduler, which resumes us when we get a response - response = Fiber.yield(call) - else - # Otherwise we're inside a normal thread, so block - response = our_mailbox.receive do |msg| - msg.is_a? Response and msg.call == call - end - end - - case response - when SuccessResponse - response.value - when ErrorResponse - ex = response.value - - if ex.is_a? AbortError - # Aborts are caused by caller error, so ensure they capture the - # caller's backtrace instead of the receiver's - raise ex.cause.class.new(ex.cause.message) - else - raise ex - end - else - raise "don't know how to handle #{response.class} messages!" - end + Actor.call @mailbox, meth, *args, &block end end end