celluloid 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +36 -2
 - data/lib/celluloid.rb +62 -2
 - data/lib/celluloid/actor.rb +113 -86
 - data/lib/celluloid/actor_pool.rb +9 -9
 - data/lib/celluloid/actor_proxy.rb +13 -67
 - data/lib/celluloid/application.rb +78 -0
 - data/lib/celluloid/calls.rb +28 -22
 - data/lib/celluloid/fibers_are_hard.rb +33 -0
 - data/lib/celluloid/io.rb +1 -27
 - data/lib/celluloid/io/mailbox.rb +2 -2
 - data/lib/celluloid/io/reactor.rb +1 -1
 - data/lib/celluloid/linking.rb +1 -1
 - data/lib/celluloid/mailbox.rb +6 -1
 - data/lib/celluloid/receivers.rb +36 -0
 - data/lib/celluloid/responses.rb +14 -4
 - data/lib/celluloid/signals.rb +3 -1
 - data/lib/celluloid/supervisor.rb +24 -11
 - data/lib/celluloid/version.rb +1 -1
 - metadata +27 -24
 - data/lib/celluloid/io/actor.rb +0 -10
 
    
        data/README.md
    CHANGED
    
    | 
         @@ -357,13 +357,43 @@ send them a value in the process: 
     | 
|
| 
       357 
357 
     | 
    
         
             
            	  end
         
     | 
| 
       358 
358 
     | 
    
         
             
            	end
         
     | 
| 
       359 
359 
     | 
    
         | 
| 
       360 
     | 
    
         
            -
            The wait_for_signal method in turn calls a method called "wait". Wait suspends
         
     | 
| 
      
 360 
     | 
    
         
            +
            The #wait_for_signal method in turn calls a method called "wait". Wait suspends
         
     | 
| 
       361 
361 
     | 
    
         
             
            the running method until another method of the same object calls the "signal"
         
     | 
| 
       362 
362 
     | 
    
         
             
            method with the same label.
         
     | 
| 
       363 
363 
     | 
    
         | 
| 
       364 
     | 
    
         
            -
            The send_signal method of this class does just that, signaling "ponycopter"
         
     | 
| 
      
 364 
     | 
    
         
            +
            The #send_signal method of this class does just that, signaling "ponycopter"
         
     | 
| 
       365 
365 
     | 
    
         
             
            with the given value. This value is returned from the original wait call.
         
     | 
| 
       366 
366 
     | 
    
         | 
| 
      
 367 
     | 
    
         
            +
            Protocol Interaction
         
     | 
| 
      
 368 
     | 
    
         
            +
            --------------------
         
     | 
| 
      
 369 
     | 
    
         
            +
             
     | 
| 
      
 370 
     | 
    
         
            +
            The asynchronous message protocol Celluloid uses can be used directly to add
         
     | 
| 
      
 371 
     | 
    
         
            +
            new behavior to actors.
         
     | 
| 
      
 372 
     | 
    
         
            +
             
     | 
| 
      
 373 
     | 
    
         
            +
            To send a raw asynchronous message to an actor, use:
         
     | 
| 
      
 374 
     | 
    
         
            +
             
     | 
| 
      
 375 
     | 
    
         
            +
                actor.mailbox << MyMessage.new
         
     | 
| 
      
 376 
     | 
    
         
            +
             
     | 
| 
      
 377 
     | 
    
         
            +
            Methods can wait on incoming MyMessage objects using the #receive method:
         
     | 
| 
      
 378 
     | 
    
         
            +
             
     | 
| 
      
 379 
     | 
    
         
            +
                class MyActor
         
     | 
| 
      
 380 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 381 
     | 
    
         
            +
                    wait_for_my_messages!
         
     | 
| 
      
 382 
     | 
    
         
            +
                  end
         
     | 
| 
      
 383 
     | 
    
         
            +
             
     | 
| 
      
 384 
     | 
    
         
            +
                  def wait_for_my_messages
         
     | 
| 
      
 385 
     | 
    
         
            +
                    loop do
         
     | 
| 
      
 386 
     | 
    
         
            +
                      message = receive { |msg| msg.is_a? MyMessage }
         
     | 
| 
      
 387 
     | 
    
         
            +
            		  puts "Got a MyMessage: #{message.inspect}"
         
     | 
| 
      
 388 
     | 
    
         
            +
                    end
         
     | 
| 
      
 389 
     | 
    
         
            +
                  end
         
     | 
| 
      
 390 
     | 
    
         
            +
                end
         
     | 
| 
      
 391 
     | 
    
         
            +
             
     | 
| 
      
 392 
     | 
    
         
            +
            The #receive method takes a block, and yields any incoming messages which are
         
     | 
| 
      
 393 
     | 
    
         
            +
            received by the current actor to the block, waiting for the block to return
         
     | 
| 
      
 394 
     | 
    
         
            +
            true. Calls to #receive sleep until a message is received which makes the
         
     | 
| 
      
 395 
     | 
    
         
            +
            block return true, at which point the matching message is returned.
         
     | 
| 
      
 396 
     | 
    
         
            +
             
     | 
| 
       367 
397 
     | 
    
         
             
            Handling I/O with Celluloid::IO
         
     | 
| 
       368 
398 
     | 
    
         
             
            -------------------------------
         
     | 
| 
       369 
399 
     | 
    
         | 
| 
         @@ -456,6 +486,10 @@ Here are a few rules you can follow to keep this from happening: 
     | 
|
| 
       456 
486 
     | 
    
         
             
               using Fibers, and why can't it be solved by a block? If you've got a really
         
     | 
| 
       457 
487 
     | 
    
         
             
               good reason and you're feeling lucky, knock yourself out.
         
     | 
| 
       458 
488 
     | 
    
         | 
| 
      
 489 
     | 
    
         
            +
            5. If you need to mock the behaviour of an Actor, you should mock its subject
         
     | 
