celluloid 0.16.0.pre → 0.16.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3f9e4bf5d8e26e99c5321bc02c61cafa9de48600
4
- data.tar.gz: b239f25215d8c3ca0c9c27cd3e08954fa62ee35c
3
+ metadata.gz: 6b9e9584ba72b44bbb2ce23372b0b4b86f2f3687
4
+ data.tar.gz: 10ec35b6465a1025defe4a697c3108f1982b5f77
5
5
  SHA512:
6
- metadata.gz: be0d373d83500400c1135176382097f8bdffeb378fbce48f95852195975984a626221292ade6182ba84cc5a9ca06fa0849461d28c68e9adea33c129396ab39a3
7
- data.tar.gz: 6f6cd39aec05a5b8f4b461ad88cd6c960a37d5832ca36ee5f633bf0e3229b294fb714668dcf87d843e162749507c301d14d32d2ae2d344c726b3f55346f9e6c8
6
+ metadata.gz: 9394c33b6d7eff1efa0e0f78d24ff5578ce208dac695d0b7b806c999b47a456253c670783599ae448cb9bb3f6bf455be4ac66705fb399d8e53c3adb72a894250
7
+ data.tar.gz: f3e2659328cb38517ec107ad32e7c08d8aaa40fece3d74213273d50f703a6cb0878a43616d933b41fb6d061d928f02ba68850d269be32107062bc5e7b162bcc2
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
- [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/celluloid/celluloid/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
176
-
@@ -1,3 +1,4 @@
1
+
1
2
  require 'timers'
2
3
 
3
4
  module Celluloid
@@ -111,8 +112,8 @@ module Celluloid
111
112
  @tasks = TaskSet.new
112
113
  @links = Links.new
113
114
  @signals = Signals.new
114
- @receivers = Receivers.new
115
- @timers = Timers.new
115
+ @timers = Timers::Group.new
116
+ @receivers = Receivers.new(@timers)
116
117
  @handlers = Handlers.new
117
118
  @running = false
118
119
  @name = nil
@@ -146,11 +147,15 @@ module Celluloid
146
147
  def run
147
148
  while @running
148
149
  begin
149
- message = @mailbox.receive(timeout_interval)
150
- handle_message message
151
- rescue TimeoutError
152
- @timers.fire
153
- @receivers.fire_timers
150
+ @timers.wait do |interval|
151
+ interval = 0 if interval and interval < 0
152
+
153
+ if message = @mailbox.check(interval)
154
+ handle_message(message)
155
+
156
+ break unless @running
157
+ end
158
+ end
154
159
  rescue MailboxShutdown
155
160
  @running = false
156
161
  end
@@ -170,31 +175,35 @@ module Celluloid
170
175
  # Perform a linking request with another actor
171
176
  def linking_request(receiver, type)
172
177
  Celluloid.exclusive do
173
- start_time = Time.now
174
178
  receiver.mailbox << LinkingRequest.new(Actor.current, type)
175
179
  system_events = []
176
180
 
177
- loop do
178
- wait_interval = start_time + LINKING_TIMEOUT - Time.now
179
- message = @mailbox.receive(wait_interval) do |msg|
180
- msg.is_a?(LinkingResponse) &&
181
- msg.actor.mailbox.address == receiver.mailbox.address &&
182
- msg.type == type
181
+ Timers::Wait.for(LINKING_TIMEOUT) do |remaining|
182
+ begin
183
+ message = @mailbox.receive(remaining) do |msg|
184
+ msg.is_a?(LinkingResponse) &&
185
+ msg.actor.mailbox.address == receiver.mailbox.address &&
186
+ msg.type == type
187
+ end
188
+ rescue TimeoutError
189
+ next # IO reactor did something, no message in queue yet.
183
190
  end
184
191
 
185
192
  if message.instance_of? LinkingResponse
186
193
  Celluloid::Probe.actors_linked(self, receiver) if $CELLULOID_MONITORING
194
+
187
195
  # We're done!
188
196
  system_events.each { |ev| @mailbox << ev }
197
+
189
198
  return
190
- elsif message.instance_of? NilClass
191
- raise TimeoutError, "linking timeout of #{LINKING_TIMEOUT} seconds exceeded"
192
- elsif message.instance_of? SystemEvent
199
+ elsif message.is_a? SystemEvent
193
200
  # Queue up pending system events to be processed after we've successfully linked
194
201
  system_events << message
195
- else raise 'wtf'
202
+ else raise "Unexpected message type: #{message.class}. Expected LinkingResponse, NilClass, SystemEvent."
196
203
  end
197
204
  end
205
+
206
+ raise TimeoutError, "linking timeout of #{LINKING_TIMEOUT} seconds exceeded"
198
207
  end
199
208
  end
200
209
 
@@ -222,20 +231,6 @@ module Celluloid
222
231
  end
223
232
  end
224
233
 
225
- # How long to wait until the next timer fires
226
- def timeout_interval
227
- i1 = @timers.wait_interval
228
- i2 = @receivers.wait_interval
229
-
230
- if i1 and i2
231
- i1 < i2 ? i1 : i2
232
- elsif i1
233
- i1
234
- else
235
- i2
236
- end
237
- end
238
-
239
234
  # Schedule a block to run at the given time
240
235
  def after(interval, &block)
241
236
  @timers.after(interval) { task(:timer, &block) }
@@ -10,4 +10,4 @@ module Celluloid
10
10
  Thread.current[:celluloid_chain_id]
11
11
  end
12
12
  end
13
- end
13
+ end
@@ -1,26 +1,34 @@
1
- require 'rbconfig'
2
-
3
1
  module Celluloid
4
2
  module CPUCounter
5
- case RbConfig::CONFIG['host_os'][/^[A-Za-z]+/]
6
- when 'darwin'
7
- @cores = Integer(`/usr/sbin/sysctl hw.ncpu`[/\d+/])
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
- def self.cores; @cores; end
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
+ rescue Errno::ENOENT
31
+ end
32
+ end
33
+ end
34
+ end
@@ -37,25 +37,18 @@ module Celluloid
37
37
  end
38
38
 
39
39
  # Receive a message from the Mailbox
40
- def receive(timeout = nil, &block)
41
- message = next_message(block)
42
-
43
- until message
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)
40
+ def check(timeout = nil, &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
- message
46
+ # ... otherwise, run the reactor once, either blocking or will return
47
+ # after the given timeout:
48
+ @reactor.run_once(timeout)
49
+
50
+ # No message was received:
51
+ return nil
59
52
  rescue IOError
60
53
  raise MailboxShutdown, "mailbox shutdown called during receive"
61
54
  end
@@ -7,7 +7,10 @@ module Celluloid
7
7
 
8
8
  def initialize
9
9
  @mutex = Mutex.new
10
- @threads = []
10
+ @idle_threads = []
11
+ @all_threads = []
12
+ @busy_size = 0
13
+ @idle_size = 0
11
14
 
12
15
  # TODO: should really adjust this based on usage
13
16
  @max_idle = 16
@@ -15,17 +18,15 @@ module Celluloid
15
18
  end
16
19
 
17
20
  def busy_size
18
- @threads.select(&:busy).size
21
+ @busy_size
19
22
  end
20
23
 
21
24
  def idle_size
22
- @threads.reject(&:busy).size
25
+ @idle_size
23
26
  end
24
27
 
25
28
  def assert_running
26
- unless running?
27
- raise Error, "Thread pool is not running"
28
- end
29
+ raise Error, "Thread pool is not running" unless running?
29
30
  end
30
31
 
31
32
  def assert_inactive
@@ -44,17 +45,15 @@ module Celluloid
44
45
  end
45
46
 
46
47
  def active?
47
- to_a.any?
48
+ busy_size + idle_size > 0
48
49
  end
49
50
 
50
51
  def each
51
- @threads.each do |thread|
52
- yield thread
53
- end
52
+ to_a.each {|thread| yield thread }
54
53
  end
55
54
 
56
55
  def to_a
57
- @threads
56
+ @mutex.synchronize { @all_threads.dup }
58
57
  end
59
58
 
60
59
  # Get a thread from the pool, running the given block
@@ -63,15 +62,16 @@ module Celluloid
63
62
  assert_running
64
63
 
65
64
  begin
66
- idle = @threads.reject(&:busy)
67
- if idle.empty?
65
+ if @idle_threads.empty?
68
66
  thread = create
69
67
  else
70
- thread = idle.first
68
+ thread = @idle_threads.pop
69
+ @idle_size = @idle_threads.length
71
70
  end
72
71
  end until thread.status # handle crashed threads
73
72
 
74
73
  thread.busy = true
74
+ @busy_size += 1
75
75
  thread[:celluloid_queue] << block
76
76
  thread
77
77
  end
@@ -81,15 +81,46 @@ module Celluloid
81
81
  def put(thread)
82
82
  @mutex.synchronize do
83
83
  thread.busy = false
84
- if idle_size >= @max_idle
84
+ if idle_size + 1 >= @max_idle
85
85
  thread[:celluloid_queue] << nil
86
- @threads.delete(thread)
86
+ @busy_size -= 1
87
+ @all_threads.delete(thread)
87
88
  else
89
+ @idle_threads.push thread
90
+ @busy_size -= 1
91
+ @idle_size = @idle_threads.length
88
92
  clean_thread_locals(thread)
89
93
  end
90
94
  end
91
95
  end
92
96
 
97
+ def shutdown
98
+ @mutex.synchronize do
99
+ finalize
100
+ @all_threads.each do |thread|
101
+ thread[:celluloid_queue] << nil
102
+ end
103
+ @all_threads.clear
104
+ @idle_threads.clear
105
+ @busy_size = 0
106
+ @idle_size = 0
107
+ end
108
+ end
109
+
110
+ def kill
111
+ @mutex.synchronize do
112
+ finalize
113
+ @running = false
114
+
115
+ @all_threads.shift.kill until @all_threads.empty?
116
+ @idle_threads.clear
117
+ @busy_size = 0
118
+ @idle_size = 0
119
+ end
120
+ end
121
+
122
+ private
123
+
93
124
  # Create a new thread with an associated queue of procs to run
94
125
  def create
95
126
  queue = Queue.new
@@ -106,7 +137,8 @@ module Celluloid
106
137
  end
107
138
 
108
139
  thread[:celluloid_queue] = queue
109
- @threads << thread
140
+ # @idle_threads << thread
141
+ @all_threads << thread
110
142
  thread
111
143
  end
112
144
 
@@ -120,26 +152,6 @@ module Celluloid
120
152
  end
121
153
  end
122
154
 
123
- def shutdown
124
- @mutex.synchronize do
125
- finalize
126
- @threads.each do |thread|
127
- thread[:celluloid_queue] << nil
128
- end
129
- end
130
- end
131
-
132
- def kill
133
- @mutex.synchronize do
134
- finalize
135
- @running = false
136
-
137
- @threads.shift.kill until @threads.empty?
138
- end
139
- end
140
-
141
- private
142
-
143
155
  def finalize
144
156
  @max_idle = 0
145
157
  end
@@ -45,36 +45,39 @@ module Celluloid
45
45
  end
46
46
  end
47
47
 
48
- # Receive a message from the Mailbox
49
- def receive(timeout = nil, &block)
48
+ # Receive a message from the Mailbox. May return nil and may return before
49
+ # the specified timeout.
50
+ def check(timeout = nil, &block)
50
51
  message = nil
51
52
 
52
53
  @mutex.lock
53
54
  begin
54
55
  raise MailboxDead, "attempted to receive from a dead mailbox" if @dead
55
56
 
56
- begin
57
+ Timers::Wait.for(timeout) do |remaining|
57
58
  message = next_message(&block)
58
59
 
59
- unless message
60
- if timeout
61
- # TODO: use hitimes/timers instead of Time.now
62
- now = Time.now
63
- wait_until ||= now + timeout
64
- wait_interval = wait_until - now
65
- raise(TimeoutError, "mailbox timeout exceeded", nil) if wait_interval <= 0
66
- else
67
- wait_interval = nil
68
- end
69
-
70
- @condition.wait(@mutex, wait_interval)
71
- end
72
- end until message
73
-
74
- message
60
+ break message if message
61
+
62
+ @condition.wait(@mutex, remaining)
63
+ end
75
64
  ensure
76
65
  @mutex.unlock rescue nil
77
66
  end
67
+
68
+ return message
69
+ end
70
+
71
+ # Receive a letter from the mailbox. Guaranteed to return a message. If
72
+ # timeout is exceeded, raise a TimeoutError.
73
+ def receive(timeout = nil, &block)
74
+ Timers::Wait.for(timeout) do |remaining|
75
+ if message = check(timeout, &block)
76
+ return message
77
+ end
78
+ end
79
+
80
+ raise TimeoutError.new("receive timeout exceeded")
78
81
  end
79
82
 
80
83
  # Shut down this mailbox and clean up its contents
@@ -24,7 +24,7 @@ module Celluloid
24
24
  end
25
25
 
26
26
  def __shutdown__
27
- terminators = (@idle + @busy).each do |actor|
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
@@ -1,12 +1,13 @@
1
1
  require 'set'
2
+
2
3
  require 'timers'
3
4
 
4
5
  module Celluloid
5
6
  # Allow methods to directly interact with the actor protocol
6
7
  class Receivers
7
- def initialize
8
+ def initialize(timers)
8
9
  @receivers = Set.new
9
- @timers = Timers.new
10
+ @timers = timers
10
11
  end
11
12
 
12
13
  # Receive an asynchronous message
@@ -28,23 +29,13 @@ module Celluloid
28
29
  end
29
30
  end
30
31
 
31
- # How long to wait until the next timer fires
32
- def wait_interval
33
- @timers.wait_interval
34
- end
35
-
36
- # Fire any pending timers
37
- def fire_timers
38
- @timers.fire
39
- end
40
-
41
32
  # Handle incoming messages
42
33
  def handle_message(message)
43
34
  receiver = @receivers.find { |r| r.match(message) }
44
35
  return unless receiver
45
36
 
46
37
  @receivers.delete receiver
47
- @timers.cancel receiver.timer if receiver.timer
38
+ receiver.timer.cancel if receiver.timer
48
39
  receiver.resume message
49
40
  message
50
41
  end
@@ -285,6 +285,31 @@ shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
285
285
  actor.send('foo').should eq('oof')
286
286
  end
287
287
 
288
+ context "when executing under JRuby" do
289
+ let(:klass) {
290
+ Class.new do
291
+ include included_module
292
+ task_class task_klass
293
+
294
+ def current_thread_name
295
+ java_thread.get_name
296
+ end
297
+
298
+ def java_thread
299
+ Thread.current.to_java.getNativeThread
300
+ end
301
+ end
302
+ }
303
+
304
+ it "sets execution info" do
305
+ klass.new.current_thread_name.should == "Class#current_thread_name"
306
+ end
307
+
308
+ it "unsets execution info after task completion" do
309
+ klass.new.java_thread.get_name.should == "<unused>"
310
+ end
311
+ end if RUBY_PLATFORM == "java"
312
+
288
313
  context "mocking methods" do
289
314
  let(:actor) { actor_class.new "Troy McClure" }
290
315
 
@@ -1,6 +1,7 @@
1
- require File.expand_path('../../../spec/support/example_actor_class', __FILE__)
2
- require File.expand_path('../../../spec/support/actor_examples', __FILE__)
3
- require File.expand_path('../../../spec/support/mailbox_examples', __FILE__)
1
+ require 'celluloid/rspec/example_actor_class'
2
+ require 'celluloid/rspec/actor_examples'
3
+ require 'celluloid/rspec/mailbox_examples'
4
+ require 'celluloid/rspec/task_examples'
4
5
 
5
6
  module Celluloid
6
7
  # Timer accuracy enforced by the tests (50ms)
@@ -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
@@ -48,6 +48,8 @@ module Celluloid
48
48
  @status = :running
49
49
  actor.setup_thread
50
50
 
51
+ name_current_thread thread_metadata
52
+
51
53
  Thread.current[:celluloid_task] = self
52
54
  CallChain.current_id = @chain_id
53
55
 
@@ -56,6 +58,7 @@ module Celluloid
56
58
  rescue Task::TerminatedError
57
59
  # Task was explicitly terminated
58
60
  ensure
61
+ name_current_thread nil
59
62
  @status = :dead
60
63
  actor.tasks.delete self
61
64
  end
@@ -147,6 +150,25 @@ module Celluloid
147
150
  raise message if $CELLULOID_DEBUG
148
151
  end
149
152
  end
153
+
154
+ private
155
+
156
+ def name_current_thread(new_name)
157
+ return unless RUBY_PLATFORM == "java"
158
+ if new_name.nil?
159
+ new_name = Thread.current[:celluloid_original_thread_name]
160
+ Thread.current[:celluloid_original_thread_name] = nil
161
+ else
162
+ Thread.current[:celluloid_original_thread_name] = Thread.current.to_java.getNativeThread.get_name
163
+ end
164
+ Thread.current.to_java.getNativeThread.set_name(new_name)
165
+ end
166
+
167
+ def thread_metadata
168
+ method = @meta && @meta[:method_name] || "<no method>"
169
+ klass = Thread.current[:celluloid_actor] && Thread.current[:celluloid_actor].behavior.subject.bare_object.class || "<no actor>"
170
+ format("[Celluloid] %s#%s", klass, method)
171
+ end
150
172
  end
151
173
  end
152
174
 
data/lib/celluloid.rb CHANGED
@@ -7,7 +7,7 @@ module Celluloid
7
7
  # Expose all instance methods as singleton methods
8
8
  extend self
9
9
 
10
- VERSION = '0.16.0.pre'
10
+ VERSION = '0.16.0'
11
11
 
12
12
  # Linking times out after 5 seconds
13
13
  LINKING_TIMEOUT = 5
@@ -2,8 +2,81 @@ require 'spec_helper'
2
2
 
3
3
  describe Celluloid::CPUCounter do
4
4
  describe :cores do
5
- it 'should return an integer' do
6
- Celluloid::CPUCounter.cores.should be_kind_of(Fixnum)
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
@@ -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.should == 3
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).should include(nil, :other_thing, :task)
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
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ class EveryActor
4
+ include Celluloid
5
+
6
+ def initialize
7
+ @trace = []
8
+ @times = []
9
+ @start = Time.now
10
+
11
+ every(1) { log(1) }
12
+ every(2) { log(2) }
13
+ every(1) { log(11) }
14
+ every(2) { log(22) }
15
+ end
16
+
17
+ def log(t)
18
+ @trace << t
19
+
20
+ offset = Time.now - @start
21
+ @times << offset
22
+
23
+ # puts "log(#{t}) @ #{offset}"
24
+ end
25
+
26
+ attr :trace
27
+ attr :times
28
+ end
29
+
30
+ describe Celluloid::Actor do
31
+ it "run every(t) task several times" do
32
+ Celluloid.boot
33
+
34
+ every_actor = EveryActor.new
35
+
36
+ sleep 5.5
37
+
38
+ times = every_actor.times
39
+ trace = every_actor.trace
40
+
41
+ Celluloid.shutdown
42
+
43
+ expect(trace.count(1)).to be == 5
44
+ expect(trace.count(11)).to be == 5
45
+ expect(trace.count(2)).to be == 2
46
+ expect(trace.count(22)).to be == 2
47
+ end
48
+ 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.pre
4
+ version: 0.16.0
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-03-29 00:00:00.000000000 Z
11
+ date: 2014-09-05 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: 2.0.0
19
+ version: 4.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: 2.0.0
26
+ version: 4.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:
@@ -133,6 +147,10 @@ files:
133
147
  - lib/celluloid/registry.rb
