celluloid 0.6.2 → 0.7.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.
@@ -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