celluloid 0.11.1 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,17 +19,34 @@ shared_context "a Celluloid Actor" do |included_module|
19
19
  end.should be_true
20
20
  end
21
21
 
22
- it "handles synchronous calls" do
22
+ it "can be stored in hashes" do
23
+ actor = actor_class.new "Troy McClure"
24
+ actor.hash.should_not == Kernel.hash
25
+ actor.object_id.should_not == Kernel.object_id
26
+ end
27
+
28
+ it "supports synchronous calls" do
23
29
  actor = actor_class.new "Troy McClure"
24
30
  actor.greet.should == "Hi, I'm Troy McClure"
25
31
  end
26
32
 
27
- it "handles futures for synchronous calls" do
33
+ it "supports synchronous calls via #method" do
34
+ method = actor_class.new("Troy McClure").method(:greet)
35
+ method.call.should == "Hi, I'm Troy McClure"
36
+ end
37
+
38
+ it "supports future(:method) syntax for synchronous future calls" do
28
39
  actor = actor_class.new "Troy McClure"
29
40
  future = actor.future :greet
30
41
  future.value.should == "Hi, I'm Troy McClure"
31
42
  end
32
43
 
44
+ it "supports future.method syntax for synchronous future calls" do
45
+ actor = actor_class.new "Troy McClure"
46
+ future = actor.future.greet
47
+ future.value.should == "Hi, I'm Troy McClure"
48
+ end
49
+
33
50
  it "handles circular synchronous calls" do
34
51
  klass = Class.new do
35
52
  include included_module
@@ -54,6 +71,12 @@ shared_context "a Celluloid Actor" do |included_module|
54
71
  actor.first.should be == :bar
55
72
  end
56
73
 
74
+ it "properly handles respond_to with include_private" do
75
+ actor = actor_class.new "Method missing privates"
76
+ actor.respond_to?(:zomg_private).should be_false
77
+ actor.respond_to?(:zomg_private, true).should be_true
78
+ end
79
+
57
80
  it "raises NoMethodError when a nonexistent method is called" do
58
81
  actor = actor_class.new "Billy Bob Thornton"
59
82
 
@@ -119,19 +142,31 @@ shared_context "a Celluloid Actor" do |included_module|
119
142
  end.to raise_exception(Celluloid::DeadActorError)
120
143
  end
121
144
 
122
- it "handles asynchronous calls" do
145
+ it "supports method! syntax for asynchronous calls" do
123
146
  actor = actor_class.new "Troy McClure"
124
147
  actor.change_name! "Charlie Sheen"
125
148
  actor.greet.should == "Hi, I'm Charlie Sheen"
126
149
  end
127
150
 
128
- it "handles asynchronous calls via #async" do
151
+ it "supports async(:method) syntax for asynchronous calls" do
129
152
  actor = actor_class.new "Troy McClure"
130
153
  actor.async :change_name, "Charlie Sheen"
131
154
  actor.greet.should == "Hi, I'm Charlie Sheen"
132
155
  end
133
156
 
134
- it "handles asynchronous calls to itself" do
157
+ it "supports async.method syntax for asynchronous calls" do
158
+ actor = actor_class.new "Troy McClure"
159
+ actor.async.change_name "Charlie Sheen"
160
+ actor.greet.should == "Hi, I'm Charlie Sheen"
161
+ end
162
+
163
+ it "supports method! syntax for asynchronous calls to itself" do
164
+ actor = actor_class.new "Troy McClure"
165
+ actor.change_name_with_a_bang "Charlie Sheen"
166
+ actor.greet.should == "Hi, I'm Charlie Sheen"
167
+ end
168
+
169
+ it "supports async.method syntax for asynchronous calls to itself" do
135
170
  actor = actor_class.new "Troy McClure"
136
171
  actor.change_name_async "Charlie Sheen"
137
172
  actor.greet.should == "Hi, I'm Charlie Sheen"
@@ -193,15 +228,15 @@ shared_context "a Celluloid Actor" do |included_module|
193
228
  actor = actor_class.new "Arnold Schwarzenegger"
194
229
  actor.should be_alive
195
230
  actor.terminate
196
- actor.join
231
+ Celluloid::Actor.join(actor)
197
232
  actor.should_not be_alive
198
233
  end
199
234
 
200
235
  it "kills" do
201
236
  actor = actor_class.new "Woody Harrelson"
202
237
  actor.should be_alive
203
- actor.kill
204
- actor.join
238
+ Celluloid::Actor.kill(actor)
239
+ Celluloid::Actor.join(actor)
205
240
  actor.should_not be_alive
