celluloid 0.13.0 → 0.14.0.pre
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.
- checksums.yaml +7 -0
- data/README.md +1 -2
- data/lib/celluloid.rb +84 -32
- data/lib/celluloid/actor.rb +35 -30
- data/lib/celluloid/autostart.rb +0 -13
- data/lib/celluloid/calls.rb +71 -23
- data/lib/celluloid/core_ext.rb +3 -14
- data/lib/celluloid/cpu_counter.rb +1 -1
- data/lib/celluloid/evented_mailbox.rb +82 -0
- data/lib/celluloid/fsm.rb +2 -0
- data/lib/celluloid/future.rb +4 -4
- data/lib/celluloid/internal_pool.rb +11 -8
- data/lib/celluloid/legacy.rb +14 -13
- data/lib/celluloid/logging/incident_logger.rb +2 -2
- data/lib/celluloid/mailbox.rb +16 -0
- data/lib/celluloid/method.rb +7 -7
- data/lib/celluloid/notifications.rb +1 -1
- data/lib/celluloid/proxies/abstract_proxy.rb +1 -1
- data/lib/celluloid/proxies/actor_proxy.rb +23 -27
- data/lib/celluloid/proxies/async_proxy.rb +18 -6
- data/lib/celluloid/proxies/block_proxy.rb +29 -0
- data/lib/celluloid/proxies/future_proxy.rb +9 -3
- data/lib/celluloid/proxies/sync_proxy.rb +31 -0
- data/lib/celluloid/receivers.rb +1 -1
- data/lib/celluloid/responses.rb +13 -1
- data/lib/celluloid/stack_dump.rb +8 -5
- data/lib/celluloid/supervision_group.rb +6 -4
- data/lib/celluloid/tasks.rb +63 -2
- data/lib/celluloid/tasks/task_fiber.rb +6 -46
- data/lib/celluloid/tasks/task_thread.rb +8 -44
- data/lib/celluloid/thread.rb +82 -0
- data/lib/celluloid/thread_handle.rb +3 -2
- data/lib/celluloid/version.rb +1 -1
- data/spec/support/actor_examples.rb +116 -53
- data/spec/support/example_actor_class.rb +7 -1
- data/spec/support/mailbox_examples.rb +29 -3
- data/spec/support/task_examples.rb +11 -9
- metadata +21 -29
| @@ -0,0 +1,82 @@ | |
| 1 | 
            +
            require 'celluloid/fiber'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Celluloid
         | 
| 4 | 
            +
              class Thread < ::Thread
         | 
| 5 | 
            +
                # FIXME: these should be replaced using APIs on Celluloid::Thread itself
         | 
| 6 | 
            +
                # e.g. Thread.current[:celluloid_actor] => Thread.current.actor
         | 
| 7 | 
            +
                CELLULOID_LOCALS = [
         | 
| 8 | 
            +
                  :celluloid_actor,
         | 
| 9 | 
            +
                  :celluloid_mailbox,
         | 
| 10 | 
            +
                  :celluloid_queue,
         | 
| 11 | 
            +
                  :celluloid_task,
         | 
| 12 | 
            +
                  :celluloid_chain_id
         | 
| 13 | 
            +
                ]
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                # A roundabout way to avoid purging :celluloid_queue
         | 
| 16 | 
            +
                EPHEMERAL_CELLULOID_LOCALS = CELLULOID_LOCALS - [:celluloid_queue]
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def celluloid?
         | 
| 19 | 
            +
                  true
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                # Obtain the Celluloid::Actor object for this thread
         | 
| 23 | 
            +
                def actor
         | 
| 24 | 
            +
                  self[:celluloid_actor]
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                # Obtain the Celluloid task object for this thread
         | 
| 28 | 
            +
                def task
         | 
| 29 | 
            +
                  self[:celluloid_task]
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                # Obtain the Celluloid mailbox for this thread
         | 
| 33 | 
            +
                def mailbox
         | 
| 34 | 
            +
                  self[:celluloid_mailbox]
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                # Obtain the call chain ID for this thread
         | 
| 38 | 
            +
                def call_chain_id
         | 
| 39 | 
            +
                  self[:celluloid_chain_id]
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                #
         | 
| 43 | 
            +
                # Override default thread local behavior, making thread locals actor-local
         | 
| 44 | 
            +
                #
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                # Obtain an actor-local value
         | 
| 47 | 
            +
                def [](key)
         | 
| 48 | 
            +
                  if CELLULOID_LOCALS.include?(key)
         | 
| 49 | 
            +
                    super(key)
         | 
