celluloid-io 0.9.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
![Celluloid](https://github.com/
|
1
|
+
![Celluloid](https://github.com/celluloid/celluloid-io/raw/master/logo.png)
|
2
2
|
=============
|
3
|
-
[![Build Status](https://secure.travis-ci.org/
|
4
|
-
[![Dependency Status](https://gemnasium.com/
|
3
|
+
[![Build Status](https://secure.travis-ci.org/celluloid/celluloid-io.png?branch=master)](http://travis-ci.org/celluloid/celluloid-io)
|
4
|
+
[![Dependency Status](https://gemnasium.com/celluloid/celluloid-io.png)](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:
|