Skip to content

Commit

Permalink
Celluloid::FutureProxy for future.method syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
tarcieri committed Sep 3, 2012
1 parent 1ac52fd commit ad7f9ab
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 18 deletions.
1 change: 1 addition & 0 deletions lib/celluloid.rb
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ def future(meth, *args, &block)
require 'celluloid/proxies/abstract_proxy'
require 'celluloid/proxies/actor_proxy'
require 'celluloid/proxies/async_proxy'
require 'celluloid/proxies/future_proxy'

require 'celluloid/actor'
require 'celluloid/future'
Expand Down
18 changes: 10 additions & 8 deletions lib/celluloid/proxies/actor_proxy.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
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.
# A proxy object returned from Celluloid::Actor.new/new_link which converts
# the normal Ruby method protocol into an inter-actor message protocol
class ActorProxy < AbstractProxy
attr_reader :mailbox, :thread

Expand Down Expand Up @@ -55,8 +54,7 @@ def to_s
Actor.call @mailbox, :to_s
end

# Make an asynchronous call to an actor, for those who don't like the
# predicate syntax. TIMTOWTDI!
# Obtain an async proxy or explicitly invoke a named async method
def async(method_name = nil, *args, &block)
if method_name
Actor.async @mailbox, method_name, *args, &block
Expand All @@ -65,9 +63,13 @@ def async(method_name = nil, *args, &block)
end
end

# Create a Celluloid::Future which calls a given method
def future(method_name, *args, &block)
Actor.future @mailbox, method_name, *args, &block
# Obtain a future proxy or explicitly invoke a named future method
def future(method_name = nil, *args, &block)
if method_name
Actor.future @mailbox, method_name, *args, &block
else
FutureProxy.new(@mailbox, @klass)
end
end

# Terminate the associated actor
Expand Down
4 changes: 1 addition & 3 deletions lib/celluloid/proxies/async_proxy.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
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.
# A proxy which sends asynchronous calls to an actor
class AsyncProxy < AbstractProxy
attr_reader :mailbox

Expand Down
19 changes: 19 additions & 0 deletions lib/celluloid/proxies/future_proxy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module Celluloid
# A proxy which creates future calls to an actor
class FutureProxy < AbstractProxy
attr_reader :mailbox

def initialize(mailbox, klass)
@mailbox, @klass = mailbox, klass
end

def inspect
"#<Celluloid::FutureProxy(#{@klass})>"
end

# method_missing black magic to call bang predicate methods asynchronously
def method_missing(meth, *args, &block)
Actor.future @mailbox, meth, *args, &block
end
end
end
20 changes: 13 additions & 7 deletions spec/support/actor_examples.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,28 @@ class ExampleCrash < StandardError
actor.object_id.should_not == Kernel.object_id
end

it "handles synchronous calls" do
it "supports synchronous calls" do
actor = actor_class.new "Troy McClure"
actor.greet.should == "Hi, I'm Troy McClure"
end

it "handles synchronous calls via #method" do
it "supports synchronous calls via #method" do
method = actor_class.new("Troy McClure").method(:greet)
method.call.should == "Hi, I'm Troy McClure"
end

it "handles futures for synchronous calls" do
it "supports future(:method) syntax for synchronous future calls" do
actor = actor_class.new "Troy McClure"
future = actor.future :greet
future.value.should == "Hi, I'm Troy McClure"
end

it "supports future.method syntax for synchronous future calls" do
actor = actor_class.new "Troy McClure"
future = actor.future.greet
future.value.should == "Hi, I'm Troy McClure"
end

it "handles circular synchronous calls" do
klass = Class.new do
include included_module
Expand Down Expand Up @@ -136,25 +142,25 @@ def to_s
end.to raise_exception(Celluloid::DeadActorError)
end

it "handles asynchronous calls" do
it "supports method! syntax for asynchronous calls" do
actor = actor_class.new "Troy McClure"
actor.change_name! "Charlie Sheen"
actor.greet.should == "Hi, I'm Charlie Sheen"
end

it "handles asynchronous calls via async(:meth)" do
it "supports async(:method) syntax for asynchronous calls" do
actor = actor_class.new "Troy McClure"
actor.async :change_name, "Charlie Sheen"
actor.greet.should == "Hi, I'm Charlie Sheen"
end

it "handles asynchronous calls via async.meth" do
it "supports async.method syntax for asynchronous calls" do
actor = actor_class.new "Troy McClure"
actor.async.change_name "Charlie Sheen"
actor.greet.should == "Hi, I'm Charlie Sheen"
end

it "handles asynchronous calls to itself" do
it "supports asynchronous calls to itself" do
actor = actor_class.new "Troy McClure"
actor.change_name_async "Charlie Sheen"
actor.greet.should == "Hi, I'm Charlie Sheen"
Expand Down

0 comments on commit ad7f9ab

Please sign in to comment.