celluloid 0.15.2 → 0.16.0.pre3
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/LICENSE.txt +20 -0
- data/README.md +25 -2
- data/lib/celluloid/actor.rb +88 -147
- data/lib/celluloid/actor_system.rb +107 -0
- data/lib/celluloid/call_chain.rb +1 -1
- data/lib/celluloid/calls.rb +16 -16
- data/lib/celluloid/cell.rb +89 -0
- data/lib/celluloid/condition.rb +25 -8
- data/lib/celluloid/cpu_counter.rb +27 -18
- data/lib/celluloid/evented_mailbox.rb +10 -16
- data/lib/celluloid/exceptions.rb +23 -0
- data/lib/celluloid/future.rb +1 -1
- data/lib/celluloid/handlers.rb +41 -0
- data/lib/celluloid/internal_pool.rb +49 -40
- data/lib/celluloid/logger.rb +30 -0
- data/lib/celluloid/logging/incident_logger.rb +1 -1
- data/lib/celluloid/mailbox.rb +35 -31
- data/lib/celluloid/method.rb +8 -0
- data/lib/celluloid/pool_manager.rb +19 -2
- data/lib/celluloid/probe.rb +73 -0
- data/lib/celluloid/properties.rb +2 -2
- data/lib/celluloid/proxies/actor_proxy.rb +9 -41
- data/lib/celluloid/proxies/cell_proxy.rb +68 -0
- data/lib/celluloid/proxies/sync_proxy.rb +1 -1
- data/lib/celluloid/receivers.rb +5 -13
- data/lib/celluloid/registry.rb +1 -8
- data/lib/celluloid/stack_dump.rb +34 -11
- data/lib/celluloid/supervision_group.rb +26 -14
- data/lib/celluloid/tasks/task_fiber.rb +6 -0
- data/lib/celluloid/tasks/task_thread.rb +2 -1
- data/lib/celluloid/tasks.rb +28 -9
- data/lib/celluloid/thread_handle.rb +2 -2
- data/lib/celluloid.rb +68 -73
- data/spec/celluloid/actor_spec.rb +1 -1
- data/spec/celluloid/actor_system_spec.rb +69 -0
- data/spec/celluloid/block_spec.rb +1 -1
- data/spec/celluloid/calls_spec.rb +1 -1
- data/spec/celluloid/condition_spec.rb +14 -3
- data/spec/celluloid/cpu_counter_spec.rb +82 -0
- data/spec/celluloid/fsm_spec.rb +1 -1
- data/spec/celluloid/future_spec.rb +1 -1
- data/spec/celluloid/notifications_spec.rb +1 -1
- data/spec/celluloid/pool_spec.rb +34 -1
- data/spec/celluloid/probe_spec.rb +121 -0
- data/spec/celluloid/registry_spec.rb +6 -6
- data/spec/celluloid/stack_dump_spec.rb +37 -8
- data/spec/celluloid/supervision_group_spec.rb +7 -1
- data/spec/celluloid/supervisor_spec.rb +12 -1
- data/spec/celluloid/tasks/task_fiber_spec.rb +1 -1
- data/spec/celluloid/tasks/task_thread_spec.rb +1 -1
- data/spec/celluloid/thread_handle_spec.rb +7 -3
- data/spec/celluloid/timer_spec.rb +48 -0
- data/spec/spec_helper.rb +20 -7
- data/spec/support/actor_examples.rb +58 -15
- data/spec/support/mailbox_examples.rb +9 -3
- data/spec/support/task_examples.rb +2 -0
- metadata +48 -22
data/lib/celluloid.rb
CHANGED
|
@@ -3,25 +3,32 @@ require 'thread'
|
|
|
3
3
|
require 'timeout'
|
|
4
4
|
require 'set'
|
|
5
5
|
|
|
6
|
-
if defined?(JRUBY_VERSION) && JRUBY_VERSION == "1.7.3"
|
|
7
|
-
raise "Celluloid is broken on JRuby 1.7.3. Please upgrade to 1.7.4+"
|
|
8
|
-
end
|
|
9
|
-
|
|
10
6
|
module Celluloid
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
# Expose all instance methods as singleton methods
|
|
8
|
+
extend self
|
|
9
|
+
|
|
10
|
+
VERSION = '0.16.0.pre3'
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
# Linking times out after 5 seconds
|
|
13
|
+
LINKING_TIMEOUT = 5
|
|
15
14
|
|
|
16
15
|
# Warning message added to Celluloid objects accessed outside their actors
|
|
17
16
|
BARE_OBJECT_WARNING_MESSAGE = "WARNING: BARE CELLULOID OBJECT "
|
|
18
17
|
|
|
19
18
|
class << self
|
|
20
|
-
|
|
19
|
+
attr_writer :actor_system # Default Actor System
|
|
21
20
|
attr_accessor :logger # Thread-safe logger class
|
|
22
21
|
attr_accessor :task_class # Default task type to use
|
|
23
22
|
attr_accessor :shutdown_timeout # How long actors have to terminate
|
|
24
23
|
|
|
24
|
+
def actor_system
|
|
25
|
+
if Thread.current.celluloid?
|
|
26
|
+
Thread.current[:celluloid_actor_system] or raise Error, "actor system not running"
|
|
27
|
+
else
|
|
28
|
+
Thread.current[:celluloid_actor_system] || @actor_system or raise Error, "Celluloid is not yet started; use Celluloid.boot"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
25
32
|
def included(klass)
|
|
26
33
|
klass.send :extend, ClassMethods
|
|
27
34
|
klass.send :include, InstanceMethods
|
|
@@ -29,19 +36,29 @@ module Celluloid
|
|
|
29
36
|
klass.send :extend, Properties
|
|
30
37
|
|
|
31
38
|
klass.property :mailbox_class, :default => Celluloid::Mailbox
|
|
32
|
-
klass.property :proxy_class, :default => Celluloid::
|
|
39
|
+
klass.property :proxy_class, :default => Celluloid::CellProxy
|
|
33
40
|
klass.property :task_class, :default => Celluloid.task_class
|
|
34
41
|
klass.property :mailbox_size
|
|
35
42
|
|
|
43
|
+
klass.property :exclusive_actor, :default => false
|
|
44
|
+
klass.property :exclusive_methods, :multi => true
|
|
36
45
|
klass.property :execute_block_on_receiver,
|
|
37
46
|
:default => [:after, :every, :receive],
|
|
38
47
|
:multi => true
|
|
39
48
|
|
|
40
49
|
klass.property :finalizer
|
|
41
|
-
klass.property :
|
|
50
|
+
klass.property :exit_handler_name
|
|
42
51
|
|
|
43
52
|
klass.send(:define_singleton_method, :trap_exit) do |*args|
|
|
44
|
-
|
|
53
|
+
exit_handler_name(*args)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
klass.send(:define_singleton_method, :exclusive) do |*args|
|
|
57
|
+
if args.any?
|
|
58
|
+
exclusive_methods(*exclusive_methods, *args)
|
|
59
|
+
else
|
|
60
|
+
exclusive_actor true
|
|
61
|
+
end
|
|
45
62
|
end
|
|
46
63
|
end
|
|
47
64
|
|
|
@@ -69,7 +86,7 @@ module Celluloid
|
|
|
69
86
|
|
|
70
87
|
# Perform a stack dump of all actors to the given output object
|
|
71
88
|
def stack_dump(output = STDERR)
|
|
72
|
-
|
|
89
|
+
actor_system.stack_dump.print(output)
|
|
73
90
|
end
|
|
74
91
|
alias_method :dump, :stack_dump
|
|
75
92
|
|
|
@@ -106,18 +123,15 @@ module Celluloid
|
|
|
106
123
|
end
|
|
107
124
|
|
|
108
125
|
def init
|
|
109
|
-
|
|
126
|
+
@actor_system = ActorSystem.new
|
|
110
127
|
end
|
|
111
128
|
|
|
112
|
-
# Launch default services
|
|
113
|
-
# FIXME: We should set up the supervision hierarchy here
|
|
114
129
|
def start
|
|
115
|
-
|
|
116
|
-
Celluloid::IncidentReporter.supervise_as :default_incident_reporter, STDERR
|
|
130
|
+
actor_system.start
|
|
117
131
|
end
|
|
118
132
|
|
|
119
133
|
def running?
|
|
120
|
-
|
|
134
|
+
actor_system && actor_system.running?
|
|
121
135
|
end
|
|
122
136
|
|
|
123
137
|
def register_shutdown
|
|
@@ -139,41 +153,7 @@ module Celluloid
|
|
|
139
153
|
|
|
140
154
|
# Shut down all running actors
|
|
141
155
|
def shutdown
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
Timeout.timeout(shutdown_timeout) do
|
|
145
|
-
internal_pool.shutdown
|
|
146
|
-
|
|
147
|
-
Logger.debug "Terminating #{actors.size} #{(actors.size > 1) ? 'actors' : 'actor'}..." if actors.size > 0
|
|
148
|
-
|
|
149
|
-
# Attempt to shut down the supervision tree, if available
|
|
150
|
-
Supervisor.root.terminate if Supervisor.root
|
|
151
|
-
|
|
152
|
-
# Actors cannot self-terminate, you must do it for them
|
|
153
|
-
actors.each do |actor|
|
|
154
|
-
begin
|
|
155
|
-
actor.terminate!
|
|
156
|
-
rescue DeadActorError
|
|
157
|
-
end
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
actors.each do |actor|
|
|
161
|
-
begin
|
|
162
|
-
Actor.join(actor)
|
|
163
|
-
rescue DeadActorError
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
end
|
|
167
|
-
rescue Timeout::Error
|
|
168
|
-
Logger.error("Couldn't cleanly terminate all actors in #{shutdown_timeout} seconds!")
|
|
169
|
-
actors.each do |actor|
|
|
170
|
-
begin
|
|
171
|
-
Actor.kill(actor)
|
|
172
|
-
rescue DeadActorError, MailboxDead
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
ensure
|
|
176
|
-
internal_pool.kill
|
|
156
|
+
actor_system.shutdown
|
|
177
157
|
end
|
|
178
158
|
|
|
179
159
|
def version
|
|
@@ -185,7 +165,7 @@ module Celluloid
|
|
|
185
165
|
module ClassMethods
|
|
186
166
|
# Create a new actor
|
|
187
167
|
def new(*args, &block)
|
|
188
|
-
proxy =
|
|
168
|
+
proxy = Cell.new(allocate, behavior_options, actor_options).proxy
|
|
189
169
|
proxy._send_(:initialize, *args, &block)
|
|
190
170
|
proxy
|
|
191
171
|
end
|
|
@@ -195,7 +175,7 @@ module Celluloid
|
|
|
195
175
|
def new_link(*args, &block)
|
|
196
176
|
raise NotActorError, "can't link outside actor context" unless Celluloid.actor?
|
|
197
177
|
|
|
198
|
-
proxy =
|
|
178
|
+
proxy = Cell.new(allocate, behavior_options, actor_options).proxy
|
|
199
179
|
Actor.link(proxy)
|
|
200
180
|
proxy._send_(:initialize, *args, &block)
|
|
201
181
|
proxy
|
|
@@ -233,26 +213,28 @@ module Celluloid
|
|
|
233
213
|
Actor.join(new(*args, &block))
|
|
234
214
|
end
|
|
235
215
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if methods.empty?
|
|
239
|
-
@exclusive_methods = :all
|
|
240
|
-
elsif !defined?(@exclusive_methods) || @exclusive_methods != :all
|
|
241
|
-
@exclusive_methods ||= Set.new
|
|
242
|
-
@exclusive_methods.merge methods.map(&:to_sym)
|
|
243
|
-
end
|
|
216
|
+
def actor_system
|
|
217
|
+
Celluloid.actor_system
|
|
244
218
|
end
|
|
245
219
|
|
|
246
220
|
# Configuration options for Actor#new
|
|
247
221
|
def actor_options
|
|
248
222
|
{
|
|
223
|
+
:actor_system => actor_system,
|
|
249
224
|
:mailbox_class => mailbox_class,
|
|
250
225
|
:mailbox_size => mailbox_size,
|
|
251
|
-
:proxy_class => proxy_class,
|
|
252
226
|
:task_class => task_class,
|
|
253
|
-
:
|
|
254
|
-
|
|
255
|
-
|
|
227
|
+
:exclusive => exclusive_actor,
|
|
228
|
+
}
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def behavior_options
|
|
232
|
+
{
|
|
233
|
+
:proxy_class => proxy_class,
|
|
234
|
+
:exclusive_methods => exclusive_methods,
|
|
235
|
+
:exit_handler_name => exit_handler_name,
|
|
236
|
+
:finalizer => finalizer,
|
|
237
|
+
:receiver_block_executions => execute_block_on_receiver,
|
|
256
238
|
}
|
|
257
239
|
end
|
|
258
240
|
|
|
@@ -291,9 +273,10 @@ module Celluloid
|
|
|
291
273
|
end
|
|
292
274
|
|
|
293
275
|
# Obtain the name of the current actor
|
|
294
|
-
def
|
|
295
|
-
Actor.
|
|
276
|
+
def registered_name
|
|
277
|
+
Actor.registered_name
|
|
296
278
|
end
|
|
279
|
+
alias_method :name, :registered_name
|
|
297
280
|
|
|
298
281
|
def inspect
|
|
299
282
|
return "..." if Celluloid.detect_recursion
|
|
@@ -303,7 +286,7 @@ module Celluloid
|
|
|
303
286
|
if leaked?
|
|
304
287
|
str << Celluloid::BARE_OBJECT_WARNING_MESSAGE
|
|
305
288
|
else
|
|
306
|
-
str << "Celluloid::
|
|
289
|
+
str << "Celluloid::CellProxy"
|
|
307
290
|
end
|
|
308
291
|
|
|
309
292
|
str << "(#{self.class}:0x#{object_id.to_s(16)})"
|
|
@@ -335,7 +318,7 @@ module Celluloid
|
|
|
335
318
|
|
|
336
319
|
# Terminate this actor
|
|
337
320
|
def terminate
|
|
338
|
-
Thread.current[:celluloid_actor].
|
|
321
|
+
Thread.current[:celluloid_actor].behavior_proxy.terminate!
|
|
339
322
|
end
|
|
340
323
|
|
|
341
324
|
# Send a signal with the given name to all waiting methods
|
|
@@ -458,15 +441,21 @@ module Celluloid
|
|
|
458
441
|
|
|
459
442
|
# Handle async calls within an actor itself
|
|
460
443
|
def async(meth = nil, *args, &block)
|
|
461
|
-
Thread.current[:celluloid_actor].
|
|
444
|
+
Thread.current[:celluloid_actor].behavior_proxy.async meth, *args, &block
|
|
462
445
|
end
|
|
463
446
|
|
|
464
447
|
# Handle calls to future within an actor itself
|
|
465
448
|
def future(meth = nil, *args, &block)
|
|
466
|
-
Thread.current[:celluloid_actor].
|
|
449
|
+
Thread.current[:celluloid_actor].behavior_proxy.future meth, *args, &block
|
|
467
450
|
end
|
|
468
451
|
end
|
|
469
452
|
|
|
453
|
+
if defined?(JRUBY_VERSION) && JRUBY_VERSION == "1.7.3"
|
|
454
|
+
raise "Celluloid is broken on JRuby 1.7.3. Please upgrade to 1.7.4+"
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
require 'celluloid/exceptions'
|
|
458
|
+
|
|
470
459
|
require 'celluloid/calls'
|
|
471
460
|
require 'celluloid/call_chain'
|
|
472
461
|
require 'celluloid/condition'
|
|
@@ -482,6 +471,7 @@ require 'celluloid/mailbox'
|
|
|
482
471
|
require 'celluloid/evented_mailbox'
|
|
483
472
|
require 'celluloid/method'
|
|
484
473
|
require 'celluloid/properties'
|
|
474
|
+
require 'celluloid/handlers'
|
|
485
475
|
require 'celluloid/receivers'
|
|
486
476
|
require 'celluloid/registry'
|
|
487
477
|
require 'celluloid/responses'
|
|
@@ -495,13 +485,16 @@ require 'celluloid/uuid'
|
|
|
495
485
|
|
|
496
486
|
require 'celluloid/proxies/abstract_proxy'
|
|
497
487
|
require 'celluloid/proxies/sync_proxy'
|
|
488
|
+
require 'celluloid/proxies/cell_proxy'
|
|
498
489
|
require 'celluloid/proxies/actor_proxy'
|
|
499
490
|
require 'celluloid/proxies/async_proxy'
|
|
500
491
|
require 'celluloid/proxies/future_proxy'
|
|
501
492
|
require 'celluloid/proxies/block_proxy'
|
|
502
493
|
|
|
503
494
|
require 'celluloid/actor'
|
|
495
|
+
require 'celluloid/cell'
|
|
504
496
|
require 'celluloid/future'
|
|
497
|
+
require 'celluloid/actor_system'
|
|
505
498
|
require 'celluloid/pool_manager'
|
|
506
499
|
require 'celluloid/supervision_group'
|
|
507
500
|
require 'celluloid/supervisor'
|
|
@@ -510,6 +503,8 @@ require 'celluloid/logging'
|
|
|
510
503
|
|
|
511
504
|
require 'celluloid/legacy' unless defined?(CELLULOID_FUTURE)
|
|
512
505
|
|
|
506
|
+
$CELLULOID_MONITORING = false
|
|
507
|
+
|
|
513
508
|
# Configure default systemwide settings
|
|
514
509
|
Celluloid.task_class = Celluloid::TaskFiber
|
|
515
510
|
Celluloid.logger = Logger.new(STDERR)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Celluloid::ActorSystem do
|
|
4
|
+
class TestActor
|
|
5
|
+
include Celluloid
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "supports non-global ActorSystem" do
|
|
9
|
+
subject.within do
|
|
10
|
+
Celluloid.actor_system.should == subject
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "starts default actors" do
|
|
15
|
+
subject.start
|
|
16
|
+
|
|
17
|
+
subject.registered.should == [:notifications_fanout, :default_incident_reporter]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "support getting threads" do
|
|
21
|
+
queue = Queue.new
|
|
22
|
+
thread = subject.get_thread do
|
|
23
|
+
Celluloid.actor_system.should == subject
|
|
24
|
+
queue << nil
|
|
25
|
+
end
|
|
26
|
+
queue.pop
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "allows a stack dump" do
|
|
30
|
+
subject.stack_dump.should be_a(Celluloid::StackDump)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "returns named actors" do
|
|
34
|
+
subject.registered.should be_empty
|
|
35
|
+
|
|
36
|
+
subject.within do
|
|
37
|
+
TestActor.supervise_as :test
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
subject.registered.should == [:test]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "returns running actors" do
|
|
44
|
+
subject.running.should be_empty
|
|
45
|
+
|
|
46
|
+
first = subject.within do
|
|
47
|
+
TestActor.new
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
second = subject.within do
|
|
51
|
+
TestActor.new
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
subject.running.should == [first, second]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "shuts down" do
|
|
58
|
+
subject.shutdown
|
|
59
|
+
|
|
60
|
+
lambda { subject.get_thread }.
|
|
61
|
+
should raise_error("Thread pool is not running")
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "warns nicely when no actor system is started" do
|
|
65
|
+
lambda { TestActor.new }.
|
|
66
|
+
should raise_error("Celluloid is not yet started; use Celluloid.boot")
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
|
-
describe Celluloid::Condition do
|
|
3
|
+
describe Celluloid::Condition, actor_system: :global do
|
|
4
4
|
class ConditionExample
|
|
5
5
|
include Celluloid
|
|
6
6
|
|
|
@@ -17,10 +17,10 @@ describe Celluloid::Condition do
|
|
|
17
17
|
condition.signal value
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
def wait_for_condition
|
|
20
|
+
def wait_for_condition(timeout = nil)
|
|
21
21
|
@waiting = true
|
|
22
22
|
begin
|
|
23
|
-
value = @condition.wait
|
|
23
|
+
value = @condition.wait(timeout)
|
|
24
24
|
@signaled_times += 1
|
|
25
25
|
ensure
|
|
26
26
|
@waiting = false
|
|
@@ -62,4 +62,15 @@ describe Celluloid::Condition do
|
|
|
62
62
|
actor.async.signal_condition condition, :value
|
|
63
63
|
condition.wait.should eq(:value)
|
|
64
64
|
end
|
|
65
|
+
|
|
66
|
+
it "times out inside normal Threads" do
|
|
67
|
+
condition = Celluloid::Condition.new
|
|
68
|
+
lambda { condition.wait(1) }.
|
|
69
|
+
should raise_error(Celluloid::ConditionError)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "times out inside Tasks" do
|
|
73
|
+
lambda { actor.wait_for_condition(1) }.
|
|
74
|
+
should raise_error(Celluloid::ConditionError)
|
|
75
|
+
end
|
|
65
76
|
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Celluloid::CPUCounter do
|
|
4
|
+
describe :cores do
|
|
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
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
data/spec/celluloid/fsm_spec.rb
CHANGED
data/spec/celluloid/pool_spec.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
|
-
describe "Celluloid.pool" do
|
|
3
|
+
describe "Celluloid.pool", actor_system: :global do
|
|
4
4
|
class ExampleError < StandardError; end
|
|
5
5
|
|
|
6
6
|
class MyWorker
|
|
@@ -14,11 +14,23 @@ describe "Celluloid.pool" 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" 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
|