206
241
  end
207
242
 
@@ -213,6 +248,15 @@ shared_context "a Celluloid Actor" do |included_module|
213
248
  actor.greet
214
249
  end.to raise_exception(Celluloid::DeadActorError)
215
250
  end
251
+
252
+ it "raises the right DeadActorError if terminate! called after terminated" do
253
+ actor = actor_class.new "Arnold Schwarzenegger"
254
+ actor.terminate
255
+
256
+ expect do
257
+ actor.terminate!
258
+ end.to raise_exception(Celluloid::DeadActorError, "actor already terminated")
259
+ end
216
260
  end
217
261
 
218
262
  context :current_actor do
@@ -236,16 +280,39 @@ shared_context "a Celluloid Actor" do |included_module|
236
280
 
237
281
  it "links to other actors" do
238
282
  @kevin.link @charlie
239
- @kevin.linked_to?(@charlie).should be_true
240
- @charlie.linked_to?(@kevin).should be_true
283
+ @kevin.monitoring?(@charlie).should be_true
284
+ @kevin.linked_to?(@charlie).should be_true
285
+ @charlie.monitoring?(@kevin).should be_true
286
+ @charlie.linked_to?(@kevin).should be_true
241
287
  end
242
288
 
243
289
  it "unlinks from other actors" do
244
290
  @kevin.link @charlie
245
291
  @kevin.unlink @charlie
246
292
 
247
- @kevin.linked_to?(@charlie).should be_false
248
- @charlie.linked_to?(@kevin).should be_false
293
+ @kevin.monitoring?(@charlie).should be_false
294
+ @kevin.linked_to?(@charlie).should be_false
295
+ @charlie.monitoring?(@kevin).should be_false
296
+ @charlie.linked_to?(@kevin).should be_false
297
+ end
298
+
299
+ it "monitors other actors unidirectionally" do
300
+ @kevin.monitor @charlie
301
+
302
+ @kevin.monitoring?(@charlie).should be_true
303
+ @kevin.linked_to?(@charlie).should be_false
304
+ @charlie.monitoring?(@kevin).should be_false
305
+ @charlie.linked_to?(@kevin).should be_false
306
+ end
307
+
308
+ it "unmonitors other actors" do
309
+ @kevin.monitor @charlie
310
+ @kevin.unmonitor @charlie
311
+
312
+ @kevin.monitoring?(@charlie).should be_false
313
+ @kevin.linked_to?(@charlie).should be_false
314
+ @charlie.monitoring?(@kevin).should be_false
315
+ @charlie.linked_to?(@kevin).should be_false
249
316
  end
250
317
 
251
318
  it "traps exit messages from other actors" do
@@ -325,7 +392,6 @@ shared_context "a Celluloid Actor" do |included_module|
325
392
  obj.should be_signaled
326
393
  end
327
394
 
328
- # FIXME: This is deadlocking on Travis, and may still have issues
329
395
  it "sends values along with signals" do
330
396
  obj = @signaler.new
331
397
  obj.should_not be_signaled
@@ -357,6 +423,38 @@ shared_context "a Celluloid Actor" do |included_module|
357
423
  end
358
424
  end
359
425
 
426
+ context "exclusive classes" do
427
+ subject do
428
+ Class.new do
429
+ include included_module
430
+ exclusive
431
+
432
+ attr_reader :tasks
433
+
434
+ def initialize
435
+ @tasks = []
436
+ end
437
+
438
+ def eat_donuts
439
+ sleep Celluloid::TIMER_QUANTUM
440
+ @tasks << 'donuts'
441
+ end
442
+
443
+ def drink_coffee
444
+ @tasks << 'coffee'
445
+ end
446
+ end
447
+ end
448
+
449
+ it "executes two methods in an exclusive order" do
450
+ actor = subject.new
451
+ actor.eat_donuts!
452
+ actor.drink_coffee!
453
+ sleep Celluloid::TIMER_QUANTUM * 2
454
+ actor.tasks.should == ['donuts', 'coffee']
455
+ end
456
+ end
457
+
360
458
  context :receiving do
361
459
  before do
362
460
  @receiver = Class.new do
@@ -386,13 +484,11 @@ shared_context "a Celluloid Actor" do |included_module|
386
484
  started_at = Time.now
387
485
 
388
486
  receiver.receive(interval) { false }.should be_nil