| 50 | 
            +
                  else
         | 
| 51 | 
            +
                    actor = super(:celluloid_actor)
         | 
| 52 | 
            +
                    actor.locals[key] if actor
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                # Set an actor-local value
         | 
| 57 | 
            +
                def []=(key, value)
         | 
| 58 | 
            +
                  if CELLULOID_LOCALS.include?(key)
         | 
| 59 | 
            +
                    super(key, value)
         | 
| 60 | 
            +
                  else
         | 
| 61 | 
            +
                    self[:celluloid_actor].locals[key] = value
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                # Obtain the keys to all actor-locals
         | 
| 66 | 
            +
                def keys
         | 
| 67 | 
            +
                  actor = self[:celluloid_actor]
         | 
| 68 | 
            +
                  actor.locals.keys if actor
         | 
| 69 | 
            +
                end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                # Is the given actor local set?
         | 
| 72 | 
            +
                def key?(key)
         | 
| 73 | 
            +
                  actor = self[:celluloid_actor]
         | 
| 74 | 
            +
                  actor.locals.has_key?(key) if actor
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                # Clear thread state so it can be reused via thread pools
         | 
| 78 | 
            +
                def recycle
         | 
| 79 | 
            +
                  EPHEMERAL_CELLULOID_LOCALS.each { |local| self[local] = nil }
         | 
| 80 | 
            +
                end
         | 
| 81 | 
            +
              end
         | 
| 82 | 
            +
            end
         | 
| @@ -31,8 +31,9 @@ module Celluloid | |
| 31 31 | 
             
                end
         | 
| 32 32 |  | 
| 33 33 | 
             
                # Join to a running thread, blocking until it terminates
         | 
| 34 | 
            -
                def join
         | 
| 35 | 
            -
                   | 
| 34 | 
            +
                def join(limit = nil)
         | 
| 35 | 
            +
                  raise ThreadError, "Target thread must not be current thread" if @thread == Thread.current
         | 
| 36 | 
            +
                  @mutex.synchronize { @join.wait(@mutex, limit) if @thread }
         | 
| 36 37 | 
             
                  self
         | 
| 37 38 | 
             
                end
         | 
| 38 39 |  | 
    
        data/lib/celluloid/version.rb
    CHANGED
    
    
| @@ -1,13 +1,22 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            shared_examples "a Celluloid Actor" do |included_module|
         | 
| 2 | 
            +
              describe "using Fibers" do
         | 
| 3 | 
            +
                include_examples "Celluloid::Actor examples", included_module, Celluloid::TaskFiber
         | 
| 4 | 
            +
              end
         | 
| 5 | 
            +
              describe "using Threads" do
         | 
| 6 | 
            +
                include_examples "Celluloid::Actor examples", included_module, Celluloid::TaskThread
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
            end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
         | 
| 2 11 | 
             
              class ExampleCrash < StandardError
         | 
| 3 12 | 
             
                attr_accessor :foo
         | 
| 4 13 | 
             
              end
         | 
| 5 14 |  | 
| 6 | 
            -
              let(:actor_class) { ExampleActorClass.create(included_module) }
         | 
| 15 | 
            +
              let(:actor_class) { ExampleActorClass.create(included_module, task_klass) }
         | 
| 7 16 |  | 
| 8 17 | 
             
              it "returns the actor's class, not the proxy's" do
         | 
| 9 18 | 
             
                actor = actor_class.new "Troy McClure"
         | 
| 10 | 
            -
                actor.class.should  | 
| 19 | 
            +
                actor.class.should eq(actor_class)
         | 
| 11 20 | 
             
              end
         | 
| 12 21 |  | 
| 13 22 | 
             
              it "compares with the actor's class in a case statement" do
         | 
| @@ -21,13 +30,13 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 21 30 |  | 
| 22 31 | 
             
              it "can be stored in hashes" do
         | 
| 23 32 | 
             
                actor = actor_class.new "Troy McClure"
         | 
| 24 | 
            -
                actor.hash.should_not  | 
| 25 | 
            -
                actor.object_id.should_not  | 
| 33 | 
            +
                actor.hash.should_not eq(Kernel.hash)
         | 
| 34 | 
            +
                actor.object_id.should_not eq(Kernel.object_id)
         | 
| 26 35 | 
             
              end
         | 
| 27 36 |  | 
| 28 37 | 
             
              it "supports synchronous calls" do
         | 
| 29 38 | 
             
                actor = actor_class.new "Troy McClure"
         | 
| 30 | 
            -
                actor.greet.should  | 
| 39 | 
            +
                actor.greet.should eq("Hi, I'm Troy McClure")
         | 
