From b3422faca8e438fe590693bcf4c4bb0694e7332a Mon Sep 17 00:00:00 2001 From: Tim Carey-Smith Date: Sat, 11 May 2013 00:39:59 +1200 Subject: [PATCH] Invalidate the block on call completion --- lib/celluloid/calls.rb | 5 ++++- lib/celluloid/proxies/block_proxy.rb | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/celluloid/calls.rb b/lib/celluloid/calls.rb index 46718d80..1aad8657 100644 --- a/lib/celluloid/calls.rb +++ b/lib/celluloid/calls.rb @@ -22,7 +22,10 @@ def execute_block_on_receiver def dispatch(obj) _block = @block && @block.to_proc - obj.public_send(@method, *@arguments, &_block) + result = obj.public_send(@method, *@arguments, &_block) + # FIXME: we should only invalidate if the sender is not an actor + @block.invalidate if @block + result rescue NoMethodError => ex # Abort if the sender made a mistake raise AbortError.new(ex) unless obj.respond_to? @method diff --git a/lib/celluloid/proxies/block_proxy.rb b/lib/celluloid/proxies/block_proxy.rb index fea213a2..52daf5cd 100644 --- a/lib/celluloid/proxies/block_proxy.rb +++ b/lib/celluloid/proxies/block_proxy.rb @@ -9,9 +9,14 @@ def initialize(call, mailbox, block) attr_writer :execution attr_reader :call, :block + def invalidate + @invalid = true + end + def to_proc if @execution == :sender lambda do |*values| + raise "The original method call has completed, the block is now invalid" if @invalid if task = Thread.current[:celluloid_task] @mailbox << BlockCall.new(self, Actor.current.mailbox, values) # TODO: if respond fails, the Task will never be resumed