celluloid 0.13.0 → 0.14.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|