| 31 40 | 
             
              end
         | 
| 32 41 |  | 
| 33 42 | 
             
              it "supports synchronous calls with blocks" do
         | 
| @@ -40,32 +49,33 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 40 49 |  | 
| 41 50 | 
             
              it "supports synchronous calls via #method" do
         | 
| 42 51 | 
             
                method = actor_class.new("Troy McClure").method(:greet)
         | 
| 43 | 
            -
                method.call.should  | 
| 52 | 
            +
                method.call.should eq("Hi, I'm Troy McClure")
         | 
| 44 53 | 
             
              end
         | 
| 45 54 |  | 
| 46 55 | 
             
              it "supports #arity calls via #method" do
         | 
| 47 56 | 
             
                method = actor_class.new("Troy McClure").method(:greet)
         | 
| 48 | 
            -
                method.arity.should  | 
| 57 | 
            +
                method.arity.should be(0)
         | 
| 49 58 |  | 
| 50 59 | 
             
                method = actor_class.new("Troy McClure").method(:change_name)
         | 
| 51 | 
            -
                method.arity.should  | 
| 60 | 
            +
                method.arity.should be(1)
         | 
| 52 61 | 
             
              end
         | 
| 53 62 |  | 
| 54 63 | 
             
              it "supports future(:method) syntax for synchronous future calls" do
         | 
| 55 64 | 
             
                actor = actor_class.new "Troy McClure"
         | 
| 56 65 | 
             
                future = actor.future :greet
         | 
| 57 | 
            -
                future.value.should  | 
| 66 | 
            +
                future.value.should eq("Hi, I'm Troy McClure")
         | 
| 58 67 | 
             
              end
         | 
| 59 68 |  | 
| 60 69 | 
             
              it "supports future.method syntax for synchronous future calls" do
         | 
| 61 70 | 
             
                actor = actor_class.new "Troy McClure"
         | 
| 62 71 | 
             
                future = actor.future.greet
         | 
| 63 | 
            -
                future.value.should  | 
| 72 | 
            +
                future.value.should eq("Hi, I'm Troy McClure")
         | 
| 64 73 | 
             
              end
         | 
| 65 74 |  | 
| 66 75 | 
             
              it "handles circular synchronous calls" do
         | 
| 67 76 | 
             
                klass = Class.new do
         | 
| 68 77 | 
             
                  include included_module
         | 
| 78 | 
            +
                  task_class task_klass
         | 
| 69 79 |  | 
| 70 80 | 
             
                  def greet_by_proxy(actor)
         | 
| 71 81 | 
             
                    actor.greet
         | 
| @@ -78,13 +88,13 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 78 88 |  | 
| 79 89 | 
             
                ponycopter = klass.new
         | 
| 80 90 | 
             
                actor = actor_class.new ponycopter
         | 
| 81 | 
            -
                ponycopter.greet_by_proxy(actor).should  | 
| 91 | 
            +
                ponycopter.greet_by_proxy(actor).should eq("Hi, I'm a ponycopter!")
         | 
| 82 92 | 
             
              end
         | 
| 83 93 |  | 
| 84 94 | 
             
              it "properly handles method_missing" do
         | 
| 85 95 | 
             
                actor = actor_class.new "Method Missing"
         | 
| 86 96 | 
             
                actor.should respond_to(:first)
         | 
| 87 | 
            -
                actor.first.should be  | 
| 97 | 
            +
                actor.first.should be :bar
         | 
| 88 98 | 
             
              end
         | 
| 89 99 |  | 
| 90 100 | 
             
              it "properly handles respond_to with include_private" do
         | 
| @@ -103,19 +113,19 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 103 113 | 
             
              it "supports async(:method) syntax for asynchronous calls" do
         | 
| 104 114 | 
             
                actor = actor_class.new "Troy McClure"
         | 
| 105 115 | 
             
                actor.async :change_name, "Charlie Sheen"
         | 
| 106 | 
            -
                actor.greet.should  | 
| 116 | 
            +
                actor.greet.should eq("Hi, I'm Charlie Sheen")
         | 
| 107 117 | 
             
              end
         | 
| 108 118 |  | 
| 109 119 | 
             
              it "supports async.method syntax for asynchronous calls" do
         | 
| 110 120 | 
             
                actor = actor_class.new "Troy McClure"
         | 
| 111 121 | 
             
                actor.async.change_name "Charlie Sheen"
         | 
| 112 | 
            -
                actor.greet.should  | 
| 122 | 
            +
                actor.greet.should eq("Hi, I'm Charlie Sheen")
         | 