| 
      
 490 
     | 
    
         
            +
               rather than the proxy itself (#actor_subject). This ensures that any time
         
     | 
| 
      
 491 
     | 
    
         
            +
               the subject calls methods on self, they will also be appropriately mocked.
         
     | 
| 
      
 492 
     | 
    
         
            +
             
     | 
| 
       459 
493 
     | 
    
         
             
            On Thread Safety in Ruby
         
     | 
| 
       460 
494 
     | 
    
         
             
            ------------------------
         
     | 
| 
       461 
495 
     | 
    
         | 
    
        data/lib/celluloid.rb
    CHANGED
    
    | 
         @@ -1,4 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'logger'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'thread'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'celluloid/fibers_are_hard'
         
     | 
| 
       2 
4 
     | 
    
         | 
| 
       3 
5 
     | 
    
         
             
            module Celluloid
         
     | 
| 
       4 
6 
     | 
    
         
             
              @logger = Logger.new STDERR
         
     | 
| 
         @@ -23,6 +25,41 @@ module Celluloid 
     | 
|
| 
       23 
25 
     | 
    
         | 
| 
       24 
26 
     | 
    
         
             
                  actor
         
     | 
| 
       25 
27 
     | 
    
         
             
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                # Receive an asynchronous message
         
     | 
| 
      
 30 
     | 
    
         
            +
                def receive(&block)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  actor = Thread.current[:actor]
         
     | 
| 
      
 32 
     | 
    
         
            +
                  if actor
         
     | 
| 
      
 33 
     | 
    
         
            +
                    actor.receive(&block)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  else
         
     | 
| 
      
 35 
     | 
    
         
            +
                    Thread.current.mailbox.receive(&block)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                # Create a fiber that participates in the Celluloid protocol
         
     | 
| 
      
 40 
     | 
    
         
            +
                def fiber(*args)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  actor   = Thread.current[:actor]
         
     | 
| 
      
 42 
     | 
    
         
            +
                  proxy   = Thread.current[:actor_proxy]
         
     | 
| 
      
 43 
     | 
    
         
            +
                  mailbox = Thread.current[:mailbox]
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  Fiber.new do
         
     | 
| 
      
 46 
     | 
    
         
            +
                    Thread.current[:actor]       = actor
         
     | 
| 
      
 47 
     | 
    
         
            +
                    Thread.current[:actor_proxy] = proxy
         
     | 
| 
      
 48 
     | 
    
         
            +
                    Thread.current[:mailbox]     = mailbox
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                    yield(*args)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                # Resume a fiber that participates in the Celluloid protocol
         
     | 
| 
      
 55 
     | 
    
         
            +
                def resume_fiber(fiber, value = nil)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  actor = Thread.current[:actor]
         
     | 
| 
      
 57 
     | 
    
         
            +
                  if actor
         
     | 
| 
      
 58 
     | 
    
         
            +
                    actor.run_fiber fiber, value
         
     | 
| 
      
 59 
     | 
    
         
            +
                  else
         
     | 
| 
      
 60 
     | 
    
         
            +
                    fiber.resume value
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
       26 
63 
     | 
    
         
             
              end
         
     | 
| 
       27 
64 
     | 
    
         | 
| 
       28 
65 
     | 
    
         
             
              # Class methods added to classes which include Celluloid
         
     | 
| 
         @@ -64,8 +101,17 @@ module Celluloid 
     | 
|
| 
       64 
101 
     | 
    
         
             
                  @exit_handler = callback.to_sym
         
     | 
| 
       65 
102 
     | 
    
         
             
                end
         
     | 
| 
       66 
103 
     | 
    
         | 
| 
       67 
     | 
    
         
            -
                # Obtain the exit handler  
     | 
| 
       68 
     | 
    
         
            -
                 
     | 
| 
      
 104 
     | 
    
         
            +
                # Obtain the exit handler for this actor
         
     | 
| 
      
 105 
     | 
    
         
            +
                attr_reader :exit_handler
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                # Configure a custom mailbox factory
         
     | 
| 
      
 108 
     | 
    
         
            +
                def use_mailbox(klass = nil, &block)
         
     | 
| 
      
 109 
     | 
    
         
            +
                  if block
         
     | 
| 
      
 110 
     | 
    
         
            +
                    define_method(:mailbox_factory, &block)
         
     | 
| 
      
 111 
     | 
    
         
            +
                  else
         
     | 
| 
      
 112 
     | 
    
         
            +
                    define_method(:mailbox_factory) { klass.new }
         
     | 
| 
      
 113 
     | 
    
         
            +
                  end
         
     | 
| 
      
 114 
     | 
    
         
            +
                end
         
     | 
| 
       69 
115 
     | 
    
         
             
              end
         
     | 
| 
       70 
116 
     | 
    
         | 
| 
       71 
117 
     | 
    
         
             
              #
         
     | 
| 
         @@ -112,6 +158,18 @@ module Celluloid 
     | 
|
| 
       112 
158 
     | 
    
         
             
                Celluloid.current_actor
         
     | 
| 
       113 
159 
     | 
    
         
             
              end
         
     | 
| 
       114 
160 
     | 
    
         | 
| 
      
 161 
     | 
    
         
            +
              # Obtain the Ruby object the actor is wrapping. This should ONLY be used
         
     | 
| 
      
 162 
     | 
    
         
            +
              # for a limited set of use cases like runtime metaprogramming. Interacting
         
     | 
| 
      
 163 
     | 
    
         
            +
              # directly with the wrapped object foregoes any kind of thread safety that
         
     | 
| 
      
 164 
     | 
    
         
            +
              # Celluloid would ordinarily provide you, and the object is guaranteed to
         
     | 
| 
      
 165 
     | 
    
         
            +
              # be shared with at least the actor thread. Tread carefully.
         
     | 
| 
      
 166 
     | 
    
         
            +
              def wrapped_object; self; end
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
              # Receive an asynchronous message via the actor protocol
         
     | 
| 
      
 169 
     | 
    
         
            +
              def receive(&block)
         
     | 
| 
      
 170 
     | 
    
         
            +
                Celluloid.receive(&block)
         
     | 
| 
      
 171 
     | 
    
         
            +
              end
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
       115 
173 
     | 
    
         
             
              # Perform a blocking or computationally intensive action inside an
         
     | 
| 
       116 
174 
     | 
    
         
             
              # asynchronous thread pool, allowing the caller to continue processing other
         
     | 
| 
       117 
175 
     | 
    
         
             
              # messages in its mailbox in the meantime
         
     | 
| 
         @@ -151,6 +209,7 @@ require 'celluloid/core_ext' 
     | 
|
| 
       151 
209 
     | 
    
         
             
            require 'celluloid/events'
         
     | 
| 
       152 
210 
     | 
    
         
             
            require 'celluloid/linking'
         
     | 
| 
       153 
211 
     | 
    
         
             
            require 'celluloid/mailbox'
         
     | 
| 
      
 212 
     | 
    
         
            +
            require 'celluloid/receivers'
         
     | 
| 
       154 
213 
     | 
    
         
             
            require 'celluloid/registry'
         
     | 
| 
       155 
214 
     | 
    
         
             
            require 'celluloid/responses'
         
     | 
| 
       156 
215 
     | 
    
         
             
            require 'celluloid/signals'
         
     | 
| 
         @@ -159,6 +218,7 @@ require 'celluloid/actor' 
     | 
|
| 
       159 
218 
     | 
    
         
             
            require 'celluloid/actor_pool'
         
     | 
| 
       160 
219 
     | 
    
         
             
            require 'celluloid/supervisor'
         
     | 
| 
       161 
220 
     | 
    
         
             
            require 'celluloid/future'
         
     | 
| 
      
 221 
     | 
    
         
            +
            require 'celluloid/application'
         
     | 
| 
       162 
222 
     | 
    
         | 
| 
       163 
223 
     | 
    
         
             
            require 'celluloid/io'
         
     | 
| 
       164 
224 
     | 
    
         
             
            require 'celluloid/tcp_server'
         
     | 
    
        data/lib/celluloid/actor.rb
    CHANGED
    
    | 
         @@ -1,18 +1,3 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'thread'
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            begin
         
     | 
| 
       4 
     | 
    
         
            -
              require 'fiber'
         
     | 
| 
       5 
     | 
    
         
            -
            rescue LoadError => ex
         
     | 
| 
       6 
     | 
    
         
            -
              if defined? JRUBY_VERSION
         
     | 
| 
       7 
     | 
    
         
            -
                raise LoadError, "Celluloid requires JRuby 1.9 mode. Please pass the --1.9 flag or set JRUBY_OPTS=--1.9"
         
     | 
| 
       8 
     | 
    
         
            -
              elsif defined? Rubinius
         
     | 
| 
       9 
     | 
    
         
            -
                # If we're on Rubinius, we can still work in 1.8 mode
         
     | 
| 
       10 
     | 
    
         
            -
                Fiber = Rubinius::Fiber
         
     | 
| 
       11 
     | 
    
         
            -
              else
         
     | 
| 
       12 
     | 
    
         
            -
                raise ex
         
     | 
| 
       13 
     | 
    
         
            -
              end
         
     | 
| 
       14 
     | 
    
         
            -
            end
         
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
1 
     | 
    
         
             
            module Celluloid
         
     | 
| 
       17 
2 
     | 
    
         
             
              # Don't do Actor-like things outside Actor scope
         
     | 
| 
       18 
3 
     | 
    
         
             
              class NotActorError < StandardError; end
         
     | 
| 
         @@ -41,47 +26,67 @@ module Celluloid 
     | 
|
| 
       41 
26 
     | 
    
         
             
                attr_reader :links
         
     | 
| 
       42 
27 
     | 
    
         
             
                attr_reader :mailbox
         
     | 
| 
       43 
28 
     | 
    
         | 
| 
      
 29 
     | 
    
         
            +
                # Invoke a method on the given actor via its mailbox
         
     | 
| 
      
 30 
     | 
    
         
            +
                def self.call(mailbox, meth, *args, &block)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  our_mailbox = Thread.current.mailbox
         
     | 
| 
      
 32 
     | 
    
         
            +
                  call = SyncCall.new(our_mailbox, meth, args, block)
         
     | 
| 
       44 
33 
     | 
    
         | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
                   
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
                  @links   = Links.new
         
     | 
| 
       50 
     | 
    
         
            -
                  @signals = Signals.new
         
     | 
| 
       51 
     | 
    
         
            -
                  @proxy   = ActorProxy.new(self, @mailbox)
         
     | 
| 
       52 
     | 
    
         
            -
                  @running = true
         
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
                  @thread = Pool.get
         
     | 
| 
       55 
     | 
    
         
            -
                  @thread[:queue] << proc do
         
     | 
| 
       56 
     | 
    
         
            -
                    initialize_thread_locals
         
     | 
| 
       57 
     | 
    
         
            -
                    run
         
     | 
| 
      
 34 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 35 
     | 
    
         
            +
                    mailbox << call
         
     | 
| 
      
 36 
     | 
    
         
            +
                  rescue MailboxError
         
     | 
| 
      
 37 
     | 
    
         
            +
                    raise DeadActorError, "attempted to call a dead actor"
         
     | 
| 
       58 
38 
     | 
    
         
             
                  end
         
     | 
| 
       59 
     | 
    
         
            -
                end
         
     | 
| 
       60 
39 
     | 
    
         | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
             
     | 
| 
      
 40 
     | 
    
         
            +
                  if Celluloid.actor?
         
     | 
| 
      
 41 
     | 
    
         
            +
                    # Yield to the actor scheduler, which resumes us when we get a response
         
     | 
| 
      
 42 
     | 
    
         
            +
                    response = Fiber.yield(call)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  else
         
     | 
| 
      
 44 
     | 
    
         
            +
                    # Otherwise we're inside a normal thread, so block
         
     | 
| 
      
 45 
     | 
    
         
            +
                    response = our_mailbox.receive do |msg|
         
     | 
| 
      
 46 
     | 
    
         
            +
                      msg.is_a? Response and msg.call_id == call.id
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  response.value
         
     | 
| 
       67 
51 
     | 
    
         
             
                end
         
     | 
| 
       68 
52 
     | 
    
         | 
| 
       69 
     | 
    
         
            -
                #  
     | 
| 
       70 
     | 
    
         
            -
                def  
     | 
| 
       71 
     | 
    
         
            -
                  Thread.current 
     | 
| 
       72 
     | 
    
         
            -
                   
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
      
 53 
     | 
    
         
            +
                # Invoke a method asynchronously on an actor via its mailbox
         
     | 
| 
      
 54 
     | 
    
         
            +
                def self.async(mailbox, meth, *args, &block)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  our_mailbox = Thread.current.mailbox
         
     | 
| 
      
 56 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 57 
     | 
    
         
            +
                    mailbox << AsyncCall.new(our_mailbox, meth, args, block)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  rescue MailboxError
         
     | 
| 
      
 59 
     | 
    
         
            +
                    # Silently swallow asynchronous calls to dead actors. There's no way
         
     | 
| 
      
 60 
     | 
    
         
            +
                    # to reliably generate DeadActorErrors for async calls, so users of
         
     | 
| 
      
 61 
     | 
    
         
            +
                    # async calls should find other ways to deal with actors dying
         
     | 
| 
      
 62 
     | 
    
         
            +
                    # during an async call (i.e. linking/supervisors)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
       74 
64 
     | 
    
         
             
                end
         
     | 
| 
       75 
65 
     | 
    
         | 
| 
       76 
     | 
    
         
            -
                #  
     | 
| 
       77 
     | 
    
         
            -
                def  
     | 
| 
       78 
     | 
    
         
            -
                   
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
       82 
     | 
    
         
            -
                   
     | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
     | 
    
         
            -
                   
     | 
| 
      
 66 
     | 
    
         
            +
                # Wrap the given subject with an Actor
         
     | 
| 
      
 67 
     | 
    
         
            +
                def initialize(subject)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  @subject = subject
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  if subject.respond_to? :mailbox_factory
         
     | 
| 
      
 71 
     | 
    
         
            +
                    @mailbox = subject.mailbox_factory
         
     | 
| 
      
 72 
     | 
    
         
            +
                  else
         
     | 
| 
      
 73 
     | 
    
         
            +
                    @mailbox = Celluloid::Mailbox.new
         
     | 
| 
      
 74 
     | 
    
         
            +
                  end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                  @links     = Links.new
         
     | 
| 
      
 77 
     | 
    
         
            +
                  @signals   = Signals.new
         
     | 
| 
      
 78 
     | 
    
         
            +
                  @receivers = Receivers.new
         
     | 
| 
      
 79 
     | 
    
         
            +
                  @proxy     = ActorProxy.new(@mailbox)
         
     | 
| 
      
 80 
     | 
    
         
            +
                  @running   = true
         
     | 
| 
      
 81 
     | 
    
         
            +
                  @pending_calls = {}
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                  @thread = Pool.get do
         
     | 
| 
      
 84 
     | 
    
         
            +
                    Thread.current[:actor]       = self
         
     | 
| 
      
 85 
     | 
    
         
            +
                    Thread.current[:actor_proxy] = @proxy
         
     | 
| 
      
 86 
     | 
    
         
            +
                    Thread.current[:mailbox]     = @mailbox
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                    run
         
     | 
| 
      
 89 
     | 
    
         
            +
                  end
         
     | 
| 
       85 
90 
     | 
    
         
             
                end
         
     | 
| 
       86 
91 
     | 
    
         | 
| 
       87 
92 
     | 
    
         
             
                # Is this actor alive?
         
     | 
| 
         @@ -105,56 +110,72 @@ module Celluloid 
     | 
|
| 
       105 
110 
     | 
    
         
             
                  @signals.wait name
         
     | 
| 
       106 
111 
     | 
    
         
             
                end
         
     | 
| 
       107 
112 
     | 
    
         | 
| 
       108 
     | 
    
         
            -
                 
     | 
| 
       109 
     | 
    
         
            -
                 
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
                # Process incoming messages
         
     | 
| 
       113 
     | 
    
         
            -
                def process_messages
         
     | 
| 
       114 
     | 
    
         
            -
                  pending_calls = {}
         
     | 
| 
      
 113 
     | 
    
         
            +
                # Receive an asynchronous message
         
     | 
| 
      
 114 
     | 
    
         
            +
                def receive(&block)
         
     | 
| 
      
 115 
     | 
    
         
            +
                  @receivers.receive(&block)
         
     | 
| 
      
 116 
     | 
    
         
            +
                end
         
     | 
| 
       115 
117 
     | 
    
         | 
| 
      
 118 
     | 
    
         
            +
                # Run the actor loop
         
     | 
| 
      
 119 
     | 
    
         
            +
                def run
         
     | 
| 
       116 
120 
     | 
    
         
             
                  while @running
         
     | 
| 
       117 
121 
     | 
    
         
             
                    begin
         
     | 
| 
       118 
122 
     | 
    
         
             
                      message = @mailbox.receive
         
     | 
| 
       119 
     | 
    
         
            -
                    rescue MailboxShutdown
         
     | 
| 
       120 
     | 
    
         
            -
                      # If the mailbox detects shutdown, exit the actor
         
     | 
| 
       121 
     | 
    
         
            -
                      @running = false
         
     | 
| 
       122 
123 
     | 
    
         
             
                    rescue ExitEvent => exit_event
         
     | 
| 
       123 
     | 
    
         
            -
                      fiber =  
     | 
| 
       124 
     | 
    
         
            -
             
     | 
| 
       125 
     | 
    
         
            -
                        handle_exit_event exit_event
         
     | 
| 
       126 
     | 
    
         
            -
                      end
         
     | 
| 
       127 
     | 
    
         
            -
             
     | 
| 
       128 
     | 
    
         
            -
                      call = fiber.resume
         
     | 
| 
       129 
     | 
    
         
            -
                      pending_calls[call] = fiber if fiber.alive?
         
     | 
| 
       130 
     | 
    
         
            -
             
     | 
| 
      
 124 
     | 
    
         
            +
                      fiber = Celluloid.fiber { handle_exit_event exit_event; nil }
         
     | 
| 
      
 125 
     | 
    
         
            +
                      run_fiber fiber
         
     | 
| 
       131 
126 
     | 
    
         
             
                      retry
         
     | 
| 
       132 
127 
     | 
    
         
             
                    end
         
     | 
| 
       133 
128 
     | 
    
         | 
| 
       134 
     | 
    
         
            -
                     
     | 
| 
       135 
     | 
    
         
            -
                    when Call
         
     | 
| 
       136 
     | 
    
         
            -
                      fiber = Fiber.new do
         
     | 
| 
       137 
     | 
    
         
            -
                        initialize_thread_locals
         
     | 
| 
       138 
     | 
    
         
            -
                        message.dispatch(@subject)
         
     | 
| 
       139 
     | 
    
         
            -
                      end
         
     | 
| 
       140 
     | 
    
         
            -
             
     | 
| 
       141 
     | 
    
         
            -
                      call = fiber.resume
         
     | 
| 
       142 
     | 
    
         
            -
                      pending_calls[call] = fiber if fiber.alive?
         
     | 
| 
       143 
     | 
    
         
            -
                    when Response
         
     | 
| 
       144 
     | 
    
         
            -
                      fiber = pending_calls.delete(message.call)
         
     | 
| 
       145 
     | 
    
         
            -
             
     | 
| 
       146 
     | 
    
         
            -
                      if fiber
         
     | 
| 
       147 
     | 
    
         
            -
                        call = fiber.resume message
         
     | 
| 
       148 
     | 
    
         
            -
                        pending_calls[call] = fiber if fiber.alive?
         
     | 
| 
       149 
     | 
    
         
            -
                      end
         
     | 
| 
       150 
     | 
    
         
            -
                    end # unexpected messages are ignored
         
     | 
| 
      
 129 
     | 
    
         
            +
                    handle_message message
         
     | 
| 
       151 
130 
     | 
    
         
             
                  end
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
                  cleanup ExitEvent.new(@proxy)
         
     | 
| 
      
 133 
     | 
    
         
            +
                rescue MailboxShutdown
         
     | 
| 
      
 134 
     | 
    
         
            +
                  # If the mailbox detects shutdown, exit the actor
         
     | 
| 
      
 135 
     | 
    
         
            +
                  @running = false
         
     | 
| 
      
 136 
     | 
    
         
            +
                rescue Exception => ex
         
     | 
| 
      
 137 
     | 
    
         
            +
                  @running = false
         
     | 
| 
      
 138 
     | 
    
         
            +
                  handle_crash(ex)
         
     | 
| 
      
 139 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 140 
     | 
    
         
            +
                  Pool.put @thread
         
     | 
| 
      
 141 
     | 
    
         
            +
                end
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                # Run a method, handling when its Fiber is suspended
         
     | 
| 
      
 144 
     | 
    
         
            +
                def run_fiber(fiber, value = nil)
         
     | 
| 
      
 145 
     | 
    
         
            +
                  result = fiber.resume value
         
     | 
| 
      
 146 
     | 
    
         
            +
                  if result.is_a? Celluloid::Call
         
     | 
| 
      
 147 
     | 
    
         
            +
                    @pending_calls[result.id] = fiber if fiber.alive?
         
     | 
| 
      
 148 
     | 
    
         
            +
                  elsif result
         
     | 
| 
      
 149 
     | 
    
         
            +
                    warning = "non-call returned from fiber: #{result.class}"
         
     | 
| 
      
 150 
     | 
    
         
            +
                    Celluloid.logger.debug warning if Celluloid.logger
         
     | 
| 
      
 151 
     | 
    
         
            +
                  end
         
     | 
| 
      
 152 
     | 
    
         
            +
                  nil
         
     | 
| 
      
 153 
     | 
    
         
            +
                end
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
                # Handle an incoming message
         
     | 
| 
      
 156 
     | 
    
         
            +
                def handle_message(message)
         
     | 
| 
      
 157 
     | 
    
         
            +
                  case message
         
     | 
| 
      
 158 
     | 
    
         
            +
                  when Call
         
     | 
| 
      
 159 
     | 
    
         
            +
                    fiber = Celluloid.fiber { message.dispatch(@subject); nil }
         
     | 
| 
      
 160 
     | 
    
         
            +
                    run_fiber fiber
         
     | 
| 
      
 161 
     | 
    
         
            +
                  when Response
         
     | 
| 
      
 162 
     | 
    
         
            +
                    fiber = @pending_calls.delete(message.call_id)
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
                    if fiber
         
     | 
| 
      
 165 
     | 
    
         
            +
                      run_fiber fiber, message
         
     | 
| 
      
 166 
     | 
    
         
            +
                    else
         
     | 
| 
      
 167 
     | 
    
         
            +
                      warning = "spurious response to call #{message.call_id}"
         
     | 
| 
      
 168 
     | 
    
         
            +
                      Celluloid.logger.debug if Celluloid.logger
         
     | 
| 
      
 169 
     | 
    
         
            +
                    end
         
     | 
| 
      
 170 
     | 
    
         
            +
                  else
         
     | 
| 
      
 171 
     | 
    
         
            +
                    @receivers.handle_message(message)
         
     | 
| 
      
 172 
     | 
    
         
            +
                  end
         
     | 
| 
      
 173 
     | 
    
         
            +
                  message
         
     | 
| 
       152 
174 
     | 
    
         
             
                end
         
     | 
| 
       153 
175 
     | 
    
         | 
| 
       154 
176 
     | 
    
         
             
                # Handle exit events received by this actor
         
     | 
| 
       155 
177 
     | 
    
         
             
                def handle_exit_event(exit_event)
         
     | 
| 
       156 
     | 
    
         
            -
                   
     | 
| 
       157 
     | 
    
         
            -
                  exit_handler = klass.exit_handler if klass.respond_to? :exit_handler
         
     | 
| 
      
 178 
     | 
    
         
            +
                  exit_handler = @subject.class.exit_handler
         
     | 
| 
       158 
179 
     | 
    
         
             
                  if exit_handler
         
     | 
| 
       159 
180 
     | 
    
         
             
                    return @subject.send(exit_handler, exit_event.actor, exit_event.reason)
         
     | 
| 
       160 
181 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -176,6 +197,12 @@ module Celluloid 
     | 
|
| 
       176 
197 
     | 
    
         
             
                def cleanup(exit_event)
         
     | 
| 
       177 
198 
     | 
    
         
             
                  @mailbox.shutdown
         
     | 
| 
       178 
199 
     | 
    
         
             
                  @links.send_event exit_event
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
      
 201 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 202 
     | 
    
         
            +
                    @subject.finalize if @subject.respond_to? :finalize
         
     | 
| 
      
 203 
     | 
    
         
            +
                  rescue Exception => finalizer_exception
         
     | 
| 
      
 204 
     | 
    
         
            +
                    log_error(finalizer_exception, "#{@subject.class}#finalize crashed!")
         
     | 
| 
      
 205 
     | 
    
         
            +
                  end
         
     | 
| 
       179 
206 
     | 
    
         
             
                end
         
     | 
| 
       180 
207 
     | 
    
         | 
| 
       181 
208 
     | 
    
         
             
                # Log errors when an actor crashes
         
     | 
    
        data/lib/celluloid/actor_pool.rb
    CHANGED
    
    | 
         @@ -11,20 +11,23 @@ module Celluloid 
     | 
|
| 
       11 
11 
     | 
    
         
             
                  class << self
         
     | 
| 
       12 
12 
     | 
    
         
             
                    attr_accessor :max_idle
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                    def get
         
     | 
| 
      
 14 
     | 
    
         
            +
                    def get(&block)
         
     | 
| 
       15 
15 
     | 
    
         
             
                      @lock.synchronize do
         
     | 
| 
       16 
16 
     | 
    
         
             
                        if @pool.empty?
         
     | 
| 
       17 
     | 
    
         
            -
                          create
         
     | 
| 
      
 17 
     | 
    
         
            +
                          thread = create
         
     | 
| 
       18 
18 
     | 
    
         
             
                        else
         
     | 
| 
       19 
     | 
    
         
            -
                          @pool.shift
         
     | 
| 
      
 19 
     | 
    
         
            +
                          thread = @pool.shift
         
     | 
| 
       20 
20 
     | 
    
         
             
                        end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                        thread[:queue] << block
         
     | 
| 
      
 23 
     | 
    
         
            +
                        thread
         
     | 
| 
       21 
24 
     | 
    
         
             
                      end
         
     | 
| 
       22 
25 
     | 
    
         
             
                    end
         
     | 
| 
       23 
26 
     | 
    
         | 
| 
       24 
27 
     | 
    
         
             
                    def put(thread)
         
     | 
| 
       25 
28 
     | 
    
         
             
                      @lock.synchronize do
         
     | 
| 
       26 
29 
     | 
    
         
             
                        if @pool.size >= @max_idle
         
     | 
| 
       27 
     | 
    
         
            -
                          thread 
     | 
| 
      
 30 
     | 
    
         
            +
                          thread[:queue] << nil
         
     | 
| 
       28 
31 
     | 
    
         
             
                        else
         
     | 
| 
       29 
32 
     | 
    
         
             
                          @pool << thread
         
     | 
| 
       30 
33 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -35,13 +38,10 @@ module Celluloid 
     | 
|
| 
       35 
38 
     | 
    
         
             
                      queue = Queue.new
         
     | 
| 
       36 
39 
     | 
    
         
             
                      thread = Thread.new do
         
     | 
| 
       37 
40 
     | 
    
         
             
                        begin
         
     | 
| 
       38 
     | 
    
         
            -
                          while  
     | 
| 
       39 
     | 
    
         
            -
                             
     | 
| 
      
 41 
     | 
    
         
            +
                          while func = queue.pop
         
     | 
| 
      
 42 
     | 
    
         
            +
                            func.call
         
     | 
| 
       40 
43 
     | 
    
         
             
                          end
         
     | 
| 
       41 
44 
     | 
    
         
             
                        rescue Exception => ex
         
     | 
| 
       42 
     | 
    
         
            -
                          # Rubinius hax
         
     | 
| 
       43 
     | 
    
         
            -
                          raise if defined?(Thread::Die) and ex.is_a? Thread::Die
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
45 
     | 
    
         
             
                          message = "Celluloid::Actor::Pool internal failure:\n"
         
     | 
| 
       46 
46 
     | 
    
         
             
                          message << "#{ex.class}: #{ex.to_s}\n"
         
     | 
| 
       47 
47 
     | 
    
         
             
                          message << ex.backtrace.join("\n")
         
     | 
| 
         @@ -3,41 +3,40 @@ module Celluloid 
     | 
|
| 
       3 
3 
     | 
    
         
             
              # dispatches calls and casts to normal Ruby objects which are running inside
         
     | 
| 
       4 
4 
     | 
    
         
             
              # of their own threads.
         
     | 
| 
       5 
5 
     | 
    
         
             
              class ActorProxy
         
     | 
| 
       6 
     | 
    
         
            -
                # FIXME: not nearly enough methods are delegated here
         
     | 
| 
       7 
6 
     | 
    
         
             
                attr_reader :mailbox
         
     | 
| 
       8 
7 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
                def initialize( 
     | 
| 
       10 
     | 
    
         
            -
                  @ 
     | 
| 
      
 8 
     | 
    
         
            +
                def initialize(mailbox, klass = "Object")
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @mailbox, @klass = mailbox, klass
         
     | 
| 
       11 
10 
     | 
    
         
             
                end
         
     | 
| 
       12 
11 
     | 
    
         | 
| 
       13 
12 
     | 
    
         
             
                def send(meth, *args, &block)
         
     | 
| 
       14 
     | 
    
         
            -
                   
     | 
| 
      
 13 
     | 
    
         
            +
                  Actor.call @mailbox, :send, meth, *args, &block
         
     | 
| 
       15 
14 
     | 
    
         
             
                end
         
     | 
| 
       16 
15 
     | 
    
         | 
| 
       17 
16 
     | 
    
         
             
                def respond_to?(meth)
         
     | 
| 
       18 
     | 
    
         
            -
                   
     | 
| 
      
 17 
     | 
    
         
            +
                  Actor.call @mailbox, :respond_to?, meth
         
     | 
| 
       19 
18 
     | 
    
         
             
                end
         
     | 
| 
       20 
19 
     | 
    
         | 
| 
       21 
20 
     | 
    
         
             
                def methods(include_ancestors = true)
         
     | 
| 
       22 
     | 
    
         
            -
                   
     | 
| 
      
 21 
     | 
    
         
            +
                  Actor.call @mailbox, :methods, include_ancestors
         
     | 
| 
       23 
22 
     | 
    
         
             
                end
         
     | 
| 
       24 
23 
     | 
    
         | 
| 
       25 
24 
     | 
    
         
             
                def alive?
         
     | 
| 
       26 
     | 
    
         
            -
                  @ 
     | 
| 
      
 25 
     | 
    
         
            +
                  @mailbox.alive?
         
     | 
| 
       27 
26 
     | 
    
         
             
                end
         
     | 
| 
       28 
27 
     | 
    
         | 
| 
       29 
28 
     | 
    
         
             
                def to_s
         
     | 
| 
       30 
     | 
    
         
            -
                   
     | 
| 
      
 29 
     | 
    
         
            +
                  Actor.call @mailbox, :to_s
         
     | 
| 
       31 
30 
     | 
    
         
             
                end
         
     | 
| 
       32 
31 
     | 
    
         | 
| 
       33 
32 
     | 
    
         
             
                def inspect
         
     | 
| 
       34 
     | 
    
         
            -
                   
     | 
| 
       35 
     | 
    
         
            -
                   
     | 
| 
      
 33 
     | 
    
         
            +
                  "#<Celluloid::Actor(#{@klass}) dead>" unless alive?
         
     | 
| 
      
 34 
     | 
    
         
            +
                  Actor.call @mailbox, :inspect
         
     | 
| 
       36 
35 
     | 
    
         
             
                end
         
     | 
| 
       37 
36 
     | 
    
         | 
| 
       38 
37 
     | 
    
         
             
                # Create a Celluloid::Future which calls a given method
         
     | 
| 
       39 
38 
     | 
    
         
             
                def future(method_name, *args, &block)
         
     | 
| 
       40 
     | 
    
         
            -
                  Celluloid::Future.new {  
     | 
| 
      
 39 
     | 
    
         
            +
                  Celluloid::Future.new { Actor.call @mailbox, method_name, *args, &block }
         
     | 
| 
       41 
40 
     | 
    
         
             
                end
         
     | 
| 
       42 
41 
     | 
    
         | 
| 
       43 
42 
     | 
    
         
             
                # Terminate the associated actor
         
     | 
| 
         @@ -61,64 +60,11 @@ module Celluloid 
     | 
|
| 
       61 
60 
     | 
    
         
             
                  # bang methods are async calls
         
     | 
| 
       62 
61 
     | 
    
         
             
                  if meth.to_s.match(/!$/)
         
     | 
| 
       63 
62 
     | 
    
         
             
                    unbanged_meth = meth.to_s.sub(/!$/, '')
         
     | 
| 
       64 
     | 
    
         
            -
                     
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
                    begin
         
     | 
| 
       67 
     | 
    
         
            -
                      @mailbox << AsyncCall.new(our_mailbox, unbanged_meth, args, block)
         
     | 
| 
       68 
     | 
    
         
            -
                    rescue MailboxError
         
     | 
| 
       69 
     | 
    
         
            -
                      # Silently swallow asynchronous calls to dead actors. There's no way
         
     | 
| 
       70 
     | 
    
         
            -
                      # to reliably generate DeadActorErrors for async calls, so users of
         
     | 
| 
       71 
     | 
    
         
            -
                      # async calls should find other ways to deal with actors dying
         
     | 
| 
       72 
     | 
    
         
            -
                      # during an async call (i.e. linking/supervisors)
         
     | 
| 
       73 
     | 
    
         
            -
                    end
         
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
     | 
    
         
            -
                    return # casts are async and return immediately
         
     | 
| 
      
 63 
     | 
    
         
            +
                    Actor.async @mailbox, unbanged_meth, *args, &block
         
     | 
| 
      
 64 
     | 
    
         
            +
                    return
         
     | 
| 
       76 
65 
     | 
    
         
             
                  end
         
     | 
| 
       77 
66 
     | 
    
         | 
| 
       78 
     | 
    
         
            -
                   
     | 
| 
       79 
     | 
    
         
            -
                end
         
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
                #######
         
     | 
| 
       82 
     | 
    
         
            -
                private
         
     | 
| 
       83 
     | 
    
         
            -
                #######
         
     | 
| 
       84 
     | 
    
         
            -
             
     | 
| 
       85 
     | 
    
         
            -
                # Make a synchronous call to the actor we're proxying to
         
     | 
| 
       86 
     | 
    
         
            -
                def __call(meth, *args, &block)
         
     | 
| 
       87 
     | 
    
         
            -
                  our_mailbox = Thread.current.mailbox
         
     | 
| 
       88 
     | 
    
         
            -
                  call = SyncCall.new(our_mailbox, meth, args, block)
         
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
                  begin
         
     | 
| 
       91 
     | 
    
         
            -
                    @mailbox << call
         
     | 
| 
       92 
     | 
    
         
            -
                  rescue MailboxError
         
     | 
| 
       93 
     | 
    
         
            -
                    raise DeadActorError, "attempted to call a dead actor"
         
     | 
| 
       94 
     | 
    
         
            -
                  end
         
     | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
       96 
     | 
    
         
            -
                  if Celluloid.actor?
         
     | 
| 
       97 
     | 
    
         
            -
                    # Yield to the actor scheduler, which resumes us when we get a response
         
     | 
| 
       98 
     | 
    
         
            -
                    response = Fiber.yield(call)
         
     | 
| 
       99 
     | 
    
         
            -
                  else
         
     | 
| 
       100 
     | 
    
         
            -
                    # Otherwise we're inside a normal thread, so block
         
     | 
| 
       101 
     | 
    
         
            -
                    response = our_mailbox.receive do |msg|
         
     | 
| 
       102 
     | 
    
         
            -
                      msg.is_a? Response and msg.call == call
         
     | 
| 
       103 
     | 
    
         
            -
                    end
         
     | 
| 
       104 
     | 
    
         
            -
                  end
         
     | 
| 
       105 
     | 
    
         
            -
             
     | 
| 
       106 
     | 
    
         
            -
                  case response
         
     | 
| 
       107 
     | 
    
         
            -
                  when SuccessResponse
         
     | 
| 
       108 
     | 
    
         
            -
                    response.value
         
     | 
| 
       109 
     | 
    
         
            -
                  when ErrorResponse
         
     | 
| 
       110 
     | 
    
         
            -
                    ex = response.value
         
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
                    if ex.is_a? AbortError
         
     | 
| 
       113 
     | 
    
         
            -
                      # Aborts are caused by caller error, so ensure they capture the
         
     | 
| 
       114 
     | 
    
         
            -
                      # caller's backtrace instead of the receiver's
         
     | 
| 
       115 
     | 
    
         
            -
                      raise ex.cause.class.new(ex.cause.message)
         
     | 
| 
       116 
     | 
    
         
            -
                    else
         
     | 
| 
       117 
     | 
    
         
            -
                      raise ex
         
     | 
| 
       118 
     | 
    
         
            -
                    end
         
     | 
| 
       119 
     | 
    
         
            -
                  else
         
     | 
| 
       120 
     | 
    
         
            -
                    raise "don't know how to handle #{response.class} messages!"
         
     | 
| 
       121 
     | 
    
         
            -
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
                  Actor.call @mailbox, meth, *args, &block
         
     | 
| 
       122 
68 
     | 
    
         
             
                end
         
     | 
| 
       123 
69 
     | 
    
         
             
              end
         
     | 
| 
       124 
70 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,78 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Celluloid
         
     | 
| 
      
 2 
     | 
    
         
            +
              # Applications describe and manage networks of Celluloid actors
         
     | 
| 
      
 3 
     | 
    
         
            +
              class Application
         
     | 
| 
      
 4 
     | 
    
         
            +
                include Celluloid
         
     | 
| 
      
 5 
     | 
    
         
            +
                trap_exit :restart_supervisor
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # Actors or sub-applications to be supervised
         
     | 
| 
      
 9 
     | 
    
         
            +
                  def supervisables
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @supervisables ||= []
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  # Start this application (and watch it with a supervisor)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  alias_method :run!, :supervise
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  # Run the application in the foreground with a simple watchdog
         
     | 
| 
      
 17 
     | 
    
         
            +
                  def run
         
     | 
| 
      
 18 
     | 
    
         
            +
                    loop do
         
     | 
| 
      
 19 
     | 
    
         
            +
                      supervisor = run!
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                      # Take five, toplevel supervisor
         
     | 
| 
      
 22 
     | 
    
         
            +
                      sleep 5 while supervisor.alive?
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                      Celluloid.logger.error "!!! Celluloid::Application #{self} crashed. Restarting..."
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  # Register an actor class or a sub-application class to be launched and
         
     | 
| 
      
 29 
     | 
    
         
            +
                  # supervised while this application is running. Available options are:
         
     | 
| 
      
 30 
     | 
    
         
            +
                  #
         
     | 
| 
      
 31 
     | 
    
         
            +
                  # * as: register this application in the Celluloid::Actor[] directory
         
     | 
| 
      
 32 
     | 
    
         
            +
                  # * args: start the actor with the given arguments
         
     | 
| 
      
 33 
     | 
    
         
            +
                  def supervise(klass, options = {})
         
     | 
| 
      
 34 
     | 
    
         
            +
                    supervisables << Supervisable.new(klass, options)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                # Start the application
         
     | 
| 
      
 39 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 40 
     | 
    
         
            +
                  @supervisors = {}
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  # This is some serious lolcode, but like... start the supervisors for
         
     | 
| 
      
 43 
     | 
    
         
            +
                  # this application
         
     | 
| 
      
 44 
     | 
    
         
            +
                  self.class.supervisables.each do |supervisable|
         
     | 
| 
      
 45 
     | 
    
         
            +
                    supervisor = supervisable.supervise
         
     | 
| 
      
 46 
     | 
    
         
            +
                    @supervisors[supervisor] = supervisable
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                # Restart a crashed supervisor
         
     | 
| 
      
 51 
     | 
    
         
            +
                def restart_supervisor(supervisor, reason)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  supervisable = @supervisors.delete supervisor
         
     | 
| 
      
 53 
     | 
    
         
            +
                  raise "a supervisable went missing. This shouldn't be!" unless supervisable
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  supervisor = supervisable.supervise
         
     | 
| 
      
 56 
     | 
    
         
            +
                  @supervisors[supervisor] = supervisable
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                # A subcomponent of an application to be supervised
         
     | 
| 
      
 60 
     | 
    
         
            +
                class Supervisable
         
     | 
| 
      
 61 
     | 
    
         
            +
                  attr_reader :klass, :as, :args
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  def initialize(klass, options = {})
         
     | 
| 
      
 64 
     | 
    
         
            +
                    @klass = klass
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                    # Stringify keys :/
         
     | 
| 
      
 67 
     | 
    
         
            +
                    options = options.inject({}) { |h,(k,v)| h[k.to_s] = v; h }
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                    @as = options['as']
         
     | 
| 
      
 70 
     | 
    
         
            +
                    @args = options['args'] || []
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  def supervise
         
     | 
| 
      
 74 
     | 
    
         
            +
                    Supervisor.new_link(@as, @klass, *@args)
         
     | 
| 
      
 75 
     | 
    
         
            +
                  end
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
              end
         
     | 
| 
      
 78 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/celluloid/calls.rb
    CHANGED
    
    | 
         @@ -1,17 +1,18 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Celluloid
         
     | 
| 
       2 
2 
     | 
    
         
             
              # Calls represent requests to an actor
         
     | 
| 
       3 
3 
     | 
    
         
             
              class Call
         
     | 
| 
       4 
     | 
    
         
            -
                attr_reader :caller, :method, :arguments, :block
         
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
      
 4 
     | 
    
         
            +
                attr_reader :id, :caller, :method, :arguments, :block
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
       6 
6 
     | 
    
         
             
                def initialize(caller, method, arguments, block)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @id = object_id # memoize object ID for serialization
         
     | 
| 
       7 
8 
     | 
    
         
             
                  @caller, @method, @arguments, @block = caller, method, arguments, block
         
     | 
| 
       8 
9 
     | 
    
         
             
                end
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
       10 
11 
     | 
    
         
             
                def check_signature(obj)
         
     | 
| 
       11 
12 
     | 
    
         
             
                  unless obj.respond_to? @method
         
     | 
| 
       12 
13 
     | 
    
         
             
                    raise NoMethodError, "undefined method `#{@method}' for #{obj.inspect}"
         
     | 
| 
       13 
14 
     | 
    
         
             
                  end
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
       15 
16 
     | 
    
         
             
                  arity = obj.method(@method).arity
         
     | 
| 
       16 
17 
     | 
    
         
             
                  if arity >= 0
         
     | 
| 
       17 
18 
     | 
    
         
             
                    if arguments.size != arity
         
     | 
| 
         @@ -25,24 +26,24 @@ module Celluloid 
     | 
|
| 
       25 
26 
     | 
    
         
             
                  end
         
     | 
| 
       26 
27 
     | 
    
         
             
                end
         
     | 
| 
       27 
28 
     | 
    
         
             
              end
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
       29 
30 
     | 
    
         
             
              # Synchronous calls wait for a response
         
     | 
| 
       30 
31 
     | 
    
         
             
              class SyncCall < Call
         
     | 
| 
       31 
32 
     | 
    
         
             
                def dispatch(obj)
         
     | 
| 
       32 
33 
     | 
    
         
             
                  begin
         
     | 
| 
       33 
34 
     | 
    
         
             
                    check_signature(obj)
         
     | 
| 
       34 
35 
     | 
    
         
             
                  rescue Exception => ex
         
     | 
| 
       35 
     | 
    
         
            -
                    respond ErrorResponse.new( 
     | 
| 
      
 36 
     | 
    
         
            +
                    respond ErrorResponse.new(@id, AbortError.new(ex))
         
     | 
| 
       36 
37 
     | 
    
         
             
                    return
         
     | 
| 
       37 
38 
     | 
    
         
             
                  end
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
       39 
40 
     | 
    
         
             
                  begin
         
     | 
| 
       40 
41 
     | 
    
         
             
                    result = obj.send @method, *@arguments, &@block
         
     | 
| 
       41 
42 
     | 
    
         
             
                  rescue Exception => exception
         
     | 
| 
       42 
43 
     | 
    
         
             
                    # Exceptions that occur during synchronous calls are reraised in the
         
     | 
| 
       43 
44 
     | 
    
         
             
                    # context of the caller
         
     | 
| 
       44 
     | 
    
         
            -
                    respond ErrorResponse.new( 
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
      
 45 
     | 
    
         
            +
                    respond ErrorResponse.new(@id, exception)
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
       46 
47 
     | 
    
         
             
                    if exception.is_a? AbortError
         
     | 
| 
       47 
48 
     | 
    
         
             
                      # Aborting indicates a protocol error on the part of the caller
         
     | 
| 
       48 
49 
     | 
    
         
             
                      # It should crash the caller, but the exception isn't reraised
         
     | 
| 
         @@ -52,43 +53,48 @@ module Celluloid 
     | 
|
| 
       52 
53 
     | 
    
         
             
                      raise exception
         
     | 
| 
       53 
54 
     | 
    
         
             
                    end
         
     | 
| 
       54 
55 
     | 
    
         
             
                  end
         
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
                  respond SuccessResponse.new( 
     | 
| 
       57 
     | 
    
         
            -
                  true
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  respond SuccessResponse.new(@id, result)
         
     | 
| 
       58 
58 
     | 
    
         
             
                end
         
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
       60 
60 
     | 
    
         
             
                def cleanup
         
     | 
| 
       61 
61 
     | 
    
         
             
                  exception = DeadActorError.new("attempted to call a dead actor")
         
     | 
| 
       62 
     | 
    
         
            -
                  respond ErrorResponse.new( 
     | 
| 
      
 62 
     | 
    
         
            +
                  respond ErrorResponse.new(@id, exception)
         
     | 
| 
       63 
63 
     | 
    
         
             
                end
         
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
       65 
65 
     | 
    
         
             
                #######
         
     | 
| 
       66 
66 
     | 
    
         
             
                private
         
     | 
| 
       67 
67 
     | 
    
         
             
                #######
         
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
       69 
69 
     | 
    
         
             
                def respond(message)
         
     | 
| 
       70 
70 
     | 
    
         
             
                  @caller << message
         
     | 
| 
       71 
71 
     | 
    
         
             
                rescue MailboxError
         
     | 
| 
       72 
72 
     | 
    
         
             
                  # It's possible the caller exited or crashed before we could send a
         
     | 
| 
       73 
73 
     | 
    
         
             
                  # response to them.
         
     | 
| 
       74 
     | 
    
         
            -
                end 
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
       75 
75 
     | 
    
         
             
              end
         
     | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
       77 
77 
     | 
    
         
             
              # Asynchronous calls don't wait for a response
         
     | 
| 
       78 
78 
     | 
    
         
             
              class AsyncCall < Call
         
     | 
| 
       79 
79 
     | 
    
         
             
                def dispatch(obj)
         
     | 
| 
       80 
80 
     | 
    
         
             
                  begin
         
     | 
| 
       81 
81 
     | 
    
         
             
                    check_signature(obj)
         
     | 
| 
       82 
82 
     | 
    
         
             
                  rescue Exception => ex
         
     | 
| 
       83 
     | 
    
         
            -
                     
     | 
| 
      
 83 
     | 
    
         
            +
                    log_error ex, "#{obj.class}: async call failed!"
         
     | 
| 
       84 
84 
     | 
    
         
             
                    return
         
     | 
| 
       85 
85 
     | 
    
         
             
                  end
         
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
       87 
87 
     | 
    
         
             
                  obj.send(@method, *@arguments, &@block)
         
     | 
| 
       88 
88 
     | 
    
         
             
                rescue AbortError => ex
         
     | 
| 
       89 
89 
     | 
    
         
             
                  # Swallow aborted async calls, as they indicate the caller made a mistake
         
     | 
| 
       90 
     | 
    
         
            -
                  obj. 
     | 
| 
      
 90 
     | 
    
         
            +
                  obj.log_error ex, "#{obj.class}: async call aborted!"
         
     | 
| 
      
 91 
     | 
    
         
            +
                end
         
     | 
| 
      
 92 
     | 
    
         
            +
                
         
     | 
| 
      
 93 
     | 
    
         
            +
                def log_error(ex, message)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  message << "\n#{ex.class}: #{ex.to_s}\n"
         
     | 
| 
      
 95 
     | 
    
         
            +
                  message << ex.backtrace.join("\n")
         
     | 
| 
      
 96 
     | 
    
         
            +
                  Celluloid.logger.error message if Celluloid.logger
         
     | 
| 
       91 
97 
     | 
    
         
             
                end
         
     | 
| 
       92 
98 
     | 
    
         
             
              end
         
     | 
| 
       93 
99 
     | 
    
         
             
            end
         
     | 
| 
       94 
     | 
    
         
            -
             
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Let's go shopping!
         
     | 
| 
      
 2 
     | 
    
         
            +
            begin
         
     | 
| 
      
 3 
     | 
    
         
            +
              require 'fiber'
         
     | 
| 
      
 4 
     | 
    
         
            +
            rescue LoadError => ex
         
     | 
| 
      
 5 
     | 
    
         
            +
              if defined? JRUBY_VERSION
         
     | 
| 
      
 6 
     | 
    
         
            +
                if RUBY_VERSION < "1.9.2"
         
     | 
| 
      
 7 
     | 
    
         
            +
                  raise LoadError, "Celluloid requires JRuby 1.9 mode. Please pass the --1.9 flag or set JRUBY_OPTS=--1.9"
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                # Fibers are broken on JRuby 1.6.5. This works around the issue
         
     | 
| 
      
 11 
     | 
    
         
            +
                if JRUBY_VERSION == "1.6.5"
         
     | 
| 
      
 12 
     | 
    
         
            +
                  require 'jruby'
         
     | 
| 
      
 13 
     | 
    
         
            +
                  org.jruby.ext.fiber.FiberExtLibrary.new.load(JRuby.runtime, false)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  class org::jruby::ext::fiber::ThreadFiber
         
     | 
| 
      
 15 
     | 
    
         
            +
                    field_accessor :state
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  class Fiber
         
     | 
| 
      
 19 
     | 
    
         
            +
                    def alive?
         
     | 
| 
      
 20 
     | 
    
         
            +
                      JRuby.reference(self).state != org.jruby.ext.fiber.ThreadFiberState::FINISHED
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                else
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # Just in case subsequent JRuby releases have broken fibers :/
         
     | 
| 
      
 25 
     | 
    
         
            +
                  raise ex
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
              elsif defined? Rubinius
         
     | 
| 
      
 28 
     | 
    
         
            +
                # If we're on Rubinius, we can still work in 1.8 mode
         
     | 
| 
      
 29 
     | 
    
         
            +
                Fiber = Rubinius::Fiber
         
     | 
| 
      
 30 
     | 
    
         
            +
              else
         
     | 
| 
      
 31 
     | 
    
         
            +
                raise ex
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/celluloid/io.rb
    CHANGED
    
    | 
         @@ -1,41 +1,15 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'celluloid/io/waker'
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'celluloid/io/reactor'
         
     | 
| 
       3 
3 
     | 
    
         
             
            require 'celluloid/io/mailbox'
         
     | 
| 
       4 
     | 
    
         
            -
            require 'celluloid/io/actor'
         
     | 
| 
       5 
4 
     | 
    
         | 
| 
       6 
5 
     | 
    
         
             
            module Celluloid
         
     | 
| 
       7 
6 
     | 
    
         
             
              # Actors which can run alongside other I/O operations
         
     | 
| 
       8 
7 
     | 
    
         
             
              module IO
         
     | 
| 
       9 
8 
     | 
    
         
             
                def self.included(klass)
         
     | 
| 
       10 
9 
     | 
    
         
             
                  klass.send :include, ::Celluloid
         
     | 
| 
       11 
     | 
    
         
            -
                  klass. 
     | 
| 
      
 10 
     | 
    
         
            +
                  klass.use_mailbox Celluloid::IO::Mailbox
         
     | 
| 
       12 
11 
     | 
    
         
             
                end
         
     | 
| 
       13 
12 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                # Class methods added to classes which include Celluloid::IO
         
     | 
| 
       15 
     | 
    
         
            -
                module ClassMethods
         
     | 
| 
       16 
     | 
    
         
            -
                  # Create a new actor
         
     | 
| 
       17 
     | 
    
         
            -
                  def new(*args, &block)
         
     | 
| 
       18 
     | 
    
         
            -
                    proxy = IO::Actor.new(allocate).proxy
         
     | 
| 
       19 
     | 
    
         
            -
                    proxy.send(:initialize, *args, &block)
         
     | 
| 
       20 
     | 
    
         
            -
                    proxy
         
     | 
| 
       21 
     | 
    
         
            -
                  end
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
                  # Create a new actor and link to the current one
         
     | 
| 
       24 
     | 
    
         
            -
                  def new_link(*args, &block)
         
     | 
| 
       25 
     | 
    
         
            -
                    current_actor = Thread.current[:actor]
         
     | 
| 
       26 
     | 
    
         
            -
                    raise NotActorError, "can't link outside actor context" unless current_actor
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
                    proxy = IO::Actor.new(allocate).proxy
         
     | 
| 
       29 
     | 
    
         
            -
                    current_actor.link proxy
         
     | 
| 
       30 
     | 
    
         
            -
                    proxy.send(:initialize, *args, &block)
         
     | 
| 
       31 
     | 
    
         
            -
                    proxy
         
     | 
| 
       32 
     | 
    
         
            -
                  end
         
     | 
| 
       33 
     | 
    
         
            -
                end
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
                #
         
     | 
| 
       36 
     | 
    
         
            -
                # Instance methods
         
     | 
| 
       37 
     | 
    
         
            -
                #
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
13 
     | 
    
         
             
                # Wait for the given IO object to become readable
         
     | 
| 
       40 
14 
     | 
    
         
             
                def wait_readable(io, &block)
         
     | 
| 
       41 
15 
     | 
    
         
             
                  # Law of demeter be damned!
         
     | 
    
        data/lib/celluloid/io/mailbox.rb
    CHANGED
    
    | 
         @@ -4,7 +4,7 @@ module Celluloid 
     | 
|
| 
       4 
4 
     | 
    
         
             
              module IO
         
     | 
| 
       5 
5 
     | 
    
         
             
                # An alternative implementation of Celluloid::Mailbox using Wakers
         
     | 
| 
       6 
6 
     | 
    
         
             
                class Mailbox < Celluloid::Mailbox
         
     | 
| 
       7 
     | 
    
         
            -
                  attr_reader :reactor
         
     | 
| 
      
 7 
     | 
    
         
            +
                  attr_reader :reactor, :waker
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
                  def initialize
         
     | 
| 
       10 
10 
     | 
    
         
             
                    @messages = []
         
     | 
| 
         @@ -50,7 +50,7 @@ module Celluloid 
     | 
|
| 
       50 
50 
     | 
    
         
             
                    end until message
         
     | 
| 
       51 
51 
     | 
    
         | 
| 
       52 
52 
     | 
    
         
             
                    message
         
     | 
| 
       53 
     | 
    
         
            -
                  rescue DeadWakerError
         
     | 
| 
      
 53 
     | 
    
         
            +
                  rescue IOError, DeadWakerError
         
     | 
| 
       54 
54 
     | 
    
         
             
                    shutdown # force shutdown of the mailbox
         
     | 
| 
       55 
55 
     | 
    
         
             
                    raise MailboxShutdown, "mailbox shutdown called during receive"
         
     | 
| 
       56 
56 
     | 
    
         
             
                  end
         
     | 
    
        data/lib/celluloid/io/reactor.rb
    CHANGED
    
    
    
        data/lib/celluloid/linking.rb
    CHANGED
    
    
    
        data/lib/celluloid/mailbox.rb
    CHANGED
    
    | 
         @@ -86,6 +86,11 @@ module Celluloid 
     | 
|
| 
       86 
86 
     | 
    
         
             
                  true
         
     | 
| 
       87 
87 
     | 
    
         
             
                end
         
     | 
| 
       88 
88 
     | 
    
         | 
| 
      
 89 
     | 
    
         
            +
                # Is the mailbox alive?
         
     | 
| 
      
 90 
     | 
    
         
            +
                def alive?
         
     | 
| 
      
 91 
     | 
    
         
            +
                  !@dead
         
     | 
| 
      
 92 
     | 
    
         
            +
                end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
       89 
94 
     | 
    
         
             
                # Cast to an array
         
     | 
| 
       90 
95 
     | 
    
         
             
                def to_a
         
     | 
| 
       91 
96 
     | 
    
         
             
                  @lock.synchronize { @messages.dup }
         
     | 
| 
         @@ -98,7 +103,7 @@ module Celluloid 
     | 
|
| 
       98 
103 
     | 
    
         | 
| 
       99 
104 
     | 
    
         
             
                # Inspect the contents of the Mailbox
         
     | 
| 
       100 
105 
     | 
    
         
             
                def inspect
         
     | 
| 
       101 
     | 
    
         
            -
                  " 
     | 
| 
      
 106 
     | 
    
         
            +
                  "#<#{self.class}:#{object_id.to_s(16)} @messages=[#{map { |m| m.inspect }.join(', ')}]>"
         
     | 
| 
       102 
107 
     | 
    
         
             
                end
         
     | 
| 
       103 
108 
     | 
    
         
             
              end
         
     | 
| 
       104 
109 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,36 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Celluloid
         
     | 
| 
      
 2 
     | 
    
         
            +
              # Allow methods to directly interact with the actor protocol
         
     | 
| 
      
 3 
     | 
    
         
            +
              class Receivers
         
     | 
| 
      
 4 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @handlers = []
         
     | 
| 
      
 6 
     | 
    
         
            +
                end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                # Receive an asynchronous message
         
     | 
| 
      
 9 
     | 
    
         
            +
                def receive(&block)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  raise ArgumentError, "receive must be given a block" unless block
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  @handlers << [Fiber.current, block]
         
     | 
| 
      
 13 
     | 
    
         
            +
                  Fiber.yield
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                # Handle incoming messages
         
     | 
| 
      
 17 
     | 
    
         
            +
                def handle_message(message)
         
     | 
| 
      
 18 
     | 
    
         
            +
                  handler = nil
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  @handlers.each_with_index do |(fiber, block), index|
         
     | 
| 
      
 21 
     | 
    
         
            +
                    if block.call(message)
         
     | 
| 
      
 22 
     | 
    
         
            +
                      handler = index
         
     | 
| 
      
 23 
     | 
    
         
            +
                      break
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  if handler
         
     | 
| 
      
 28 
     | 
    
         
            +
                    fiber, _ = @handlers.delete_at handler
         
     | 
| 
      
 29 
     | 
    
         
            +
                    Celluloid.resume_fiber fiber, message
         
     | 
| 
      
 30 
     | 
    
         
            +
                    true
         
     | 
| 
      
 31 
     | 
    
         
            +
                  else
         
     | 
| 
      
 32 
     | 
    
         
            +
                    false
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/celluloid/responses.rb
    CHANGED
    
    | 
         @@ -1,10 +1,10 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Celluloid
         
     | 
| 
       2 
2 
     | 
    
         
             
              # Responses to calls
         
     | 
| 
       3 
3 
     | 
    
         
             
              class Response
         
     | 
| 
       4 
     | 
    
         
            -
                attr_reader : 
     | 
| 
      
 4 
     | 
    
         
            +
                attr_reader :call_id, :value
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
                def initialize( 
     | 
| 
       7 
     | 
    
         
            -
                  @ 
     | 
| 
      
 6 
     | 
    
         
            +
                def initialize(call_id, value)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @call_id, @value = call_id, value
         
     | 
| 
       8 
8 
     | 
    
         
             
                end
         
     | 
| 
       9 
9 
     | 
    
         
             
              end
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
         @@ -12,5 +12,15 @@ module Celluloid 
     | 
|
| 
       12 
12 
     | 
    
         
             
              class SuccessResponse < Response; end
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
              # Call was aborted due to caller error
         
     | 
| 
       15 
     | 
    
         
            -
              class ErrorResponse < Response 
     | 
| 
      
 15 
     | 
    
         
            +
              class ErrorResponse < Response
         
     | 
| 
      
 16 
     | 
    
         
            +
                def value
         
     | 
| 
      
 17 
     | 
    
         
            +
                  if super.is_a? AbortError
         
     | 
| 
      
 18 
     | 
    
         
            +
                    # Aborts are caused by caller error, so ensure they capture the
         
     | 
| 
      
 19 
     | 
    
         
            +
                    # caller's backtrace instead of the receiver's
         
     | 
| 
      
 20 
     | 
    
         
            +
                    raise super.cause.class.new(super.cause.message)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  else
         
     | 
| 
      
 22 
     | 
    
         
            +
                    raise super
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
       16 
26 
     | 
    
         
             
            end
         
     | 
    
        data/lib/celluloid/signals.rb
    CHANGED
    
    
    
        data/lib/celluloid/supervisor.rb
    CHANGED
    
    | 
         @@ -4,37 +4,50 @@ module Celluloid 
     | 
|
| 
       4 
4 
     | 
    
         
             
              class Supervisor
         
     | 
| 
       5 
5 
     | 
    
         
             
                include Celluloid
         
     | 
| 
       6 
6 
     | 
    
         
             
                trap_exit :restart_actor
         
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
       8 
8 
     | 
    
         
             
                # Retrieve the actor this supervisor is supervising
         
     | 
| 
       9 
9 
     | 
    
         
             
                attr_reader :actor
         
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
       11 
11 
     | 
    
         
             
                def self.supervise(klass, *args, &block)
         
     | 
| 
       12 
12 
     | 
    
         
             
                  new(nil, klass, *args, &block)
         
     | 
| 
       13 
13 
     | 
    
         
             
                end
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
       15 
15 
     | 
    
         
             
                def self.supervise_as(name, klass, *args, &block)
         
     | 
| 
       16 
16 
     | 
    
         
             
                  new(name, klass, *args, &block)
         
     | 
| 
       17 
17 
     | 
    
         
             
                end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
       19 
19 
     | 
    
         
             
                def initialize(name, klass, *args, &block)
         
     | 
| 
       20 
20 
     | 
    
         
             
                  @name, @klass, @args, @block = name, klass, args, block
         
     | 
| 
       21 
21 
     | 
    
         
             
                  start_actor
         
     | 
| 
       22 
22 
     | 
    
         
             
                end
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
                def start_actor
         
     | 
| 
       25 
     | 
    
         
            -
                   
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def start_actor(start_attempts = 2, sleep_interval = 30)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  failures = 0
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 28 
     | 
    
         
            +
                    @actor = @klass.new_link(*@args, &@block)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  rescue
         
     | 
| 
      
 30 
     | 
    
         
            +
                    failures += 1
         
     | 
| 
      
 31 
     | 
    
         
            +
                    if failures >= start_attempts
         
     | 
| 
      
 32 
     | 
    
         
            +
                      failures = 0
         
     | 
| 
      
 33 
     | 
    
         
            +
                      Celluloid.logger.warn "#{@klass} is crashing on initialize repeatedly, sleeping for #{sleep_interval} seconds"
         
     | 
| 
      
 34 
     | 
    
         
            +
                      sleep sleep_interval
         
     | 
| 
      
 35 
     | 
    
         
            +
                    end
         
     | 
| 
      
 36 
     | 
    
         
            +
                    retry
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
       26 
39 
     | 
    
         
             
                  Celluloid::Actor[@name] = @actor if @name
         
     | 
| 
       27 
40 
     | 
    
         
             
                end
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
       29 
42 
     | 
    
         
             
                # When actors die, regardless of the reason, restart them
         
     | 
| 
       30 
43 
     | 
    
         
             
                def restart_actor(actor, reason)
         
     | 
| 
       31 
44 
     | 
    
         
             
                  start_actor
         
     | 
| 
       32 
45 
     | 
    
         
             
                end
         
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
       34 
47 
     | 
    
         
             
                def inspect
         
     | 
| 
       35 
     | 
    
         
            -
                  str = " 
     | 
| 
      
 48 
     | 
    
         
            +
                  str = "#<#{self.class}(#{@klass}):0x#{object_id.to_s(16)}"
         
     | 
| 
       36 
49 
     | 
    
         
             
                  str << " " << @args.map { |arg| arg.inspect }.join(' ') unless @args.empty?
         
     | 
| 
       37 
50 
     | 
    
         
             
                  str << ">"
         
     | 
| 
       38 
51 
     | 
    
         
             
                end
         
     | 
| 
       39 
52 
     | 
    
         
             
              end
         
     | 
| 
       40 
     | 
    
         
            -
            end
         
     | 
| 
      
 53 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/celluloid/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | 
         @@ -1,38 +1,38 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: celluloid
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
               
     | 
| 
       5 
     | 
    
         
            -
               
     | 
| 
      
 4 
     | 
    
         
            +
              prerelease:
         
     | 
| 
      
 5 
     | 
    
         
            +
              version: 0.6.0
         
     | 
| 
       6 
6 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       7 
7 
     | 
    
         
             
            authors:
         
     | 
| 
       8 
8 
     | 
    
         
             
            - Tony Arcieri
         
     | 
| 
       9 
     | 
    
         
            -
            autorequire: 
     | 
| 
      
 9 
     | 
    
         
            +
            autorequire:
         
     | 
| 
       10 
10 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       11 
11 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       12 
     | 
    
         
            -
            date: 2011- 
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2011-11-19 00:00:00.000000000Z
         
     | 
| 
       13 
13 
     | 
    
         
             
            dependencies:
         
     | 
| 
       14 
14 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       15 
15 
     | 
    
         
             
              name: rake
         
     | 
| 
       16 
     | 
    
         
            -
               
     | 
| 
       17 
     | 
    
         
            -
                none: false
         
     | 
| 
      
 16 
     | 
    
         
            +
              version_requirements: &2056 !ruby/object:Gem::Requirement
         
     | 
| 
       18 
17 
     | 
    
         
             
                requirements:
         
     | 
| 
       19 
18 
     | 
    
         
             
                - - ! '>='
         
     | 
| 
       20 
19 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       21 
20 
     | 
    
         
             
                    version: '0'
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
      
 21 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 22 
     | 
    
         
            +
              requirement: *2056
         
     | 
| 
       23 
23 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       24 
     | 
    
         
            -
               
     | 
| 
      
 24 
     | 
    
         
            +
              type: :development
         
     | 
| 
       25 
25 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       26 
26 
     | 
    
         
             
              name: rspec
         
     | 
| 
       27 
     | 
    
         
            -
               
     | 
| 
       28 
     | 
    
         
            -
                none: false
         
     | 
| 
      
 27 
     | 
    
         
            +
              version_requirements: &2074 !ruby/object:Gem::Requirement
         
     | 
| 
       29 
28 
     | 
    
         
             
                requirements:
         
     | 
| 
       30 
29 
     | 
    
         
             
                - - ! '>='
         
     | 
| 
       31 
30 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       32 
31 
     | 
    
         
             
                    version: 2.7.0
         
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
      
 32 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 33 
     | 
    
         
            +
              requirement: *2074
         
     | 
| 
       34 
34 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       35 
     | 
    
         
            -
               
     | 
| 
      
 35 
     | 
    
         
            +
              type: :development
         
     | 
| 
       36 
36 
     | 
    
         
             
            description: Celluloid is a concurrent object framework inspired by the Actor Model
         
     | 
| 
       37 
37 
     | 
    
         
             
            email:
         
     | 
| 
       38 
38 
     | 
    
         
             
            - tony@medioh.com
         
     | 
| 
         @@ -41,20 +41,20 @@ extensions: [] 
     | 
|
| 
       41 
41 
     | 
    
         
             
            extra_rdoc_files: []
         
     | 
| 
       42 
42 
     | 
    
         
             
            files:
         
     | 
| 
       43 
43 
     | 
    
         
             
            - README.md
         
     | 
| 
      
 44 
     | 
    
         
            +
            - lib/celluloid.rb
         
     | 
| 
       44 
45 
     | 
    
         
             
            - lib/celluloid/actor.rb
         
     | 
| 
       45 
46 
     | 
    
         
             
            - lib/celluloid/actor_pool.rb
         
     | 
| 
       46 
47 
     | 
    
         
             
            - lib/celluloid/actor_proxy.rb
         
     | 
| 
      
 48 
     | 
    
         
            +
            - lib/celluloid/application.rb
         
     | 
| 
       47 
49 
     | 
    
         
             
            - lib/celluloid/calls.rb
         
     | 
| 
       48 
50 
     | 
    
         
             
            - lib/celluloid/core_ext.rb
         
     | 
| 
       49 
51 
     | 
    
         
             
            - lib/celluloid/events.rb
         
     | 
| 
      
 52 
     | 
    
         
            +
            - lib/celluloid/fibers_are_hard.rb
         
     | 
| 
       50 
53 
     | 
    
         
             
            - lib/celluloid/future.rb
         
     | 
| 
       51 
     | 
    
         
            -
            - lib/celluloid/io/actor.rb
         
     | 
| 
       52 
     | 
    
         
            -
            - lib/celluloid/io/mailbox.rb
         
     | 
| 
       53 
     | 
    
         
            -
            - lib/celluloid/io/reactor.rb
         
     | 
| 
       54 
     | 
    
         
            -
            - lib/celluloid/io/waker.rb
         
     | 
| 
       55 
54 
     | 
    
         
             
            - lib/celluloid/io.rb
         
     | 
| 
       56 
55 
     | 
    
         
             
            - lib/celluloid/linking.rb
         
     | 
| 
       57 
56 
     | 
    
         
             
            - lib/celluloid/mailbox.rb
         
     | 
| 
      
 57 
     | 
    
         
            +
            - lib/celluloid/receivers.rb
         
     | 
| 
       58 
58 
     | 
    
         
             
            - lib/celluloid/registry.rb
         
     | 
| 
       59 
59 
     | 
    
         
             
            - lib/celluloid/responses.rb
         
     | 
| 
       60 
60 
     | 
    
         
             
            - lib/celluloid/rspec.rb
         
     | 
| 
         @@ -62,31 +62,34 @@ files: 
     | 
|
| 
       62 
62 
     | 
    
         
             
            - lib/celluloid/supervisor.rb
         
     | 
| 
       63 
63 
     | 
    
         
             
            - lib/celluloid/tcp_server.rb
         
     | 
| 
       64 
64 
     | 
    
         
             
            - lib/celluloid/version.rb
         
     | 
| 
       65 
     | 
    
         
            -
            - lib/celluloid.rb
         
     | 
| 
      
 65 
     | 
    
         
            +
            - lib/celluloid/io/mailbox.rb
         
     | 
| 
      
 66 
     | 
    
         
            +
            - lib/celluloid/io/reactor.rb
         
     | 
| 
      
 67 
     | 
    
         
            +
            - lib/celluloid/io/waker.rb
         
     | 
| 
       66 
68 
     | 
    
         
             
            homepage: https://github.com/tarcieri/celluloid
         
     | 
| 
       67 
69 
     | 
    
         
             
            licenses:
         
     | 
| 
       68 
70 
     | 
    
         
             
            - MIT
         
     | 
| 
       69 
     | 
    
         
            -
            post_install_message: 
     | 
| 
      
 71 
     | 
    
         
            +
            post_install_message:
         
     | 
| 
       70 
72 
     | 
    
         
             
            rdoc_options: []
         
     | 
| 
       71 
73 
     | 
    
         
             
            require_paths:
         
     | 
| 
       72 
74 
     | 
    
         
             
            - lib
         
     | 
| 
       73 
75 
     | 
    
         
             
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
       74 
     | 
    
         
            -
              none: false
         
     | 
| 
       75 
76 
     | 
    
         
             
              requirements:
         
     | 
| 
       76 
77 
     | 
    
         
             
              - - ! '>='
         
     | 
| 
       77 
78 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       78 
79 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       79 
     | 
    
         
            -
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
       80 
80 
     | 
    
         
             
              none: false
         
     | 
| 
      
 81 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
       81 
82 
     | 
    
         
             
              requirements:
         
     | 
| 
       82 
83 
     | 
    
         
             
              - - ! '>='
         
     | 
| 
       83 
84 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       84 
85 
     | 
    
         
             
                  version: 1.3.6
         
     | 
| 
      
 86 
     | 
    
         
            +
              none: false
         
     | 
| 
       85 
87 
     | 
    
         
             
            requirements: []
         
     | 
| 
       86 
     | 
    
         
            -
            rubyforge_project: 
     | 
| 
       87 
     | 
    
         
            -
            rubygems_version: 1.8. 
     | 
| 
       88 
     | 
    
         
            -
            signing_key: 
     | 
| 
      
 88 
     | 
    
         
            +
            rubyforge_project:
         
     | 
| 
      
 89 
     | 
    
         
            +
            rubygems_version: 1.8.9
         
     | 
| 
      
 90 
     | 
    
         
            +
            signing_key:
         
     | 
| 
       89 
91 
     | 
    
         
             
            specification_version: 3
         
     | 
| 
       90 
92 
     | 
    
         
             
            summary: Celluloid is a concurrent object framework inspired by the Actor Model
         
     | 
| 
       91 
93 
     | 
    
         
             
            test_files: []
         
     | 
| 
       92 
     | 
    
         
            -
            has_rdoc: 
     | 
| 
      
 94 
     | 
    
         
            +
            has_rdoc:
         
     | 
| 
      
 95 
     | 
    
         
            +
            ...
         
     |