celluloid 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,52 @@
1
+ shared_context "a Celluloid Mailbox" do
2
+ class TestEvent < Celluloid::SystemEvent; end
3
+
4
+ it "receives messages" do
5
+ message = :ohai
6
+
7
+ subject << message
8
+ subject.receive.should == message
9
+ end
10
+
11
+ it "raises system events when received" do
12
+ subject.system_event TestEvent.new("example")
13
+
14
+ expect do
15
+ subject.receive
16
+ end.to raise_exception(TestEvent)
17
+ end
18
+
19
+ it "prioritizes system events over other messages" do
20
+ subject << :dummy1
21
+ subject << :dummy2
22
+ subject.system_event TestEvent.new("example")
23
+
24
+ expect do
25
+ subject.receive
26
+ end.to raise_exception(TestEvent)
27
+ end
28
+
29
+ it "selectively receives messages with a block" do
30
+ class Foo; end
31
+ class Bar; end
32
+ class Baz; end
33
+
34
+ foo, bar, baz = Foo.new, Bar.new, Baz.new
35
+
36
+ subject << baz
37
+ subject << foo
38
+ subject << bar
39
+
40
+ subject.receive { |msg| msg.is_a? Foo }.should == foo
41
+ subject.receive { |msg| msg.is_a? Bar }.should == bar
42
+ subject.receive.should == baz
43
+ end
44
+
45
+ it "waits for a given timeout interval" do
46
+ interval = 0.1
47
+ started_at = Time.now
48
+
49
+ subject.receive(interval) { false }
50
+ (Time.now - started_at).should be_within(Celluloid::Timer::QUANTUM).of interval
51
+ end
52
+ 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.6.2
4
+ version: 0.7.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: 2011-11-30 00:00:00.000000000 Z
12
+ date: 2011-12-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &70122472224600 !ruby/object:Gem::Requirement
16
+ requirement: &70176959879340 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70122472224600
24
+ version_requirements: *70176959879340
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &70122472224020 !ruby/object:Gem::Requirement
27
+ requirement: &70176959878380 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: 2.7.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70122472224020
35
+ version_requirements: *70176959878380
36
36
  description: Celluloid is a concurrent object framework inspired by the Actor Model
37
37
  email:
38
38
  - tony@medioh.com
@@ -49,11 +49,8 @@ files:
49
49
  - lib/celluloid/core_ext.rb
50
50
  - lib/celluloid/events.rb
51
51
  - lib/celluloid/fiber.rb
52
+ - lib/celluloid/fsm.rb
52
53
  - lib/celluloid/future.rb
53
- - lib/celluloid/io/mailbox.rb
54
- - lib/celluloid/io/reactor.rb
55
- - lib/celluloid/io/waker.rb
56
- - lib/celluloid/io.rb
57
54
  - lib/celluloid/links.rb
58
55
  - lib/celluloid/logger.rb
59
56
  - lib/celluloid/mailbox.rb
@@ -63,9 +60,13 @@ files:
63
60
  - lib/celluloid/rspec.rb
64
61
  - lib/celluloid/signals.rb
65
62
  - lib/celluloid/supervisor.rb
63
+ - lib/celluloid/task.rb
66
64
  - lib/celluloid/tcp_server.rb
65
+ - lib/celluloid/timers.rb
67
66
  - lib/celluloid/version.rb
68
67
  - lib/celluloid.rb
68
+ - spec/support/actor_examples.rb
69
+ - spec/support/mailbox_examples.rb
69
70
  homepage: https://github.com/tarcieri/celluloid
70
71
  licenses:
71
72
  - MIT
@@ -92,4 +93,3 @@ signing_key:
92
93
  specification_version: 3
93
94
  summary: Celluloid is a concurrent object framework inspired by the Actor Model
94
95
  test_files: []
