celluloid 0.13.0 → 0.14.1
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/actor.rb +33 -30
- data/lib/celluloid/autostart.rb +0 -13
- data/lib/celluloid/calls.rb +71 -23
- data/lib/celluloid/condition.rb +32 -28
- 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 +22 -31
- data/lib/celluloid/internal_pool.rb +13 -0
- 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 +17 -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 +10 -10
- data/lib/celluloid/system_events.rb +1 -0
- data/lib/celluloid/tasks/task_fiber.rb +9 -47
- data/lib/celluloid/tasks/task_thread.rb +9 -44
- data/lib/celluloid/tasks.rb +63 -2
- data/lib/celluloid/thread.rb +38 -0
- data/lib/celluloid/thread_handle.rb +5 -3
- data/lib/celluloid/version.rb +1 -1
- data/lib/celluloid.rb +84 -32
- data/spec/support/actor_examples.rb +92 -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
|
@@ -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
|
|
@@ -317,6 +332,7 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
317
332
|
let(:supervisor_class) do
|
|
318
333
|
Class.new do # like a boss
|
|
319
334
|
include included_module
|
|
335
|
+
task_class task_klass
|
|
320
336
|
trap_exit :lambaste_subordinate
|
|
321
337
|
|
|
322
338
|
def initialize(name)
|
|
@@ -403,7 +419,7 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
403
419
|
end.to raise_exception(ExampleCrash)
|
|
404
420
|
|
|
405
421
|
sleep 0.1 # hax to prevent a race between exit handling and the next call
|
|
406
|
-
chuck.links.count.should
|
|
422
|
+
chuck.links.count.should be(0)
|
|
407
423
|
end
|
|
408
424
|
end
|
|
409
425
|
|
|
@@ -411,6 +427,7 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
411
427
|
before do
|
|
412
428
|
@signaler = Class.new do
|
|
413
429
|
include included_module
|
|
430
|
+
task_class task_klass
|
|
414
431
|
|
|
415
432
|
def initialize
|
|
416
433
|
@waiting = false
|
|
@@ -466,7 +483,7 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
466
483
|
obj.should_not be_signaled
|
|
467
484
|
|
|
468
485
|
obj.send_signal(:foobar).should be_true
|
|
469
|
-
future.value.should
|
|
486
|
+
future.value.should be(:foobar)
|
|
470
487
|
end
|
|
471
488
|
end
|
|
472
489
|
|
|
@@ -474,6 +491,7 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
474
491
|
subject do
|
|
475
492
|
Class.new do
|
|
476
493
|
include included_module
|
|
494
|
+
task_class task_klass
|
|
477
495
|
|
|
478
496
|
attr_reader :tasks
|
|
479
497
|
|
|
@@ -516,14 +534,14 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
516
534
|
subject.async.exclusive_with_block_log_task(:one)
|
|
517
535
|
subject.async.log_task(:two)
|
|
518
536
|
sleep Celluloid::TIMER_QUANTUM * 2
|
|
519
|
-
subject.tasks.should
|
|
537
|
+
subject.tasks.should eq([:one, :two])
|
|
520
538
|
end
|
|
521
539
|
|
|
522
540
|
it "executes methods in the proper order with a class-level annotation" do
|
|
523
541
|
subject.async.exclusive_log_task :one
|
|
524
542
|
subject.async.log_task :two
|
|
525
543
|
sleep Celluloid::TIMER_QUANTUM * 2
|
|
526
|
-
subject.tasks.should
|
|
544
|
+
subject.tasks.should eq([:one, :two])
|
|
527
545
|
end
|
|
528
546
|
|
|
529
547
|
it "knows when it's in exclusive mode" do
|
|
@@ -540,6 +558,7 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
540
558
|
subject do
|
|
541
559
|
Class.new do
|
|
542
560
|
include included_module
|
|
561
|
+
task_class task_klass
|
|
543
562
|
exclusive
|
|
544
563
|
|
|
545
564
|
attr_reader :tasks
|
|
@@ -564,7 +583,7 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
564
583
|
actor.async.eat_donuts
|
|
565
584
|
actor.async.drink_coffee
|
|
566
585
|
sleep Celluloid::TIMER_QUANTUM * 2
|
|
567
|
-
actor.tasks.should
|
|
586
|
+
actor.tasks.should eq(['donuts', 'coffee'])
|
|
568
587
|
end
|
|
569
588
|
end
|
|
570
589
|
|
|
@@ -572,6 +591,8 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
572
591
|
before do
|
|
573
592
|
@receiver = Class.new do
|
|
574
593
|
include included_module
|
|
594
|
+
task_class task_klass
|
|
595
|
+
execute_block_on_receiver :signal_myself
|
|
575
596
|
|
|
576
597
|
def signal_myself(obj, &block)
|
|
577
598
|
current_actor.mailbox << obj
|
|
@@ -584,12 +605,12 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
584
605
|
let(:message) { Object.new }
|
|
585
606
|
|
|
586
607
|
it "allows unconditional receive" do
|
|
587
|
-
receiver.signal_myself(message).should
|
|
608
|
+
receiver.signal_myself(message).should eq(message)
|
|
588
609
|
end
|
|
589
610
|
|
|
590
611
|
it "allows arbitrary selective receive" do
|
|
591
612
|
received_obj = receiver.signal_myself(message) { |o| o == message }
|
|
592
|
-
received_obj.should
|
|
613
|
+
received_obj.should eq(message)
|
|
593
614
|
end
|
|
594
615
|
|
|
595
616
|
it "times out after the given interval", :pending => ENV['CI'] do
|
|
@@ -605,6 +626,7 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
605
626
|
before do
|
|
606
627
|
@klass = Class.new do
|
|
607
628
|
include included_module
|
|
629
|
+
task_class task_klass
|
|
608
630
|
|
|
609
631
|
def initialize
|
|
610
632
|
@sleeping = false
|
|
@@ -653,9 +675,8 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
653
675
|
actor = @klass.new
|
|
654
676
|
|
|
655
677
|
interval = Celluloid::TIMER_QUANTUM * 10
|
|
656
|
-
started_at = Time.now
|
|
657
678
|
|
|
658
|
-
|
|
679
|
+
actor.fire_after(interval)
|
|
659
680
|
actor.should_not be_fired
|
|
660
681
|
|
|
661
682
|
sleep(interval + Celluloid::TIMER_QUANTUM) # wonky! #/
|
|
@@ -666,23 +687,21 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
666
687
|
actor = @klass.new
|
|
667
688
|
|
|
668
689
|
interval = Celluloid::TIMER_QUANTUM * 10
|
|
669
|
-
started_at = Time.now
|
|
670
690
|
|
|
671
|
-
|
|
672
|
-
actor.fired.should
|
|
691
|
+
actor.fire_every(interval)
|
|
692
|
+
actor.fired.should be_zero
|
|
673
693
|
|
|
674
694
|
sleep(interval + Celluloid::TIMER_QUANTUM) # wonky! #/
|
|
675
|
-
actor.fired.should be
|
|
695
|
+
actor.fired.should be 1
|
|
676
696
|
|
|
677
697
|
2.times { sleep(interval + Celluloid::TIMER_QUANTUM) } # wonky! #/
|
|
678
|
-
actor.fired.should be
|
|
698
|
+
actor.fired.should be 3
|
|
679
699
|
end
|
|
680
700
|
|
|
681
701
|
it "cancels timers before they fire" do
|
|
682
702
|
actor = @klass.new
|
|
683
703
|
|
|
684
704
|
interval = Celluloid::TIMER_QUANTUM * 10
|
|
685
|
-
started_at = Time.now
|
|
686
705
|
|
|
687
706
|
timer = actor.fire_after(interval)
|
|
688
707
|
actor.should_not be_fired
|
|
@@ -696,10 +715,9 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
696
715
|
actor = @klass.new
|
|
697
716
|
|
|
698
717
|
interval = Celluloid::TIMER_QUANTUM * 10
|
|
699
|
-
started_at = Time.now
|
|
700
718
|
fired = false
|
|
701
719
|
|
|
702
|
-
|
|
720
|
+
actor.after(interval) do
|
|
703
721
|
fired = true
|
|
704
722
|
end
|
|
705
723
|
fired.should be_false
|
|
@@ -713,6 +731,7 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
713
731
|
before do
|
|
714
732
|
@klass = Class.new do
|
|
715
733
|
include included_module
|
|
734
|
+
task_class task_klass
|
|
716
735
|
attr_reader :blocker
|
|
717
736
|
|
|
718
737
|
def initialize
|
|
@@ -741,21 +760,21 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
741
760
|
actor = @klass.new
|
|
742
761
|
|
|
743
762
|
tasks = actor.tasks
|
|
744
|
-
tasks.size.should
|
|
763
|
+
tasks.size.should be 1
|
|
745
764
|
|
|
746
|
-
|
|
765
|
+
actor.future(:blocking_call)
|
|
747
766
|
sleep 0.1 # hax! waiting for ^^^ call to actually start
|
|
748
767
|
|
|
749
768
|
tasks = actor.tasks
|
|
750
|
-
tasks.size.should
|
|
769
|
+
tasks.size.should be 2
|
|
751
770
|
|
|
752
771
|
blocking_task = tasks.find { |t| t.status != :running }
|
|
753
|
-
blocking_task.should be_a
|
|
754
|
-
blocking_task.status.should
|
|
772
|
+
blocking_task.should be_a task_klass
|
|
773
|
+
blocking_task.status.should be :callwait
|
|
755
774
|
|
|
756
775
|
actor.blocker.unblock
|
|
757
776
|
sleep 0.1 # hax again :(
|
|
758
|
-
actor.tasks.size.should
|
|
777
|
+
actor.tasks.size.should be 1
|
|
759
778
|
end
|
|
760
779
|
end
|
|
761
780
|
|
|
@@ -765,6 +784,7 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
765
784
|
subject do
|
|
766
785
|
Class.new do
|
|
767
786
|
include included_module
|
|
787
|
+
task_class task_klass
|
|
768
788
|
mailbox_class ExampleMailbox
|
|
769
789
|
end
|
|
770
790
|
end
|
|
@@ -779,23 +799,42 @@ shared_context "a Celluloid Actor" do |included_module|
|
|
|
779
799
|
end
|
|
780
800
|
end
|
|
781
801
|
|
|
802
|
+
context :mailbox_limit do
|
|
803
|
+
subject do
|
|
804
|
+
Class.new do
|
|
805
|
+
include included_module
|
|
806
|
+
task_class task_klass
|
|
807
|
+
mailbox.max_size = 100
|
|
808
|
+
end
|
|
809
|
+
end
|
|
810
|
+
|
|
811
|
+
it "configures the mailbox limit" do
|
|
812
|
+
subject.new.mailbox.max_size.should == 100
|
|
813
|
+
end
|
|
814
|
+
end
|
|
815
|
+
|
|
782
816
|
context :proxy_class do
|
|
783
|
-
class ExampleProxy < Celluloid::ActorProxy
|
|
817
|
+
class ExampleProxy < Celluloid::ActorProxy
|
|
818
|
+
def subclass_proxy?
|
|
819
|
+
true
|
|
820
|
+
end
|
|
821
|
+
end
|
|
784
822
|
|
|
785
823
|
subject do
|
|
786
824
|
Class.new do
|
|
787
825
|
include included_module
|
|
826
|
+
task_class task_klass
|
|
788
827
|
proxy_class ExampleProxy
|
|
789
828
|
end
|
|
790
829
|
end
|
|
791
830
|
|
|
792
831
|
it "uses user-specified proxy" do
|
|
793
|
-
subject.new.
|
|
832
|
+
subject.new.should be_subclass_proxy
|
|
794
833
|
end
|
|
795
834
|
|
|
796
835
|
it "retains custom proxy when subclassed" do
|
|
797
836
|
subclass = Class.new(subject)
|
|
798
|
-
subclass.new.
|
|
837
|
+
subclass.new.should be_subclass_proxy
|
|
799
838
|
end
|
|
800
839
|
end
|
|
801
840
|
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
module ExampleActorClass
|
|
2
|
-
def self.create(included_module)
|
|
2
|
+
def self.create(included_module, task_klass)
|
|
3
3
|
Class.new do
|
|
4
4
|
include included_module
|
|
5
|
+
task_class task_klass
|
|
5
6
|
attr_reader :name
|
|
6
7
|
finalizer :my_finalizer
|
|
8
|
+
execute_block_on_receiver :run_on_receiver
|
|
7
9
|
|
|
8
10
|
def initialize(name)
|
|
9
11
|
@name = name
|
|
@@ -30,6 +32,10 @@ module ExampleActorClass
|
|
|
30
32
|
yield(*args)
|
|
31
33
|
end
|
|
32
34
|
|
|
35
|
+
def run_on_receiver(*args)
|
|
36
|
+
yield(*args)
|
|
37
|
+
end
|
|
38
|
+
|
|
33
39
|
def crash
|
|
34
40
|
raise ExampleCrash, "the spec purposely crashed me :("
|
|
35
41
|
end
|
|
@@ -25,9 +25,9 @@ shared_context "a Celluloid Mailbox" do
|
|
|
25
25
|
subject << foo
|
|
26
26
|
subject << bar
|
|
27
27
|
|
|
28
|
-
subject.receive { |msg| msg.is_a? Foo }.should
|
|
29
|
-
subject.receive { |msg| msg.is_a? Bar }.should
|
|
30
|
-
subject.receive.should
|
|
28
|
+
subject.receive { |msg| msg.is_a? Foo }.should eq(foo)
|
|
29
|
+
subject.receive { |msg| msg.is_a? Bar }.should eq(bar)
|
|
30
|
+
subject.receive.should eq(baz)
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
it "waits for a given timeout interval" do
|
|
@@ -37,4 +37,30 @@ shared_context "a Celluloid Mailbox" do
|
|
|
37
37
|
subject.receive(interval) { false }
|
|
38
38
|
(Time.now - started_at).should be_within(Celluloid::TIMER_QUANTUM).of interval
|
|
39
39
|
end
|
|
40
|
+
|
|
41
|
+
it "has a size" do
|
|
42
|
+
subject.should respond_to(:size)
|
|
43
|
+
subject.size.should be_zero
|
|
44
|
+
subject << :foo
|
|
45
|
+
subject << :foo
|
|
46
|
+
subject.size.should be 2
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "discards messages received when when full" do
|
|
50
|
+
subject.max_size = 2
|
|
51
|
+
subject << :first
|
|
52
|
+
subject << :second
|
|
53
|
+
subject << :third
|
|
54
|
+
subject.to_a.should =~ [:first, :second]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "logs discarded messages" do
|
|
58
|
+
Celluloid.logger = mock.as_null_object
|
|
59
|
+
Celluloid.logger.should_receive(:debug).with("Discarded message: third")
|
|
60
|
+
|
|
61
|
+
subject.max_size = 2
|
|
62
|
+
subject << :first
|
|
63
|
+
subject << :second
|
|
64
|
+
subject << :third
|
|
65
|
+
end
|
|
40
66
|
end
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
attr_reader :tasks
|
|
1
|
+
class MockActor
|
|
2
|
+
attr_reader :tasks
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
end
|
|
4
|
+
def initialize
|
|
5
|
+
@tasks = []
|
|
8
6
|
end
|
|
9
7
|
|
|
8
|
+
def setup_thread
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
shared_context "a Celluloid Task" do |task_class|
|
|
10
13
|
let(:task_type) { :foobar }
|
|
11
14
|
let(:suspend_state) { :doing_something }
|
|
12
15
|
let(:actor) { MockActor.new }
|
|
@@ -22,13 +25,13 @@ shared_context "a Celluloid Task" do |task_class|
|
|
|
22
25
|
end
|
|
23
26
|
|
|
24
27
|
it "begins with status :new" do
|
|
25
|
-
subject.status.should
|
|
28
|
+
subject.status.should be :new
|
|
26
29
|
end
|
|
27
30
|
|
|
28
31
|
it "resumes" do
|
|
29
32
|
subject.should be_running
|
|
30
33
|
subject.resume
|
|
31
|
-
subject.status.should
|
|
34
|
+
subject.status.should eq(suspend_state)
|
|
32
35
|
subject.resume
|
|
33
36
|
subject.should_not be_running
|
|
34
37
|
end
|
|
@@ -41,5 +44,4 @@ shared_context "a Celluloid Task" do |task_class|
|
|
|
41
44
|
task.resume
|
|
42
45
|
end.to raise_exception("failure")
|
|
43
46
|
end
|
|
44
|
-
|
|
45
47
|
end
|