lib/celluloid/actor_proxy.rb in celluloid-0.2.2 vs lib/celluloid/actor_proxy.rb in celluloid-0.5.0
- old
+ new
@@ -3,82 +3,92 @@
# 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
end
-
+
def send(meth, *args, &block)
__call :send, meth, *args, &block
end
-
+
def respond_to?(meth)
__call :respond_to?, meth
end
-
+
def methods(include_ancestors = true)
__call :methods, include_ancestors
end
-
+
def alive?
@actor.alive?
end
-
+
def to_s
__call :to_s
end
-
+
def inspect
return __call :inspect if alive?
"#<Celluloid::Actor(#{@actor.class}:0x#{@actor.object_id.to_s(16)}) dead>"
end
-
+
# Create a Celluloid::Future which calls a given method
def future(method_name, *args, &block)
Celluloid::Future.new { __call method_name, *args, &block }
end
-
+
# Terminate the associated actor
def terminate
raise DeadActorError, "actor already terminated" unless alive?
- terminate!
+
+ begin
+ send :terminate
+ rescue DeadActorError
+ # In certain cases this is thrown during termination. This is likely
+ # a bug in Celluloid's internals, but it shouldn't affect the caller.
+ # FIXME: track this down and fix it, or at the very least log it
+ end
+
+ # Always return nil until a dependable exit value can be obtained
+ nil
end
-
+
# 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(/!$/)
+ 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
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
@@ -109,6 +119,6 @@
else
raise "don't know how to handle #{response.class} messages!"
end
end
end
-end
\ No newline at end of file
+end