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
|
|