134
148
  - lib/celluloid/responses.rb
135
149
  - lib/celluloid/rspec.rb
150
+ - lib/celluloid/rspec/actor_examples.rb
151
+ - lib/celluloid/rspec/example_actor_class.rb
152
+ - lib/celluloid/rspec/mailbox_examples.rb
153
+ - lib/celluloid/rspec/task_examples.rb
136
154
  - lib/celluloid/signals.rb
137
155
  - lib/celluloid/stack_dump.rb
138
156
  - lib/celluloid/supervision_group.rb
@@ -170,12 +188,9 @@ files:
170
188
  - spec/celluloid/tasks/task_fiber_spec.rb
171
189
  - spec/celluloid/tasks/task_thread_spec.rb
172
190
  - spec/celluloid/thread_handle_spec.rb
191
+ - spec/celluloid/timer_spec.rb
173
192
  - spec/celluloid/uuid_spec.rb
174
193
  - spec/spec_helper.rb
175
- - spec/support/actor_examples.rb
176
- - spec/support/example_actor_class.rb
177
- - spec/support/mailbox_examples.rb
178
- - spec/support/task_examples.rb
179
194
  homepage: https://github.com/celluloid/celluloid
180
195
  licenses:
181
196
  - MIT
@@ -196,7 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
196
211
  version: 1.3.6
197
212
  requirements: []
198
213
  rubyforge_project:
199
- rubygems_version: 2.2.0
214
+ rubygems_version: 2.2.2
200
215
  signing_key:
201
216
  specification_version: 4
202
217
  summary: Actor-based concurrent object framework for Ruby