celluloid 0.16.0.pre → 0.16.0.pre2
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.
- checksums.yaml +4 -4
- data/README.md +0 -4
- data/lib/celluloid.rb +1 -1
- data/lib/celluloid/actor.rb +19 -12
- data/lib/celluloid/call_chain.rb +1 -1
- data/lib/celluloid/cpu_counter.rb +27 -20
- data/lib/celluloid/evented_mailbox.rb +8 -16
- data/lib/celluloid/pool_manager.rb +18 -1
- data/lib/celluloid/receivers.rb +2 -1
- data/lib/celluloid/tasks/task_fiber.rb +1 -1
- data/spec/celluloid/cpu_counter_spec.rb +75 -2
- data/spec/celluloid/pool_spec.rb +33 -0
- data/spec/celluloid/stack_dump_spec.rb +4 -4
- metadata +19 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9c58eede0a8ebeb315bf6f2fa925e19173dd5e9
|
4
|
+
data.tar.gz: 525f0ae4823a55ca1e23bf1ff5b6c8493592551f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2ac75588d4accd17305ea04b6329563783db6972262584898e3143bdf6086ba47dc8bcf8c93ad6c7a8b44115c2c718fbcc615219da968ffdfa8a7a5f17b5f908
|
7
|
+
data.tar.gz: e1185014388060dcd75a41b583a6df01f7bcbb37e21e1619091e364374cb861a31df7c7110b371887540c2482ff54cfae0cf7a3df534fc188157e220d5f8cd12
|
data/README.md
CHANGED
@@ -170,7 +170,3 @@ License
|
|
170
170
|
|
171
171
|
Copyright (c) 2011-2014 Tony Arcieri. Distributed under the MIT License. See
|
172
172
|
LICENSE.txt for further details.
|
173
|
-
|
174
|
-
|
175
|
-
[](https://bitdeli.com/free "Bitdeli Badge")
|
176
|
-
|
data/lib/celluloid.rb
CHANGED
data/lib/celluloid/actor.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
require 'timers'
|
2
3
|
|
3
4
|
module Celluloid
|
@@ -112,7 +113,7 @@ module Celluloid
|
|
112
113
|
@links = Links.new
|
113
114
|
@signals = Signals.new
|
114
115
|
@receivers = Receivers.new
|
115
|
-
@timers = Timers.new
|
116
|
+
@timers = Timers::Group.new
|
116
117
|
@handlers = Handlers.new
|
117
118
|
@running = false
|
118
119
|
@name = nil
|
@@ -170,31 +171,37 @@ module Celluloid
|
|
170
171
|
# Perform a linking request with another actor
|
171
172
|
def linking_request(receiver, type)
|
172
173
|
Celluloid.exclusive do
|
173
|
-
|
174
|
+
linking_timeout = Timers::Timeout.new(LINKING_TIMEOUT)
|
175
|
+
|
174
176
|
receiver.mailbox << LinkingRequest.new(Actor.current, type)
|
175
177
|
system_events = []
|
176
178
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
179
|
+
linking_timeout.while_time_remaining do |remaining|
|
180
|
+
begin
|
181
|
+
message = @mailbox.receive(remaining) do |msg|
|
182
|
+
msg.is_a?(LinkingResponse) &&
|
183
|
+
msg.actor.mailbox.address == receiver.mailbox.address &&
|
184
|
+
msg.type == type
|
185
|
+
end
|
186
|
+
rescue TimeoutError
|
187
|
+
next # IO reactor did something, no message in queue yet.
|
183
188
|
end
|
184
189
|
|
185
190
|
if message.instance_of? LinkingResponse
|
186
191
|
Celluloid::Probe.actors_linked(self, receiver) if $CELLULOID_MONITORING
|
192
|
+
|
187
193
|
# We're done!
|
188
194
|
system_events.each { |ev| @mailbox << ev }
|
195
|
+
|
189
196
|
return
|
190
|
-
elsif message.
|
191
|
-
raise TimeoutError, "linking timeout of #{LINKING_TIMEOUT} seconds exceeded"
|
192
|
-
elsif message.instance_of? SystemEvent
|
197
|
+
elsif message.is_a? SystemEvent
|
193
198
|
# Queue up pending system events to be processed after we've successfully linked
|
194
199
|
system_events << message
|
195
|
-
else raise
|
200
|
+
else raise "Unexpected message type: #{message.class}. Expected LinkingResponse, NilClass, SystemEvent."
|
196
201
|
end
|
197
202
|
end
|
203
|
+
|
204
|
+
raise TimeoutError, "linking timeout of #{LINKING_TIMEOUT} seconds exceeded"
|
198
205
|
end
|
199
206
|
end
|
200
207
|
|
data/lib/celluloid/call_chain.rb
CHANGED
@@ -1,26 +1,33 @@
|
|
1
|
-
require 'rbconfig'
|
2
|
-
|
3
1
|
module Celluloid
|
4
2
|
module CPUCounter
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
when 'linux'
|
9
|
-
@cores = if File.exists?("/sys/devices/system/cpu/present")
|
10
|
-
File.read("/sys/devices/system/cpu/present").split('-').last.to_i+1
|
11
|
-
else
|
12
|
-
Dir["/sys/devices/system/cpu/cpu*"].select { |n| n=~/cpu\d+/ }.count
|
3
|
+
class << self
|
4
|
+
def cores
|
5
|
+
@cores ||= count_cores
|
13
6
|
end
|
14
|
-
when 'mingw', 'mswin'
|
15
|
-
@cores = Integer(ENV["NUMBER_OF_PROCESSORS"][/\d+/])
|
16
|
-
when 'freebsd'
|
17
|
-
@cores = Integer(`sysctl hw.ncpu`[/\d+/])
|
18
|
-
else
|
19
|
-
@cores = nil
|
20
|
-
end
|
21
7
|
|
22
|
-
|
23
|
-
end
|
24
|
-
end
|
8
|
+
private
|
25
9
|
|
10
|
+
def count_cores
|
11
|
+
result = from_env || from_sysdev || from_sysctl
|
12
|
+
Integer(result.to_s[/\d+/], 10) if result
|
13
|
+
end
|
14
|
+
|
15
|
+
def from_env
|
16
|
+
result = ENV['NUMBER_OF_PROCESSORS']
|
17
|
+
result if result
|
18
|
+
end
|
26
19
|
|
20
|
+
def from_sysdev
|
21
|
+
::IO.read('/sys/devices/system/cpu/present').split('-').last.to_i + 1
|
22
|
+
rescue Errno::ENOENT
|
23
|
+
result = Dir['/sys/devices/system/cpu/cpu*'].count { |n| n =~ /cpu\d+/ }
|
24
|
+
result unless result.zero?
|
25
|
+
end
|
26
|
+
|
27
|
+
def from_sysctl
|
28
|
+
result = `sysctl -n hw.ncpu`
|
29
|
+
result if $?.success?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -38,24 +38,16 @@ module Celluloid
|
|
38
38
|
|
39
39
|
# Receive a message from the Mailbox
|
40
40
|
def receive(timeout = nil, &block)
|
41
|
-
message
|
42
|
-
|
43
|
-
|
44
|
-
if timeout
|
45
|
-
# TODO: use hitimes/timers instead of Time.now
|
46
|
-
now = Time.now
|
47
|
-
wait_until ||= now + timeout
|
48
|
-
wait_interval = wait_until - now
|
49
|
-
raise(TimeoutError, "mailbox timeout exceeded", nil) if wait_interval <= 0
|
50
|
-
else
|
51
|
-
wait_interval = nil
|
52
|
-
end
|
53
|
-
|
54
|
-
@reactor.run_once(wait_interval)
|
55
|
-
message = next_message(block)
|
41
|
+
# Get a message if it is available and process it immediately if possible:
|
42
|
+
if message = next_message(block)
|
43
|
+
return message
|
56
44
|
end
|
57
45
|
|
58
|
-
|
46
|
+
# ... otherwise, run the reactor once, either blocking or will return after the given timeout.
|
47
|
+
@reactor.run_once(timeout)
|
48
|
+
|
49
|
+
# This is a hack to get the main Actor#run loop to recompute the timeout:
|
50
|
+
raise TimeoutError
|
59
51
|
rescue IOError
|
60
52
|
raise MailboxShutdown, "mailbox shutdown called during receive"
|
61
53
|
end
|
@@ -24,7 +24,7 @@ module Celluloid
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def __shutdown__
|
27
|
-
terminators = (@idle + @busy).
|
27
|
+
terminators = (@idle + @busy).map do |actor|
|
28
28
|
begin
|
29
29
|
actor.future(:terminate)
|
30
30
|
rescue DeadActorError
|
@@ -81,6 +81,23 @@ module Celluloid
|
|
81
81
|
@size
|
82
82
|
end
|
83
83
|
|
84
|
+
def size=(new_size)
|
85
|
+
new_size = [0, new_size].max
|
86
|
+
|
87
|
+
if new_size > size
|
88
|
+
delta = new_size - size
|
89
|
+
delta.times { @idle << @worker_class.new_link(*@args) }
|
90
|
+
else
|
91
|
+
(size - new_size).times do
|
92
|
+
worker = __provision_worker__
|
93
|
+
unlink worker
|
94
|
+
@busy.delete worker
|
95
|
+
worker.terminate
|
96
|
+
end
|
97
|
+
end
|
98
|
+
@size = new_size
|
99
|
+
end
|
100
|
+
|
84
101
|
def busy_size
|
85
102
|
@busy.length
|
86
103
|
end
|
data/lib/celluloid/receivers.rb
CHANGED
@@ -37,7 +37,7 @@ module Celluloid
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def backtrace
|
40
|
-
"#{self.class} backtrace unavailable. Please try `Celluloid.task_class = Celluloid::TaskThread` if you need backtraces here."
|
40
|
+
["#{self.class} backtrace unavailable. Please try `Celluloid.task_class = Celluloid::TaskThread` if you need backtraces here."]
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -2,8 +2,81 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Celluloid::CPUCounter do
|
4
4
|
describe :cores do
|
5
|
-
|
6
|
-
|
5
|
+
subject { described_class.cores }
|
6
|
+
|
7
|
+
let(:num_cores) { 1024 }
|
8
|
+
|
9
|
+
before do
|
10
|
+
described_class.stub(:`) { fail 'backtick stub called' }
|
11
|
+
::IO.stub(:open).and_raise('IO.open stub called!')
|
12
|
+
described_class.instance_variable_set('@cores', nil)
|
13
|
+
end
|
14
|
+
|
15
|
+
after { ENV['NUMBER_OF_PROCESSORS'] = nil }
|
16
|
+
|
17
|
+
context 'from valid env value' do
|
18
|
+
before { ENV['NUMBER_OF_PROCESSORS'] = num_cores.to_s }
|
19
|
+
it { should eq num_cores }
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'from invalid env value' do
|
23
|
+
before { ENV['NUMBER_OF_PROCESSORS'] = '' }
|
24
|
+
specify { expect { subject }.to raise_error(ArgumentError) }
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'with no env value' do
|
28
|
+
before { ENV['NUMBER_OF_PROCESSORS'] = nil }
|
29
|
+
|
30
|
+
context 'when /sys/devices/system/cpu/present exists' do
|
31
|
+
before do
|
32
|
+
::IO.should_receive(:read).with('/sys/devices/system/cpu/present')
|
33
|
+
.and_return("dunno-whatever-#{num_cores - 1}")
|
34
|
+
end
|
35
|
+
it { should eq num_cores }
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when /sys/devices/system/cpu/present does NOT exist' do
|
39
|
+
before do
|
40
|
+
::IO.should_receive(:read).with('/sys/devices/system/cpu/present')
|
41
|
+
.and_raise(Errno::ENOENT)
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when /sys/devices/system/cpu/cpu* files exist' do
|
45
|
+
before do
|
46
|
+
cpu_entries = (1..num_cores).map { |n| "cpu#{n}" }
|
47
|
+
cpu_entries << 'non-cpu-entry-to-ignore'
|
48
|
+
Dir.should_receive(:[]).with('/sys/devices/system/cpu/cpu*')
|
49
|
+
.and_return(cpu_entries)
|
50
|
+
end
|
51
|
+
it { should eq num_cores }
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'when /sys/devices/system/cpu/cpu* files DO NOT exist' do
|
55
|
+
before do
|
56
|
+
Dir.should_receive(:[]).with('/sys/devices/system/cpu/cpu*')
|
57
|
+
.and_return([])
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when sysctl blows up' do
|
61
|
+
before { described_class.stub(:`).and_raise(Errno::EINTR) }
|
62
|
+
specify { expect { subject }.to raise_error }
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'when sysctl fails' do
|
66
|
+
before { described_class.stub(:`).and_return(`false`) }
|
67
|
+
it { should be nil }
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'when sysctl succeeds' do
|
71
|
+
before do
|
72
|
+
described_class.should_receive(:`).with('sysctl -n hw.ncpu')
|
73
|
+
.and_return(num_cores.to_s)
|
74
|
+
`true`
|
75
|
+
end
|
76
|
+
it { should eq num_cores }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
7
80
|
end
|
8
81
|
end
|
9
82
|
end
|
data/spec/celluloid/pool_spec.rb
CHANGED
@@ -14,11 +14,23 @@ describe "Celluloid.pool", actor_system: :global do
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
def sleepy_work
|
18
|
+
t = Time.now.to_f
|
19
|
+
sleep 0.25
|
20
|
+
t
|
21
|
+
end
|
22
|
+
|
17
23
|
def crash
|
18
24
|
raise ExampleError, "zomgcrash"
|
19
25
|
end
|
20
26
|
end
|
21
27
|
|
28
|
+
def test_concurrency_of(pool)
|
29
|
+
baseline = Time.now.to_f
|
30
|
+
values = 10.times.map { pool.future.sleepy_work }.map(&:value)
|
31
|
+
values.select {|t| t - baseline < 0.1 }.length
|
32
|
+
end
|
33
|
+
|
22
34
|
subject { MyWorker.pool }
|
23
35
|
|
24
36
|
it "processes work units synchronously" do
|
@@ -56,4 +68,25 @@ describe "Celluloid.pool", actor_system: :global do
|
|
56
68
|
end
|
57
69
|
futures.map(&:value)
|
58
70
|
end
|
71
|
+
|
72
|
+
context "#size=" do
|
73
|
+
subject { MyWorker.pool size: 4 }
|
74
|
+
|
75
|
+
it "should adjust the pool size up", pending: 'flaky' do
|
76
|
+
expect(test_concurrency_of(subject)).to eq(4)
|
77
|
+
|
78
|
+
subject.size = 6
|
79
|
+
subject.size.should == 6
|
80
|
+
|
81
|
+
test_concurrency_of(subject).should == 6
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should adjust the pool size down" do
|
85
|
+
test_concurrency_of(subject).should == 4
|
86
|
+
|
87
|
+
subject.size = 2
|
88
|
+
subject.size.should == 2
|
89
|
+
test_concurrency_of(subject).should == 2
|
90
|
+
end
|
91
|
+
end
|
59
92
|
end
|
@@ -45,8 +45,8 @@ describe Celluloid::StackDump do
|
|
45
45
|
end
|
46
46
|
|
47
47
|
describe '#threads' do
|
48
|
-
it 'should include threads that are not actors' do
|
49
|
-
subject.threads.size.
|
48
|
+
it 'should include threads that are not actors', pending: 'flaky' do
|
49
|
+
expect(subject.threads.size).to eq(3)
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'should include idle threads' do
|
@@ -57,8 +57,8 @@ describe Celluloid::StackDump do
|
|
57
57
|
subject.threads.map(&:thread_id).should include(@active_thread.object_id)
|
58
58
|
end
|
59
59
|
|
60
|
-
it 'should have the correct roles' do
|
61
|
-
subject.threads.map(&:role).
|
60
|
+
it 'should have the correct roles', pending: 'flaky' do
|
61
|
+
expect(subject.threads.map(&:role)).to include(nil, :other_thing, :task)
|
62
62
|
end
|
63
63
|
end
|
64
64
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: celluloid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.16.0.
|
4
|
+
version: 0.16.0.pre2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Arcieri
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: timers
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 3.0.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 3.0.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
description: Celluloid enables people to build concurrent programs out of concurrent
|
84
98
|
objects just as easily as they build sequential programs out of sequential objects
|
85
99
|
email:
|
@@ -196,7 +210,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
196
210
|
version: 1.3.6
|
197
211
|
requirements: []
|
198
212
|
rubyforge_project:
|
199
|
-
rubygems_version: 2.2.
|
213
|
+
rubygems_version: 2.2.2
|
200
214
|
signing_key:
|
201
215
|
specification_version: 4
|
202
216
|
summary: Actor-based concurrent object framework for Ruby
|