celluloid-io 0.9.0 → 0.10.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.
- data/.travis.yml +4 -4
- data/CHANGES.md +6 -0
- data/Gemfile +1 -1
- data/LICENSE.txt +2 -2
- data/README.md +10 -8
- data/Rakefile +2 -4
- data/benchmarks/actor.rb +35 -0
- data/benchmarks/ring.rb +14 -0
- data/celluloid-io.gemspec +3 -2
- data/examples/echo_client.rb +25 -0
- data/lib/celluloid/io.rb +4 -3
- data/lib/celluloid/io/common_methods.rb +64 -29
- data/lib/celluloid/io/dns_resolver.rb +79 -0
- data/lib/celluloid/io/mailbox.rb +4 -2
- data/lib/celluloid/io/reactor.rb +3 -3
- data/lib/celluloid/io/tcp_socket.rb +47 -3
- data/lib/celluloid/io/version.rb +1 -1
- data/logo.png +0 -0
- data/spec/celluloid/io/actor_spec.rb +1 -1
- data/spec/celluloid/io/dns_resolver_spec.rb +8 -0
- data/tasks/benchmarks.task +19 -0
- data/tasks/rspec.task +7 -0
- metadata +32 -14
data/.travis.yml
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
rvm:
|
2
|
-
- 1.9.2
|
3
2
|
- 1.9.3
|
4
3
|
- ruby-head
|
5
4
|
- jruby-19mode
|
6
|
-
- jruby-head
|
7
5
|
|
8
|
-
#
|
9
|
-
# -
|
6
|
+
# Getting a deadlock in the nonblocking connect code :(
|
7
|
+
# - jruby-head
|
8
|
+
|
9
|
+
# See https://github.com/rubinius/rubinius/issues/1611
|
10
10
|
# - rbx-19mode
|
data/CHANGES.md
CHANGED
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) 2012 Tony Arcieri
|
2
2
|
|
3
3
|
MIT License
|
4
4
|
|
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
19
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
20
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
21
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-