| 113 123 | 
             
              end
         | 
| 114 124 |  | 
| 115 125 | 
             
              it "supports async.method syntax for asynchronous calls to itself" do
         | 
| 116 126 | 
             
                actor = actor_class.new "Troy McClure"
         | 
| 117 127 | 
             
                actor.change_name_async "Charlie Sheen"
         | 
| 118 | 
            -
                actor.greet.should  | 
| 128 | 
            +
                actor.greet.should eq("Hi, I'm Charlie Sheen")
         | 
| 119 129 | 
             
              end
         | 
| 120 130 |  | 
| 121 131 | 
             
              it "allows an actor to call private methods asynchronously" do
         | 
| @@ -129,6 +139,9 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 129 139 | 
             
                actor = actor_class.new "Troy McClure"
         | 
| 130 140 | 
             
                actor.run do
         | 
| 131 141 | 
             
                  Celluloid.actor?
         | 
| 142 | 
            +
                end.should be_false
         | 
| 143 | 
            +
                actor.run_on_receiver do
         | 
| 144 | 
            +
                  Celluloid.actor?
         | 
| 132 145 | 
             
                end.should be_true
         | 
| 133 146 | 
             
                actor.should be_actor
         | 
| 134 147 | 
             
              end
         | 
| @@ -144,7 +157,7 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 144 157 | 
             
              it "inspects properly when dead" do
         | 
| 145 158 | 
             
                actor = actor_class.new "Troy McClure"
         | 
| 146 159 | 
             
                actor.terminate
         | 