389
- (Time.now - started_at).should be_within(Q).of interval
487
+ (Time.now - started_at).should be_within(Celluloid::TIMER_QUANTUM).of interval
390
488
  end
391
489
  end
392
490
 
393
491
  context :timers do
394
- # Level of accuracy enforced by the tests (50ms)
395
- Q = 0.05
396
492
 
397
493
  before do
398
494
  @klass = Class.new do
@@ -430,7 +526,7 @@ shared_context "a Celluloid Actor" do |included_module|
430
526
 
431
527
  # Sleep long enough to ensure we're actually seeing behavior when asleep
432
528
  # but not so long as to delay the test suite unnecessarily
433
- interval = Q * 10
529
+ interval = Celluloid::TIMER_QUANTUM * 10
434
530
  started_at = Time.now
435
531
 
436
532
  future = actor.future(:do_sleep, interval)
@@ -438,49 +534,49 @@ shared_context "a Celluloid Actor" do |included_module|
438
534
  actor.should be_sleeping
439
535
 
440
536
  future.value
441
- (Time.now - started_at).should be_within(Q).of interval
537
+ (Time.now - started_at).should be_within(Celluloid::TIMER_QUANTUM).of interval
442
538
  end
443
539
 
444
540
  it "schedules timers which fire in the future" do
445
541
  actor = @klass.new
446
542
 
447
- interval = Q * 10
543
+ interval = Celluloid::TIMER_QUANTUM * 10
448
544
  started_at = Time.now
449
545
 
450
546
  timer = actor.fire_after(interval)
451
547
  actor.should_not be_fired
452
548
 
453
- sleep(interval + Q) # wonky! #/
549
+ sleep(interval + Celluloid::TIMER_QUANTUM) # wonky! #/
454
550
  actor.should be_fired
455
551
  end
456
552
 
457
553
  it "schedules recurring timers which fire in the future" do
458
554
  actor = @klass.new
459
555
 
460
- interval = Q * 10
556
+ interval = Celluloid::TIMER_QUANTUM * 10
461
557
  started_at = Time.now
462
558
 
463
559
  timer = actor.fire_every(interval)
464
560
  actor.fired.should be == 0
465
561
 
466
- sleep(interval + Q) # wonky! #/
562
+ sleep(interval + Celluloid::TIMER_QUANTUM) # wonky! #/
467
563
  actor.fired.should be == 1
468
564
 
469
- 2.times { sleep(interval + Q) } # wonky! #/
565
+ 2.times { sleep(interval + Celluloid::TIMER_QUANTUM) } # wonky! #/
470
566
  actor.fired.should be == 3
471
567
  end
472
568
 
473
569
  it "cancels timers before they fire" do
474
570
  actor = @klass.new
475
571
 
476
- interval = Q * 10
572
+ interval = Celluloid::TIMER_QUANTUM * 10
477
573
  started_at = Time.now
478
574
 
479
575
  timer = actor.fire_after(interval)
480
576
  actor.should_not be_fired
481
577
  timer.cancel
482
578
 
483
- sleep(interval + Q) # wonky! #/
579
+ sleep(interval + Celluloid::TIMER_QUANTUM) # wonky! #/
484
580
  actor.should_not be_fired
485
581
  end
486
582
  end
@@ -526,7 +622,7 @@ shared_context "a Celluloid Actor" do |included_module|
526
622
  tasks.size.should == 2
527
623
 
528
624
  blocking_task = tasks.find { |t| t.status != :running }
529
- blocking_task.should be_a Celluloid::Task
625
+ blocking_task.should be_a Celluloid.task_class
530
626
  blocking_task.status.should == :callwait
531
627
 
532
628
  actor.blocker.unblock
@@ -534,4 +630,64 @@ shared_context "a Celluloid Actor" do |included_module|
534
630
  actor.tasks.size.should == 1
535
631
  end
536
632
  end