|
2
2
|
=============
|
3
|
-
[](http://travis-ci.org/celluloid/celluloid-io)
|
4
|
+
[](https://gemnasium.com/celluloid/celluloid-io)
|
5
5
|
|
6
6
|
You don't have to choose between threaded and evented IO! Celluloid::IO
|
7
7
|
provides an event-driven IO system for building fast, scalable network
|
8
8
|
applications that integrates directly with the
|
9
|
-
[Celluloid actor library](https://github.com/
|
9
|
+
[Celluloid actor library](https://github.com/celluloid/celluloid), making it
|
10
10
|
easy to combine both threaded and evented concepts. Celluloid::IO is ideal for
|
11
11
|
servers which handle large numbers of mostly-idle connections, such as Websocket
|
12
12
|
servers or chat/messaging systems.
|
@@ -38,7 +38,9 @@ Like Celluloid::IO? [Join the Google Group](http://groups.google.com/group/cellu
|
|
38
38
|
Supported Platforms
|
39
39
|
-------------------
|
40
40
|
|
41
|
-
Celluloid::IO
|
41
|
+
Celluloid::IO requires Ruby 1.9 support on all Ruby VMs.
|
42
|
+
|
43
|
+
Supported VMs are Ruby 1.9.3, JRuby 1.6, and Rubinius 2.0.
|
42
44
|
|
43
45
|
To use JRuby in 1.9 mode, you'll need to pass the "--1.9" command line option
|
44
46
|
to the JRuby executable, or set the "JRUBY_OPTS=--1.9" environment variable.
|
@@ -85,7 +87,7 @@ end
|
|
85
87
|
The very first thing including *Celluloid::IO* does is also include the
|
86
88
|
*Celluloid* module, which promotes objects of this class to concurrent Celluloid
|
87
89
|
actors each running in their own thread. Before trying to use Celluloid::IO
|
88
|
-
you may want to [familiarize yourself with Celluloid in general](https://github.com/
|
90
|
+
you may want to [familiarize yourself with Celluloid in general](https://github.com/celluloid/celluloid/).
|
89
91
|
Celluloid actors can each be thought of as being event loops. Celluloid::IO actors
|
90
92
|
are heavier but have capabilities similar to other event loop-driven frameworks.
|
91
93
|
|
@@ -114,7 +116,7 @@ comes in three forms:
|
|
114
116
|
|
115
117
|
* __Reactor + Fibers:__ Celluloid::IO is a combination of Actor and Reactor
|
116
118
|
concepts. The blocking mechanism used by the mailboxes of Celluloid::IO
|
117
|
-
actors is an [nio4r-powered reactor](https://github.com/
|
119
|
+
actors is an [nio4r-powered reactor](https://github.com/celluloid/celluloid-io/blob/master/lib/celluloid/io/reactor.rb).
|
118
120
|
When the current task needs to make a blocking I/O call, it first makes
|
119
121
|
a non-blocking attempt, and if the socket isn't ready the current task
|
120
122
|
is suspended until the reactor detects the operation is ready and resumes
|
@@ -149,7 +151,7 @@ Contributing to Celluloid::IO
|
|
149
151
|
License
|
150
152
|
-------
|
151
153
|
|
152
|
-
Copyright (c)
|
154
|
+
Copyright (c) 2012 Tony Arcieri. Distributed under the MIT License. See
|
153
155
|
LICENSE.txt for further details.
|
154
156
|
|
155
157
|
Contains code originally from the RubySpec project also under the MIT License
|
data/Rakefile
CHANGED
data/benchmarks/actor.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'celluloid/io'
|
6
|
+
require 'benchmark/ips'
|
7
|
+
|
8
|
+
class ExampleActor
|
9
|
+
include Celluloid::IO
|
10
|
+
def example_method; end
|
11
|
+
end
|
12
|
+
|
13
|
+
example_actor = ExampleActor.new
|
14
|
+
mailbox = Celluloid::Mailbox.new
|
15
|
+
|
16
|
+
latch_in, latch_out = Queue.new, Queue.new
|
17
|
+
latch = Thread.new do
|
18
|
+
while true
|
19
|
+
n = latch_in.pop
|
20
|
+
for i in 0..n; mailbox.receive; end
|
21
|
+
latch_out << :done
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
Benchmark.ips do |ips|
|
26
|
+
ips.report("spawn") { ExampleActor.new.terminate }
|
27
|
+
ips.report("calls") { example_actor.example_method }
|
28
|
+
ips.report("async calls") { example_actor.example_method! }
|
29
|
+
|
30
|
+
ips.report("messages") do |n|
|
31
|
+
latch_in << n
|
32
|
+
for i in 0..n; mailbox << :message; end
|
33
|
+
latch_out.pop
|
34
|
+
end
|
35
|
+
end
|
data/benchmarks/ring.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'celluloid'
|
6
|
+
require 'benchmark/ips'
|
7
|
+
require File.expand_path("../../examples/ring", __FILE__)
|
8
|
+
|
9
|
+
# 512-node ring
|
10
|
+
ring = Ring.new 512
|
11
|
+
|
12
|
+
Benchmark.ips do |ips|
|
13
|
+
ips.report("ring-around") { |n| ring.run n }
|
14
|
+
end
|
data/celluloid-io.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
|
|
6
6
|
gem.email = ["tony.arcieri@gmail.com"]
|
7
7
|
gem.description = "Evented IO for Celluloid actors"
|
8
8
|
gem.summary = "Celluloid::IO allows you to monitor multiple IO objects within a Celluloid actor"
|
9
|
-
gem.homepage = "http://github.com/
|
9
|
+
gem.homepage = "http://github.com/celluloid/celluloid-io"
|
10
10
|
|
11
11
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
12
12
|
gem.files = `git ls-files`.split("\n")
|
@@ -15,9 +15,10 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.require_paths = ["lib"]
|
16
16
|
gem.version = Celluloid::IO::VERSION
|
17
17
|
|
18
|
-
gem.add_dependency 'celluloid', '~> 0.
|
18
|
+
gem.add_dependency 'celluloid', '~> 0.10.0'
|
19
19
|
gem.add_dependency 'nio4r', '>= 0.3.1'
|
20
20
|
|
21
21
|
gem.add_development_dependency 'rake'
|
22
22
|
gem.add_development_dependency 'rspec'
|
23
|
+
gem.add_development_dependency 'benchmark_suite'
|
23
24
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'celluloid/io'
|
6
|
+
|
7
|
+
class EchoClient
|
8
|
+
include Celluloid::IO
|
9
|
+
|
10
|
+
def initialize(host, port)
|
11
|
+
puts "*** Connecting to echo server on #{host}:#{port}"
|
12
|
+
|
13
|
+
@socket = TCPSocket.from_ruby_socket(::TCPSocket.new(host, port))
|
14
|
+
end
|
15
|
+
|
16
|
+
def echo(s)
|
17
|
+
@socket.write(s)
|
18
|
+
actor = Celluloid.current_actor
|
19
|
+
@socket.readpartial(4096)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
client = EchoClient.new("127.0.0.1", 1234)
|
25
|
+
puts client.echo("TEST FOR ECHO")
|
data/lib/celluloid/io.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
require 'forwardable'
|
1
2
|
require 'celluloid/io/version'
|
2
3
|
|
3
|
-
require 'forwardable'
|
4
4
|
require 'celluloid'
|
5
5
|
require 'celluloid/io/common_methods'
|
6
|
+
require 'celluloid/io/dns_resolver'
|
6
7
|
require 'celluloid/io/mailbox'
|
7
8
|
require 'celluloid/io/reactor'
|
8
9
|
|
@@ -20,7 +21,7 @@ module Celluloid
|
|
20
21
|
|
21
22
|
extend Forwardable
|
22
23
|
|
23
|
-
# Wait for the given IO object to become readable/
|
24
|
-
def_delegators 'current_actor.mailbox.reactor', :wait_readable, :
|
24
|
+
# Wait for the given IO object to become readable/writable
|
25
|
+
def_delegators 'current_actor.mailbox.reactor', :wait_readable, :wait_writable
|
25
26
|
end
|
26
27
|
end
|
@@ -19,8 +19,6 @@ module Celluloid
|
|
19
19
|
|
20
20
|
# Wait until the current object is writable
|
21
21
|
def wait_writable
|
22
|
-
actor = Thread.current[:actor]
|
23
|
-
|
24
22
|
if evented?
|
25
23
|
Celluloid.current_actor.wait_writable(self.to_io)
|
26
24
|
else
|
@@ -28,20 +26,60 @@ module Celluloid
|
|
28
26
|
end
|
29
27
|
end
|
30
28
|
|
29
|
+
# Request exclusive control for a particular operation
|
30
|
+
# Type should be one of :r (read) or :w (write)
|
31
|
+
def acquire_ownership(type)
|
32
|
+
return unless Thread.current[:actor]
|
33
|
+
|
34
|
+
case type
|
35
|
+
when :r
|
36
|
+
ivar = :@read_owner
|
37
|
+
when :w
|
38
|
+
ivar = :@write_owner
|
39
|
+
else raise ArgumentError, "invalid ownership type: #{type}"
|
40
|
+
end
|
41
|
+
|
42
|
+
Actor.current.wait(self) while instance_variable_get(ivar)
|
43
|
+
instance_variable_set(ivar, Task.current)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Release ownership for a particular operation
|
47
|
+
# Type should be one of :r (read) or :w (write)
|
48
|
+
def release_ownership(type)
|
49
|
+
return unless Thread.current[:actor]
|
50
|
+
|
51
|
+
case type
|
52
|
+
when :r
|
53
|
+
ivar = :@read_owner
|
54
|
+
when :w
|
55
|
+
ivar = :@write_owner
|
56
|
+
else raise ArgumentError, "invalid ownership type: #{type}"
|
57
|
+
end
|
58
|
+
|
59
|
+
raise "not owner" unless instance_variable_get(ivar) == Task.current
|
60
|
+
instance_variable_set(ivar, nil)
|
61
|
+
Actor.current.signal(self)
|
62
|
+
end
|
63
|
+
|
31
64
|
def read(length, buffer = nil)
|
32
65
|
buffer ||= ''
|
33
66
|
remaining = length
|
34
67
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
68
|
+
acquire_ownership :r
|
69
|
+
begin
|
70
|
+
until remaining.zero?
|
71
|
+
begin
|
72
|
+
str = readpartial(remaining)
|
73
|
+
rescue EOFError
|
74
|
+
return if length == remaining
|
75
|
+
return buffer
|
76
|
+
end
|
42
77
|
|
43
|
-
|
44
|
-
|
78
|
+
buffer << str
|
79
|
+
remaining -= str.length
|
80
|
+
end
|
81
|
+
ensure
|
82
|
+
release_ownership :r
|
45
83
|
end
|
46
84
|
|
47
85
|
buffer
|
@@ -65,27 +103,24 @@ module Celluloid
|
|
65
103
|
total_written = 0
|
66
104
|
|
67
105
|
remaining = string
|
68
|
-
|
69
|
-
begin
|
70
|
-
written = write_nonblock(remaining)
|
71
|
-
rescue ::IO::WaitWritable
|
72
|
-
wait_writable
|
73
|
-
retry
|
74
|
-
rescue EOFError
|
75
|
-
return total_written
|
76
|
-
end
|
106
|
+
acquire_ownership :w
|
77
107
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
108
|
+
begin
|
109
|
+
while total_written < length
|
110
|
+
begin
|
111
|
+
written = write_nonblock(remaining)
|
112
|
+
rescue ::IO::WaitWritable
|
113
|
+
wait_writable
|
114
|
+
retry
|
115
|
+
rescue EOFError
|
116
|
+
return total_written
|
87
117
|
end
|
118
|
+
|
119
|
+
total_written += written
|
120
|
+
remaining.slice!(0, written) if written < remaining.length
|
88
121
|
end
|
122
|
+
ensure
|
123
|
+
release_ownership :w
|
89
124
|
end
|
90
125
|
|
91
126
|
total_written
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'resolv'
|
2
|
+
|
3
|
+
module Celluloid
|
4
|
+
module IO
|
5
|
+
# Asynchronous DNS resolver using Celluloid::IO::UDPSocket
|
6
|
+
class DNSResolver
|
7
|
+
RESOLV_CONF = '/etc/resolv.conf'
|
8
|
+
HOSTS = '/etc/hosts'
|
9
|
+
DNS_PORT = 53
|
10
|
+
|
11
|
+
@mutex = Mutex.new
|
12
|
+
@identifier = 1
|
13
|
+
|
14
|
+
def self.generate_id
|
15
|
+
@mutex.synchronize { @identifier = (@identifier + 1) & 0xFFFF }
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.nameservers(config = RESOLV_CONF)
|
19
|
+
File.read(config).scan(/^\s*nameserver\s+([0-9.:]+)/).flatten
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.hosts(hostfile = HOSTS)
|
23
|
+
hosts = {}
|
24
|
+
File.open(hostfile) do |f|
|
25
|
+
f.each_line do |host_entry|
|
26
|
+
entries = host_entry.gsub(/#.*$/, '').gsub(/\s+/, ' ').split(' ')
|
27
|
+
addr = entries.shift
|
28
|
+
entries.each { |e| hosts[e] ||= addr }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
hosts
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize
|
35
|
+
@nameservers, @hosts = self.class.nameservers, self.class.hosts
|
36
|
+
|
37
|
+
# TODO: fall back on other nameservers if the first one is unavailable
|
38
|
+
@server = @nameservers.first
|
39
|
+
|
40
|
+
# The non-blocking secret sauce is here, as this is actually a
|
41
|
+
# Celluloid::IO::UDPSocket
|
42
|
+
@socket = UDPSocket.new
|
43
|
+
end
|
44
|
+
|
45
|
+
def resolve(hostname)
|
46
|
+
host = @hosts[hostname]
|
47
|
+
if host
|
48
|
+
begin
|
49
|
+
return Resolv::IPv4.create(host)
|
50
|
+
rescue ArgumentError
|
51
|
+
end
|
52
|
+
|
53
|
+
begin
|
54
|
+
return Resolv::IPv6.create(host)
|
55
|
+
rescue ArgumentError
|
56
|
+
end
|
57
|
+
|
58
|
+
raise Resolv::ResolvError, "invalid entry in hosts file: #{host}"
|
59
|
+
end
|
60
|
+
|
61
|
+
query = Resolv::DNS::Message.new
|
62
|
+
query.id = self.class.generate_id
|
63
|
+
query.rd = 1
|
64
|
+
query.add_question hostname, Resolv::DNS::Resource::IN::A
|
65
|
+
|
66
|
+
@socket.send query.encode, 0, @server, DNS_PORT
|
67
|
+
data, _ = @socket.recvfrom(512)
|
68
|
+
response = Resolv::DNS::Message.decode(data)
|
69
|
+
|
70
|
+
addrs = []
|
71
|
+
response.each_answer { |name, ttl, value| addrs << value.address }
|
72
|
+
|
73
|
+
return if addrs.empty?
|
74
|
+
return addrs.first if addrs.size == 1
|
75
|
+
addrs
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/celluloid/io/mailbox.rb
CHANGED
@@ -15,7 +15,8 @@ module Celluloid
|
|
15
15
|
@mutex.lock
|
16
16
|
begin
|
17
17
|
@messages << message
|
18
|
-
|
18
|
+
current_actor = Thread.current[:actor]
|
19
|
+
@reactor.wakeup unless current_actor && current_actor.mailbox == self
|
19
20
|
rescue IOError
|
20
21
|
raise MailboxError, "dead recipient"
|
21
22
|
ensure @mutex.unlock
|
@@ -28,7 +29,8 @@ module Celluloid
|
|
28
29
|
@mutex.lock
|
29
30
|
begin
|
30
31
|
@messages.unshift event
|
31
|
-
|
32
|
+
current_actor = Thread.current[:actor]
|
33
|
+
@reactor.wakeup unless current_actor && current_actor.mailbox == self
|
32
34
|
rescue IOError
|
33
35
|
# Silently fail if messages are sent to dead actors
|
34
36
|
ensure @mutex.unlock
|
data/lib/celluloid/io/reactor.rb
CHANGED
@@ -21,8 +21,8 @@ module Celluloid
|
|
21
21
|
wait io, :r
|
22
22
|
end
|
23
23
|
|
24
|
-
# Wait for the given IO object to become
|
25
|
-
def
|
24
|
+
# Wait for the given IO object to become writable
|
25
|
+
def wait_writable(io)
|
26
26
|
wait io, :w
|
27
27
|
end
|
28
28
|
|
@@ -48,7 +48,7 @@ module Celluloid
|
|
48
48
|
def run_once(timeout = nil)
|
49
49
|
@selector.select(timeout) do |monitor|
|
50
50
|
task = monitor.value
|
51
|
-
|
51
|
+
monitor.close
|
52
52
|
|
53
53
|
if task.running?
|
54
54
|
task.resume
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'socket'
|
2
|
+
require 'resolv'
|
2
3
|
|
3
4
|
module Celluloid
|
4
5
|
module IO
|
@@ -8,7 +9,7 @@ module Celluloid
|
|
8
9
|
extend Forwardable
|
9
10
|
|
10
11
|
def_delegators :@socket, :read_nonblock, :write_nonblock, :close, :closed?
|
11
|
-
def_delegators :@socket, :addr, :peeraddr
|
12
|
+
def_delegators :@socket, :addr, :peeraddr, :setsockopt
|
12
13
|
|
13
14
|
# Convert a Ruby TCPSocket into a Celluloid::IO::TCPSocket
|
14
15
|
def self.from_ruby_socket(ruby_socket)
|
@@ -22,8 +23,51 @@ module Celluloid
|
|
22
23
|
# and local_port are specified, then those parameters are used on the
|
23
24
|
# local end to establish the connection.
|
24
25
|
def initialize(remote_host, remote_port, local_host = nil, local_port = nil)
|
25
|
-
#
|
26
|
-
|
26
|
+
# Is it an IPv4 address?
|
27
|
+
begin
|
28
|
+
@addr = Resolv::IPv4.create(remote_host)
|
29
|
+
rescue ArgumentError
|
30
|
+
end
|
31
|
+
|
32
|
+
# Guess it's not IPv4! Is it IPv6?
|
33
|
+
unless @addr
|
34
|
+
begin
|
35
|
+
@addr = Resolv::IPv6.create(remote_host)
|
36
|
+
rescue ArgumentError
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Guess it's not an IP address, so let's try DNS
|
41
|
+
unless @addr
|
42
|
+
# TODO: suppport asynchronous DNS
|
43
|
+
# Even EventMachine doesn't do async DNS by default o_O
|
44
|
+
addrs = Array(DNSResolver.new.resolve(remote_host))
|
45
|
+
raise Resolv::ResolvError, "DNS result has no information for #{remote_host}" if addrs.empty?
|
46
|
+
|
47
|
+
# Pseudorandom round-robin DNS support :/
|
48
|
+
@addr = addrs[rand(addrs.size)]
|
49
|
+
end
|
50
|
+
|
51
|
+
case @addr
|
52
|
+
when Resolv::IPv4
|
53
|
+
family = Socket::AF_INET
|
54
|
+
when Resolv::IPv6
|
55
|
+
family = Socket::AF_INET6
|
56
|
+
else raise ArgumentError, "unsupported address class: #{@addr.class}"
|
57
|
+
end
|
58
|
+
|
59
|
+
@socket = Socket.new(family, Socket::SOCK_STREAM, 0)
|
60
|
+
@socket.bind Addrinfo.tcp(local_host, local_port) if local_host
|
61
|
+
|
62
|
+
begin
|
63
|
+
@socket.connect_nonblock Socket.sockaddr_in(remote_port, @addr.to_s)
|
64
|
+
rescue Errno::EINPROGRESS
|
65
|
+
wait_writable
|
66
|
+
retry
|
67
|
+
rescue Errno::EISCONN
|
68
|
+
# We're now connected! Yay exceptions for flow control
|
69
|
+
# NOTE: This is the approach the Ruby stdlib docs suggest ;_;
|
70
|
+
end
|
27
71
|
end
|
28
72
|
|
29
73
|
def to_io
|
data/lib/celluloid/io/version.rb
CHANGED
data/logo.png
CHANGED
Binary file
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
|
3
|
+
desc "Run Celluloid benchmarks"
|
4
|
+
task :benchmark do
|
5
|
+
# Travis has an out-of-date version of rbx that rashes on the benchmarks
|
6
|
+
exit 0 if ENV['CI'] and RUBY_ENGINE == 'rbx'
|
7
|
+
|
8
|
+
begin
|
9
|
+
Timeout.timeout(120) do
|
10
|
+
glob = File.expand_path("../../benchmarks/*.rb", __FILE__)
|
11
|
+
Dir[glob].each { |benchmark| load benchmark }
|
12
|
+
end
|
13
|
+
rescue Exception, Timeout::Error => ex
|
14
|
+
puts "ERROR: Couldn't complete benchmark: #{ex.class}: #{ex}"
|
15
|
+
puts " #{ex.backtrace.join("\n ")}"
|
16
|
+
|
17
|
+
exit 1 unless ENV['CI'] # Hax for running benchmarks on Travis
|
18
|
+
end
|
19
|
+
end
|
data/tasks/rspec.task
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: celluloid-io
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-02
|
12
|
+
date: 2012-04-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: celluloid
|
16
|
-
requirement: &
|
16
|
+
requirement: &70278839545080 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.
|
21
|
+
version: 0.10.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70278839545080
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: nio4r
|
27
|
-
requirement: &
|
27
|
+
requirement: &70278839544320 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 0.3.1
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70278839544320
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rake
|
38
|
-
requirement: &
|
38
|
+
requirement: &70278839543940 !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: *
|
46
|
+
version_requirements: *70278839543940
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rspec
|
49
|
-
requirement: &
|
49
|
+
requirement: &70278839543480 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,7 +54,18 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70278839543480
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: benchmark_suite
|
60
|
+
requirement: &70278839543020 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70278839543020
|
58
69
|
description: Evented IO for Celluloid actors
|
59
70
|
email:
|
60
71
|
- tony.arcieri@gmail.com
|
@@ -70,10 +81,14 @@ files:
|
|
70
81
|
- LICENSE.txt
|
71
82
|
- README.md
|
72
83
|
- Rakefile
|
84
|
+
- benchmarks/actor.rb
|
85
|
+
- benchmarks/ring.rb
|
73
86
|
- celluloid-io.gemspec
|
87
|
+
- examples/echo_client.rb
|
74
88
|
- examples/echo_server.rb
|
75
89
|
- lib/celluloid/io.rb
|
76
90
|
- lib/celluloid/io/common_methods.rb
|
91
|
+
- lib/celluloid/io/dns_resolver.rb
|
77
92
|
- lib/celluloid/io/mailbox.rb
|
78
93
|
- lib/celluloid/io/reactor.rb
|
79
94
|
- lib/celluloid/io/tcp_server.rb
|
@@ -82,12 +97,15 @@ files:
|
|
82
97
|
- lib/celluloid/io/version.rb
|
83
98
|
- logo.png
|
84
99
|
- spec/celluloid/io/actor_spec.rb
|
100
|
+
- spec/celluloid/io/dns_resolver_spec.rb
|
85
101
|
- spec/celluloid/io/mailbox_spec.rb
|
86
102
|
- spec/celluloid/io/tcp_server_spec.rb
|
87
103
|
- spec/celluloid/io/tcp_socket_spec.rb
|
88
104
|
- spec/celluloid/io/udp_socket_spec.rb
|
89
105
|
- spec/spec_helper.rb
|
90
|
-
|
106
|
+
- tasks/benchmarks.task
|
107
|
+
- tasks/rspec.task
|
108
|
+
homepage: http://github.com/celluloid/celluloid-io
|
91
109
|
licenses: []
|
92
110
|
post_install_message:
|
93
111
|
rdoc_options: []
|
@@ -107,16 +125,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
125
|
version: '0'
|
108
126
|
requirements: []
|
109
127
|
rubyforge_project:
|
110
|
-
rubygems_version: 1.8.
|
128
|
+
rubygems_version: 1.8.17
|
111
129
|
signing_key:
|
112
130
|
specification_version: 3
|
113
131
|
summary: Celluloid::IO allows you to monitor multiple IO objects within a Celluloid
|
114
132
|
actor
|
115
133
|
test_files:
|
116
134
|
- spec/celluloid/io/actor_spec.rb
|
135
|
+
- spec/celluloid/io/dns_resolver_spec.rb
|
117
136
|
- spec/celluloid/io/mailbox_spec.rb
|
118
137
|
- spec/celluloid/io/tcp_server_spec.rb
|
119
138
|
- spec/celluloid/io/tcp_socket_spec.rb
|
120
139
|
- spec/celluloid/io/udp_socket_spec.rb
|
121
140
|
- spec/spec_helper.rb
|
122
|
-
has_rdoc:
|