| 147 | 
            -
                actor.inspect.should match(/Celluloid:: | 
| 160 | 
            +
                actor.inspect.should match(/Celluloid::ActorProxy\(/)
         | 
| 148 161 | 
             
                actor.inspect.should match(/#{actor_class}/)
         | 
| 149 162 | 
             
                actor.inspect.should include('dead')
         | 
| 150 163 | 
             
              end
         | 
| @@ -164,7 +177,7 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 164 177 |  | 
| 165 178 | 
             
              it "can override #send" do
         | 
| 166 179 | 
             
                actor = actor_class.new "Troy McClure"
         | 
| 167 | 
            -
                actor.send('foo').should  | 
| 180 | 
            +
                actor.send('foo').should eq('oof')
         | 
| 168 181 | 
             
              end
         | 
| 169 182 |  | 
| 170 183 | 
             
              context "mocking methods" do
         | 
| @@ -175,16 +188,16 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 175 188 | 
             
                end
         | 
| 176 189 |  | 
| 177 190 | 
             
                it "works externally via the proxy" do
         | 
| 178 | 
            -
                  actor.external_hello.should  | 
| 191 | 
            +
                  actor.external_hello.should eq("World")
         | 
| 179 192 | 
             
                end
         | 
| 180 193 |  | 
| 181 194 | 
             
                it "works internally when called on self" do
         | 
| 182 | 
            -
                  actor.internal_hello.should  | 
| 195 | 
            +
                  actor.internal_hello.should eq("World")
         | 
| 183 196 | 
             
                end
         | 
| 184 197 | 
             
              end
         | 
| 185 198 |  | 
| 186 199 | 
             
              context :exceptions do
         | 
| 187 | 
            -
                it "reraises exceptions which occur during synchronous calls in the  | 
| 200 | 
            +
                it "reraises exceptions which occur during synchronous calls in the sender" do
         | 
| 188 201 | 
             
                  actor = actor_class.new "James Dean" # is this in bad taste?
         | 
| 189 202 |  | 
| 190 203 | 
             
                  expect do
         | 
| @@ -192,9 +205,10 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 192 205 | 
             
                  end.to raise_exception(ExampleCrash)
         | 
| 193 206 | 
             
                end
         | 
| 194 207 |  | 
| 195 | 
            -
                it "includes both  | 
| 208 | 
            +
                it "includes both sender and receiver in exception traces" do
         | 
| 196 209 | 
             
                  ExampleReceiver = Class.new do
         | 
| 197 210 | 
             
                    include included_module
         | 
| 211 | 
            +
                    task_class task_klass
         | 
| 198 212 |  | 
| 199 213 | 
             
                    def receiver_method
         | 
| 200 214 | 
             
                      raise ExampleCrash, "the spec purposely crashed me :("
         | 
| @@ -203,20 +217,21 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 203 217 |  | 
| 204 218 | 
             
                  ExampleCaller = Class.new do
         | 
| 205 219 | 
             
                    include included_module
         | 
| 220 | 
            +
                    task_class task_klass
         | 
| 206 221 |  | 
| 207 | 
            -
                    def  | 
| 222 | 
            +
                    def sender_method
         | 
| 208 223 | 
             
                      ExampleReceiver.new.receiver_method
         | 
| 209 224 | 
             
                    end
         | 
| 210 225 | 
             
                  end
         | 
| 211 226 |  | 
| 212 227 | 
             
                  ex = nil
         | 
| 213 228 | 
             
                  begin
         | 
| 214 | 
            -
                    ExampleCaller.new. | 
| 229 | 
            +
                    ExampleCaller.new.sender_method
         | 
| 215 230 | 
             
                  rescue => ex
         | 
| 216 231 | 
             
                  end
         | 
| 217 232 |  | 
| 218 233 | 
             
                  ex.should be_a ExampleCrash
         | 
| 219 | 
            -
                  ex.backtrace.grep(/` | 
| 234 | 
            +
                  ex.backtrace.grep(/`sender_method'/).should be_true
         | 
| 220 235 | 
             
                  ex.backtrace.grep(/`receiver_method'/).should be_true
         | 
| 221 236 | 
             
                end
         | 
| 222 237 |  | 
| @@ -231,7 +246,7 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 231 246 | 
             
              end
         | 
| 232 247 |  | 
| 233 248 | 
             
              context :abort do
         | 
| 234 | 
            -
                it "raises exceptions in the  | 
| 249 | 
            +
                it "raises exceptions in the sender but keeps running" do
         | 
| 235 250 | 
             
                  actor = actor_class.new "Al Pacino"
         | 
| 236 251 |  | 
| 237 252 | 
             
                  expect do
         | 
| @@ -248,7 +263,7 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 248 263 | 
             
                  end.to raise_exception(RuntimeError, "foo")
         | 
| 249 264 | 
             
                end
         | 
| 250 265 |  | 
| 251 | 
            -
                it "crashes the  | 
| 266 | 
            +
                it "crashes the sender if we pass neither String nor Exception" do
         | 
| 252 267 | 
             
                  actor = actor_class.new "Al Pacino"
         | 
| 253 268 | 
             
                  expect do
         | 
| 254 269 | 
             
                    actor.crash_with_abort_raw 10
         | 
| @@ -308,6 +323,30 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 308 323 | 
             
                end
         | 
| 309 324 | 
             
              end
         | 
| 310 325 |  | 
| 326 | 
            +
              context "thread locals" do
         | 
| 327 | 
            +
                let(:example_class) do
         | 
| 328 | 
            +
                  Class.new do
         | 
| 329 | 
            +
                    include included_module
         | 
| 330 | 
            +
                    task_class task_klass
         | 
| 331 | 
            +
             | 
| 332 | 
            +
                    def initialize(value)
         | 
| 333 | 
            +
                      Thread.current[:example_thread_local] = value
         | 
| 334 | 
            +
                    end
         | 
| 335 | 
            +
             | 
| 336 | 
            +
                    def value
         | 
| 337 | 
            +
                      Thread.current[:example_thread_local]
         | 
| 338 | 
            +
                    end
         | 
| 339 | 
            +
                  end
         | 
| 340 | 
            +
                end
         | 
| 341 | 
            +
             | 
| 342 | 
            +
                let(:example_value) { "foobar" }
         | 
| 343 | 
            +
             | 
| 344 | 
            +
                it "preserves thread locals between tasks" do
         | 
| 345 | 
            +
                  actor = example_class.new(example_value)
         | 
| 346 | 
            +
                  actor.value.should eq example_value
         | 
| 347 | 
            +
                end
         | 
| 348 | 
            +
              end
         | 
| 349 | 
            +
             | 
| 311 350 | 
             
              context :linking do
         | 
| 312 351 | 
             
                before :each do
         | 
| 313 352 | 
             
                  @kevin   = actor_class.new "Kevin Bacon" # Some six degrees action here
         | 
| @@ -317,6 +356,7 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 317 356 | 
             
                let(:supervisor_class) do
         | 
| 318 357 | 
             
                  Class.new do # like a boss
         | 
| 319 358 | 
             
                    include included_module
         | 
| 359 | 
            +
                    task_class task_klass
         | 
| 320 360 | 
             
                    trap_exit :lambaste_subordinate
         | 
| 321 361 |  | 
| 322 362 | 
             
                    def initialize(name)
         | 
| @@ -403,7 +443,7 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 403 443 | 
             
                  end.to raise_exception(ExampleCrash)
         | 
| 404 444 |  | 
| 405 445 | 
             
                  sleep 0.1 # hax to prevent a race between exit handling and the next call
         | 
| 406 | 
            -
                  chuck.links.count.should  | 
| 446 | 
            +
                  chuck.links.count.should be(0)
         | 
| 407 447 | 
             
                end
         | 
| 408 448 | 
             
              end
         | 
| 409 449 |  | 
| @@ -411,6 +451,7 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 411 451 | 
             
                before do
         | 
| 412 452 | 
             
                  @signaler = Class.new do
         | 
| 413 453 | 
             
                    include included_module
         | 
| 454 | 
            +
                    task_class task_klass
         | 
| 414 455 |  | 
| 415 456 | 
             
                    def initialize
         | 
| 416 457 | 
             
                      @waiting  = false
         | 
| @@ -466,7 +507,7 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 466 507 | 
             
                  obj.should_not be_signaled
         | 
| 467 508 |  | 
| 468 509 | 
             
                  obj.send_signal(:foobar).should be_true
         | 
| 469 | 
            -
                  future.value.should  | 
| 510 | 
            +
                  future.value.should be(:foobar)
         | 
| 470 511 | 
             
                end
         | 
| 471 512 | 
             
              end
         | 
| 472 513 |  | 
| @@ -474,6 +515,7 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 474 515 | 
             
                subject do
         | 
| 475 516 | 
             
                  Class.new do
         | 
| 476 517 | 
             
                    include included_module
         | 
| 518 | 
            +
                    task_class task_klass
         | 
| 477 519 |  | 
| 478 520 | 
             
                    attr_reader :tasks
         | 
| 479 521 |  | 
| @@ -516,14 +558,14 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 516 558 | 
             
                  subject.async.exclusive_with_block_log_task(:one)
         | 
| 517 559 | 
             
                  subject.async.log_task(:two)
         | 
| 518 560 | 
             
                  sleep Celluloid::TIMER_QUANTUM * 2
         | 
| 519 | 
            -
                  subject.tasks.should  | 
| 561 | 
            +
                  subject.tasks.should eq([:one, :two])
         | 
| 520 562 | 
             
                end
         | 
| 521 563 |  | 
| 522 564 | 
             
                it "executes methods in the proper order with a class-level annotation" do
         | 
| 523 565 | 
             
                  subject.async.exclusive_log_task :one
         | 
| 524 566 | 
             
                  subject.async.log_task :two
         | 
| 525 567 | 
             
                  sleep Celluloid::TIMER_QUANTUM * 2
         | 
| 526 | 
            -
                  subject.tasks.should  | 
| 568 | 
            +
                  subject.tasks.should eq([:one, :two])
         | 
| 527 569 | 
             
                end
         | 
| 528 570 |  | 
| 529 571 | 
             
                it "knows when it's in exclusive mode" do
         | 
| @@ -540,6 +582,7 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 540 582 | 
             
                subject do
         | 
| 541 583 | 
             
                  Class.new do
         | 
| 542 584 | 
             
                    include included_module
         | 
| 585 | 
            +
                    task_class task_klass
         | 
| 543 586 | 
             
                    exclusive
         | 
| 544 587 |  | 
| 545 588 | 
             
                    attr_reader :tasks
         | 
| @@ -564,7 +607,7 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 564 607 | 
             
                  actor.async.eat_donuts
         | 
| 565 608 | 
             
                  actor.async.drink_coffee
         | 
| 566 609 | 
             
                  sleep Celluloid::TIMER_QUANTUM * 2
         | 
| 567 | 
            -
                  actor.tasks.should  | 
| 610 | 
            +
                  actor.tasks.should eq(['donuts', 'coffee'])
         | 
| 568 611 | 
             
                end
         | 
| 569 612 | 
             
              end
         | 
| 570 613 |  | 
| @@ -572,6 +615,8 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 572 615 | 
             
                before do
         | 
| 573 616 | 
             
                  @receiver = Class.new do
         | 
| 574 617 | 
             
                    include included_module
         | 
| 618 | 
            +
                    task_class task_klass
         | 
| 619 | 
            +
                    execute_block_on_receiver :signal_myself
         | 
| 575 620 |  | 
| 576 621 | 
             
                    def signal_myself(obj, &block)
         | 
| 577 622 | 
             
                      current_actor.mailbox << obj
         | 
| @@ -584,12 +629,12 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 584 629 | 
             
                let(:message) { Object.new }
         | 
| 585 630 |  | 
| 586 631 | 
             
                it "allows unconditional receive" do
         | 
| 587 | 
            -
                  receiver.signal_myself(message).should  | 
| 632 | 
            +
                  receiver.signal_myself(message).should eq(message)
         | 
| 588 633 | 
             
                end
         | 
| 589 634 |  | 
| 590 635 | 
             
                it "allows arbitrary selective receive" do
         | 
| 591 636 | 
             
                  received_obj = receiver.signal_myself(message) { |o| o == message }
         | 
| 592 | 
            -
                  received_obj.should  | 
| 637 | 
            +
                  received_obj.should eq(message)
         | 
| 593 638 | 
             
                end
         | 
| 594 639 |  | 
| 595 640 | 
             
                it "times out after the given interval", :pending => ENV['CI'] do
         | 
| @@ -605,6 +650,7 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 605 650 | 
             
                before do
         | 
| 606 651 | 
             
                  @klass = Class.new do
         | 
| 607 652 | 
             
                    include included_module
         | 
| 653 | 
            +
                    task_class task_klass
         | 
| 608 654 |  | 
| 609 655 | 
             
                    def initialize
         | 
| 610 656 | 
             
                      @sleeping = false
         | 
| @@ -653,9 +699,8 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 653 699 | 
             
                  actor = @klass.new
         | 
| 654 700 |  | 
| 655 701 | 
             
                  interval = Celluloid::TIMER_QUANTUM * 10
         | 
| 656 | 
            -
                  started_at = Time.now
         | 
| 657 702 |  | 
| 658 | 
            -
                   | 
| 703 | 
            +
                  actor.fire_after(interval)
         | 
| 659 704 | 
             
                  actor.should_not be_fired
         | 
| 660 705 |  | 
| 661 706 | 
             
                  sleep(interval + Celluloid::TIMER_QUANTUM) # wonky! #/
         | 
| @@ -666,23 +711,21 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 666 711 | 
             
                  actor = @klass.new
         | 
| 667 712 |  | 
| 668 713 | 
             
                  interval = Celluloid::TIMER_QUANTUM * 10
         | 
| 669 | 
            -
                  started_at = Time.now
         | 
| 670 714 |  | 
| 671 | 
            -
                   | 
| 672 | 
            -
                  actor.fired.should  | 
| 715 | 
            +
                  actor.fire_every(interval)
         | 
| 716 | 
            +
                  actor.fired.should be_zero
         | 
| 673 717 |  | 
| 674 718 | 
             
                  sleep(interval + Celluloid::TIMER_QUANTUM) # wonky! #/
         | 
| 675 | 
            -
                  actor.fired.should be  | 
| 719 | 
            +
                  actor.fired.should be 1
         | 
| 676 720 |  | 
| 677 721 | 
             
                  2.times { sleep(interval + Celluloid::TIMER_QUANTUM) } # wonky! #/
         | 
| 678 | 
            -
                  actor.fired.should be  | 
| 722 | 
            +
                  actor.fired.should be 3
         | 
| 679 723 | 
             
                end
         | 
| 680 724 |  | 
| 681 725 | 
             
                it "cancels timers before they fire" do
         | 
| 682 726 | 
             
                  actor = @klass.new
         | 
| 683 727 |  | 
| 684 728 | 
             
                  interval = Celluloid::TIMER_QUANTUM * 10
         | 
| 685 | 
            -
                  started_at = Time.now
         | 
| 686 729 |  | 
| 687 730 | 
             
                  timer = actor.fire_after(interval)
         | 
| 688 731 | 
             
                  actor.should_not be_fired
         | 
| @@ -696,10 +739,9 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 696 739 | 
             
                  actor = @klass.new
         | 
| 697 740 |  | 
| 698 741 | 
             
                  interval = Celluloid::TIMER_QUANTUM * 10
         | 
| 699 | 
            -
                  started_at = Time.now
         | 
| 700 742 | 
             
                  fired = false
         | 
| 701 743 |  | 
| 702 | 
            -
                   | 
| 744 | 
            +
                  actor.after(interval) do
         | 
| 703 745 | 
             
                    fired = true
         | 
| 704 746 | 
             
                  end
         | 
| 705 747 | 
             
                  fired.should be_false
         | 
| @@ -713,6 +755,7 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 713 755 | 
             
                before do
         | 
| 714 756 | 
             
                  @klass = Class.new do
         | 
| 715 757 | 
             
                    include included_module
         | 
| 758 | 
            +
                    task_class task_klass
         | 
| 716 759 | 
             
                    attr_reader :blocker
         | 
| 717 760 |  | 
| 718 761 | 
             
                    def initialize
         | 
| @@ -741,21 +784,21 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 741 784 | 
             
                  actor = @klass.new
         | 
| 742 785 |  | 
| 743 786 | 
             
                  tasks = actor.tasks
         | 
| 744 | 
            -
                  tasks.size.should  | 
| 787 | 
            +
                  tasks.size.should be 1
         | 
| 745 788 |  | 
| 746 | 
            -
                   | 
| 789 | 
            +
                  actor.future(:blocking_call)
         | 
| 747 790 | 
             
                  sleep 0.1 # hax! waiting for ^^^ call to actually start
         | 
| 748 791 |  | 
| 749 792 | 
             
                  tasks = actor.tasks
         | 
| 750 | 
            -
                  tasks.size.should  | 
| 793 | 
            +
                  tasks.size.should be 2
         | 
| 751 794 |  | 
| 752 795 | 
             
                  blocking_task = tasks.find { |t| t.status != :running }
         | 
| 753 | 
            -
                  blocking_task.should be_a  | 
| 754 | 
            -
                  blocking_task.status.should  | 
| 796 | 
            +
                  blocking_task.should be_a task_klass
         | 
| 797 | 
            +
                  blocking_task.status.should be :callwait
         | 
| 755 798 |  | 
| 756 799 | 
             
                  actor.blocker.unblock
         | 
| 757 800 | 
             
                  sleep 0.1 # hax again :(
         | 
| 758 | 
            -
                  actor.tasks.size.should  | 
| 801 | 
            +
                  actor.tasks.size.should be 1
         | 
| 759 802 | 
             
                end
         | 
| 760 803 | 
             
              end
         | 
| 761 804 |  | 
| @@ -765,6 +808,7 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 765 808 | 
             
                subject do
         | 
| 766 809 | 
             
                  Class.new do
         | 
| 767 810 | 
             
                    include included_module
         | 
| 811 | 
            +
                    task_class task_klass
         | 
| 768 812 | 
             
                    mailbox_class ExampleMailbox
         | 
| 769 813 | 
             
                  end
         | 
| 770 814 | 
             
                end
         | 
| @@ -779,23 +823,42 @@ shared_context "a Celluloid Actor" do |included_module| | |
| 779 823 | 
             
                end
         | 
| 780 824 | 
             
              end
         | 
| 781 825 |  | 
| 826 | 
            +
              context :mailbox_limit do
         | 
| 827 | 
            +
                subject do
         | 
| 828 | 
            +
                  Class.new do
         | 
| 829 | 
            +
                    include included_module
         | 
| 830 | 
            +
                    task_class task_klass
         | 
| 831 | 
            +
                    mailbox.max_size = 100
         | 
| 832 | 
            +
                  end
         | 
| 833 | 
            +
                end
         | 
| 834 | 
            +
             | 
| 835 | 
            +
                it "configures the mailbox limit" do
         | 
| 836 | 
            +
                  subject.new.mailbox.max_size.should == 100
         | 
| 837 | 
            +
                end
         | 
| 838 | 
            +
              end
         | 
| 839 | 
            +
             | 
| 782 840 | 
             
              context :proxy_class do
         | 
| 783 | 
            -
                class ExampleProxy < Celluloid::ActorProxy | 
| 841 | 
            +
                class ExampleProxy < Celluloid::ActorProxy
         | 
| 842 | 
            +
                  def subclass_proxy?
         | 
| 843 | 
            +
                    true
         | 
| 844 | 
            +
                  end
         | 
| 845 | 
            +
                end
         | 
| 784 846 |  | 
| 785 847 | 
             
                subject do
         | 
| 786 848 | 
             
                  Class.new do
         | 
| 787 849 | 
             
                    include included_module
         | 
| 850 | 
            +
                    task_class task_klass
         | 
| 788 851 | 
             
                    proxy_class ExampleProxy
         | 
| 789 852 | 
             
                  end
         | 
| 790 853 | 
             
                end
         | 
| 791 854 |  | 
| 792 855 | 
             
                it "uses user-specified proxy" do
         | 
| 793 | 
            -
                  subject.new. | 
| 856 | 
            +
                  subject.new.should be_subclass_proxy
         | 
| 794 857 | 
             
                end
         | 
| 795 858 |  | 
| 796 859 | 
             
                it "retains custom proxy when subclassed" do
         | 
| 797 860 | 
             
                  subclass = Class.new(subject)
         | 
| 798 | 
            -
                  subclass.new. | 
| 861 | 
            +
                  subclass.new.should be_subclass_proxy
         | 
| 799 862 | 
             
                end
         | 
| 800 863 | 
             
              end
         | 
| 801 864 |  |