633
+
634
+ context :use_mailbox do
635
+ class ExampleMailbox < Celluloid::Mailbox; end
636
+
637
+ subject do
638
+ Class.new do
639
+ include included_module
640
+ use_mailbox ExampleMailbox
641
+ end
642
+ end
643
+
644
+ it "uses user-specified mailboxes" do
645
+ subject.new.mailbox.should be_a ExampleMailbox
646
+ end
647
+
648
+ it "retains custom mailboxes when subclassed" do
649
+ subclass = Class.new(subject)
650
+ subclass.new.mailbox.should be_a ExampleMailbox
651
+ end
652
+ end
653
+
654
+ context :mailbox_class do
655
+ class ExampleMailbox < Celluloid::Mailbox; end
656
+
657
+ subject do
658
+ Class.new do
659
+ include included_module
660
+ mailbox_class ExampleMailbox
661
+ end
662
+ end
663
+
664
+ it "overrides the mailbox class" do
665
+ subject.new.mailbox.should be_a ExampleMailbox
666
+ end
667
+
668
+ it "retains custom mailboxes when subclassed" do
669
+ subclass = Class.new(subject)
670
+ subclass.new.mailbox.should be_a ExampleMailbox
671
+ end
672
+ end
673
+
674
+ context :task_class do
675
+ class ExampleTask < Celluloid::TaskFiber; end
676
+
677
+ subject do
678
+ Class.new do
679
+ include included_module
680
+ task_class ExampleTask
681
+ end
682
+ end
683
+
684
+ it "overrides the task class" do
685
+ subject.new.tasks.first.should be_a ExampleTask
686
+ end
687
+
688
+ it "retains custom task classes when subclassed" do
689
+ subclass = Class.new(subject)
690
+ subclass.new.tasks.first.should be_a ExampleTask
691
+ end
692
+ end
537
693
  end
@@ -13,10 +13,14 @@ module ExampleActorClass
13
13
  @name = new_name
14
14
  end
15
15
 
16
- def change_name_async(new_name)
16
+ def change_name_with_a_bang(new_name)
17
17
  change_name! new_name
18
18
  end
19
19
 
20
+ def change_name_async(new_name)
21
+ async.change_name new_name
22
+ end
23
+
20
24
  def greet
21
25
  "Hi, I'm #{@name}"
22
26
  end
@@ -55,7 +59,7 @@ module ExampleActorClass
55
59
  end
56
60
  end
57
61
 
58
- def respond_to?(method_name)
62
+ def respond_to?(method_name, include_private = false)
59
63
  super || delegates?(method_name)
60
64
  end
61
65
 
@@ -1,9 +1,4 @@
1
1
  shared_context "a Celluloid Mailbox" do
2
- # Level of timer accuracy enforced by the tests (50ms)
3
- Q = 0.05
4
-
5
- class TestEvent < Celluloid::SystemEvent; end
6
-
7
2
  it "receives messages" do
8
3
  message = :ohai
9
4
 
@@ -11,22 +6,12 @@ shared_context "a Celluloid Mailbox" do
11
6
  subject.receive.should == message
12
7
  end
13
8
 
14
- it "raises system events when received" do
15
- subject.system_event TestEvent.new("example")
16
-
17
- expect do
18
- subject.receive
19
- end.to raise_exception(TestEvent)
20
- end
21
-
22
9
  it "prioritizes system events over other messages" do
23
10
  subject << :dummy1
24
11
  subject << :dummy2
25
- subject.system_event TestEvent.new("example")
26
12
 
27
- expect do
28
- subject.receive
29
- end.to raise_exception(TestEvent)
13
+ subject << Celluloid::SystemEvent.new
14
+ subject.receive.should be_a(Celluloid::SystemEvent)
30
15
  end
31
16
 
32
17
  it "selectively receives messages with a block" do
@@ -50,6 +35,6 @@ shared_context "a Celluloid Mailbox" do
50
35
  started_at = Time.now
51
36
 
52
37
  subject.receive(interval) { false }
53
- (Time.now - started_at).should be_within(Q).of interval
38
+ (Time.now - started_at).should be_within(Celluloid::TIMER_QUANTUM).of interval
54
39
  end
55
40
  end
@@ -0,0 +1,36 @@
1
+ shared_context "a Celluloid Task" do |task_class|
2
+ class MockActor
3
+ attr_reader :tasks
4
+
5
+ def initialize
6
+ @tasks = []
7
+ end
8
+ end
9
+
10
+ let(:task_type) { :foobar }
11
+ let(:suspend_state) { :doing_something }
12
+ let(:actor) { MockActor.new }
13
+
14
+ subject { task_class.new(task_type) { Celluloid::Task.suspend(suspend_state) } }
15
+
16
+ before :each do
17
+ Thread.current[:actor] = actor
18
+ end
19
+
20
+ after :each do
21
+ Thread.current[:actor] = nil
22
+ end
23
+
24
+ it "begins with status :new" do
25
+ subject.status.should == :new
26
+ end
27
+
28
+ it "resumes" do
29
+ subject.should be_running
30
+ subject.resume
31
+ subject.status.should == suspend_state
32
+ subject.resume
33
+ subject.should_not be_running
34
+ end
35
+
36
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: celluloid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.1
4
+ version: 0.12.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-17 00:00:00.000000000 Z
12
+ date: 2012-09-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: timers
16
- requirement: &70167227984140 !ruby/object:Gem::Requirement
16
+ requirement: &70127789999080 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.0.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70167227984140
24
+ version_requirements: *70127789999080
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &70167227983760 !ruby/object:Gem::Requirement
27
+ requirement: &70127789997960 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70167227983760
35
+ version_requirements: *70127789997960
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &70167227983300 !ruby/object:Gem::Requirement
38
+ requirement: &70127789997400 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70167227983300
46
+ version_requirements: *70127789997400
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: benchmark_suite
49
- requirement: &70167227982880 !ruby/object:Gem::Requirement
49
+ requirement: &70127789996720 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70167227982880
57
+ version_requirements: *70127789996720
58
58
  description: Celluloid enables people to build concurrent programs out of concurrent