95
- has_rdoc:
@@ -1,24 +0,0 @@
1
- require 'celluloid/io/waker'
2
- require 'celluloid/io/reactor'
3
- require 'celluloid/io/mailbox'
4
-
5
- module Celluloid
6
- # Actors which can run alongside other I/O operations
7
- module IO
8
- def self.included(klass)
9
- klass.send :include, ::Celluloid
10
- klass.use_mailbox Celluloid::IO::Mailbox
11
- end
12
-
13
- # Wait for the given IO object to become readable
14
- def wait_readable(io, &block)
15
- # Law of demeter be damned!
16
- current_actor.mailbox.reactor.wait_readable(io, &block)
17
- end
18
-
19
- # Wait for the given IO object to become writeable
20
- def wait_writeable(io, &block)
21
- current_actor.mailbox.reactor.wait_writeable(io, &block)
22
- end
23
- end
24
- end
@@ -1,65 +0,0 @@
1
- require 'thread'
2
-
3
- module Celluloid
4
- module IO
5
- # An alternative implementation of Celluloid::Mailbox using Wakers
6
- class Mailbox < Celluloid::Mailbox
7
- attr_reader :reactor, :waker
8
-
9
- def initialize
10
- @messages = []
11
- @lock = Mutex.new
12
- @waker = Waker.new
13
- @reactor = Reactor.new(@waker)
14
- end
15
-
16
- # Add a message to the Mailbox
17
- def <<(message)
18
- @lock.synchronize do
19
- @messages << message
20
- @waker.signal
21
- end
22
- nil
23
- rescue DeadWakerError
24
- raise MailboxError, "dead recipient"
25
- end
26
-
27
- # Add a high-priority system event to the Mailbox
28
- def system_event(event)
29
- @lock.synchronize do
30
- @messages.unshift event
31
-
32
- begin
33
- @waker.signal
34
- rescue DeadWakerError
35
- # Silently fail if messages are sent to dead actors
36
- end
37
- end
38
- nil
39
- end
40
-
41
- # Receive a message from the Mailbox
42
- def receive(&block)
43
- message = nil
44
-
45
- begin
46
- @reactor.run_once do
47
- @waker.wait
48
- message = next_message(&block)
49
- end
50
- end until message
51
-
52
- message
53
- rescue IOError, DeadWakerError
54
- shutdown # force shutdown of the mailbox
55
- raise MailboxShutdown, "mailbox shutdown called during receive"
56
- end
57
-
58
- # Cleanup any IO objects this Mailbox may be using
59
- def shutdown
60
- @waker.cleanup
61
- super
62
- end
63
- end
64
- end
65
- end
@@ -1,63 +0,0 @@
1
- module Celluloid
2
- module IO
3
- # React to external I/O events. This is kinda sorta supposed to resemble the
4
- # Reactor design pattern.
5
- class Reactor
6
- def initialize(waker)
7
- @waker = waker
8
- @readers = {}
9
- @writers = {}
10
- end
11
-
12
- # Wait for the given IO object to become readable
13
- def wait_readable(io)
14
- monitor_io io, @readers
15
- Fiber.yield
16
- block_given? ? yield(io) : io
17
- end
18
-
19
- # Wait for the given IO object to become writeable
20
- def wait_writeable(io)
21
- monitor_io io, @writers
22
- Fiber.yield
23
- block_given? ? yield(io) : io
24
- end
25
-
26
- # Run the reactor, waiting for events, and calling the given block if
27
- # the reactor is awoken by the waker
28
- def run_once
29
- readers, writers = select @readers.keys << @waker.io, @writers.keys
30
- yield if readers.include? @waker.io
31
-
32
- [[readers, @readers], [writers, @writers]].each do |ios, registered|
33
- ios.each do |io|
34
- fiber = registered.delete io
35
- fiber.resume if fiber
36
- end
37
- end
38
- end
39
-
40
- #######
41
- private
42
- #######
43
-
44
- def monitor_io(io, set)
45
- # zomg ugly type conversion :(
46
- unless io.is_a?(IO)
47
- if IO.respond_to? :try_convert
48
- io = IO.try_convert(io)
49
- elsif io.respond_to? :to_io
50
- io = io.to_io
51
- else raise TypeError, "can't convert #{io.class} into IO"
52
- end
53
- end
54
-
55
- if set.has_key? io
56
- raise ArgumentError, "another method is already waiting on #{io.inspect}"
57
- else
58
- set[io] = Fiber.current
59
- end
60
- end
61
- end
62
- end
63
- end
@@ -1,43 +0,0 @@
1
- module Celluloid
2
- module IO
3
- class DeadWakerError < StandardError; end # You can't wake the dead
4
-
5
- # Wakes up sleepy threads so that they can check their mailbox
6
- # Works like a ConditionVariable, except it's implemented as an IO object so
7
- # that it can be multiplexed alongside other IO objects.
8
- class Waker
9
- PAYLOAD = "\0" # the payload doesn't matter. each byte is a signal
10
- def initialize
11
- @receiver, @sender = ::IO.pipe
12
- end
13
-
14
- # Wakes up the thread that is waiting for this Waker
15
- def signal
16
- @sender << PAYLOAD
17
- nil
18
- rescue IOError, Errno::EPIPE, Errno::EBADF
19
- raise DeadWakerError, "waker is already dead"
20
- end
21
-
22
- # Wait for another thread to signal this Waker
23
- def wait
24
- byte = @receiver.read(1)
25
- raise DeadWakerError, "can't wait on a dead waker" unless byte == PAYLOAD
26
- rescue IOError, RuntimeError
27
- raise DeadWakerError, "can't wait on a dead waker"
28
- end
29
-
30
- # Return the IO object which will be readable when this Waker is signaled
31
- def io
32
- @receiver
33
- end
34
-
35
- # Clean up the IO objects associated with this waker
36
- def cleanup
37
- @receiver.close rescue nil
38
- @sender.close rescue nil
39
- nil
40
- end
41
- end
42
- end
43
- end