59
59
  objects just as easily as they build sequential programs out of sequential objects
60
60
  email:
@@ -65,11 +65,10 @@ extra_rdoc_files: []
65
65
  files:
66
66
  - README.md
67
67
  - lib/celluloid/actor.rb
68
- - lib/celluloid/actor_proxy.rb
68
+ - lib/celluloid/boot.rb
69
69
  - lib/celluloid/calls.rb
70
70
  - lib/celluloid/core_ext.rb
71
71
  - lib/celluloid/cpu_counter.rb
72
- - lib/celluloid/events.rb
73
72
  - lib/celluloid/fiber.rb
74
73
  - lib/celluloid/fsm.rb
75
74
  - lib/celluloid/future.rb
@@ -77,8 +76,13 @@ files:
77
76
  - lib/celluloid/links.rb
78
77
  - lib/celluloid/logger.rb
79
78
  - lib/celluloid/mailbox.rb
79
+ - lib/celluloid/method.rb
80
80
  - lib/celluloid/notifications.rb
81
81
  - lib/celluloid/pool_manager.rb
82
+ - lib/celluloid/proxies/abstract_proxy.rb
83
+ - lib/celluloid/proxies/actor_proxy.rb
84
+ - lib/celluloid/proxies/async_proxy.rb
85
+ - lib/celluloid/proxies/future_proxy.rb
82
86
  - lib/celluloid/receivers.rb
83
87
  - lib/celluloid/registry.rb
84
88
  - lib/celluloid/responses.rb
@@ -86,7 +90,10 @@ files:
86
90
  - lib/celluloid/signals.rb
87
91
  - lib/celluloid/supervision_group.rb
88
92
  - lib/celluloid/supervisor.rb
93
+ - lib/celluloid/system_events.rb
89
94
  - lib/celluloid/task.rb
95
+ - lib/celluloid/tasks/task_fiber.rb
96
+ - lib/celluloid/tasks/task_thread.rb
90
97
  - lib/celluloid/thread_handle.rb
91
98
  - lib/celluloid/uuid.rb
92
99
  - lib/celluloid/version.rb
@@ -94,6 +101,7 @@ files:
94
101
  - spec/support/actor_examples.rb
95
102
  - spec/support/example_actor_class.rb
96
103
  - spec/support/mailbox_examples.rb
104
+ - spec/support/task_examples.rb
97
105
  homepage: https://github.com/celluloid/celluloid
98
106
  licenses:
99
107
  - MIT
@@ -106,7 +114,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
106
114
  requirements:
107
115
  - - ! '>='
108
116
  - !ruby/object:Gem::Version
109
- version: '0'
117
+ version: 1.9.2
110
118
  required_rubygems_version: !ruby/object:Gem::Requirement
111
119
  none: false
112
120
  requirements:
@@ -1,26 +0,0 @@
1
- module Celluloid
2
- # Exceptional system events which need to be processed out of band
3
- class SystemEvent < Exception; end
4
-
5
- # An actor has exited for the given reason
6
- class ExitEvent < SystemEvent
7
- attr_reader :actor, :reason
8
-
9
- def initialize(actor, reason = nil)
10
- @actor, @reason = actor, reason
11
- super reason.to_s
12
- end
13
- end
14
-
15
- # Name an actor at the time it's registered
16
- class NamingRequest < SystemEvent
17
- attr_reader :name
18
-
19
- def initialize(name)
20
- @name = name
21
- end
22
- end
23
-
24
- # Request for an actor to terminate
25
- class TerminationRequest < SystemEvent; end
26
- end