celluloid 0.16.0 → 0.17.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of celluloid might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGES.md +333 -0
- data/README.md +1 -1
- data/culture/CODE_OF_CONDUCT.md +28 -0
- data/culture/Gemfile +9 -0
- data/culture/README.md +22 -0
- data/culture/Rakefile +5 -0
- data/culture/SYNC.md +70 -0
- data/culture/celluloid-culture.gemspec +18 -0
- data/culture/gems/README.md +39 -0
- data/culture/gems/dependencies.yml +78 -0
- data/culture/gems/loader.rb +101 -0
- data/culture/rubocop/README.md +38 -0
- data/culture/rubocop/lint.yml +8 -0
- data/culture/rubocop/metrics.yml +15 -0
- data/culture/rubocop/rubocop.yml +4 -0
- data/culture/rubocop/style.yml +48 -0
- data/culture/spec/gems_spec.rb +2 -0
- data/culture/spec/spec_helper.rb +0 -0
- data/culture/spec/sync_spec.rb +2 -0
- data/culture/sync.rb +56 -0
- data/culture/tasks/rspec.rake +5 -0
- data/culture/tasks/rubocop.rake +2 -0
- data/examples/basic_usage.rb +49 -0
- data/examples/futures.rb +38 -0
- data/examples/ring.rb +61 -0
- data/examples/simple_pmap.rb +14 -0
- data/examples/timers.rb +72 -0
- data/lib/celluloid.rb +142 -127
- data/lib/celluloid/actor.rb +47 -41
- data/lib/celluloid/actor_system.rb +75 -22
- data/lib/celluloid/autostart.rb +1 -1
- data/lib/celluloid/backported.rb +2 -0
- data/lib/celluloid/call/async.rb +16 -0
- data/lib/celluloid/call/block.rb +22 -0
- data/lib/celluloid/call/sync.rb +70 -0
- data/lib/celluloid/calls.rb +25 -114
- data/lib/celluloid/cell.rb +32 -20
- data/lib/celluloid/condition.rb +3 -3
- data/lib/celluloid/core_ext.rb +1 -1
- data/lib/celluloid/current.rb +2 -0
- data/lib/celluloid/deprecate.rb +18 -0
- data/lib/celluloid/exceptions.rb +1 -1
- data/lib/celluloid/fiber.rb +3 -3
- data/lib/celluloid/future.rb +7 -6
- data/lib/celluloid/group.rb +65 -0
- data/lib/celluloid/group/manager.rb +27 -0
- data/lib/celluloid/group/pool.rb +125 -0
- data/lib/celluloid/group/spawner.rb +71 -0
- data/lib/celluloid/logging.rb +5 -5
- data/lib/celluloid/mailbox.rb +14 -13
- data/lib/celluloid/mailbox/evented.rb +76 -0
- data/lib/celluloid/notices.rb +15 -0
- data/lib/celluloid/proxies.rb +12 -0
- data/lib/celluloid/proxy/abstract.rb +24 -0
- data/lib/celluloid/proxy/actor.rb +46 -0
- data/lib/celluloid/proxy/async.rb +36 -0
- data/lib/celluloid/proxy/block.rb +31 -0
- data/lib/celluloid/proxy/cell.rb +76 -0
- data/lib/celluloid/proxy/future.rb +40 -0
- data/lib/celluloid/proxy/sync.rb +44 -0
- data/lib/celluloid/rspec.rb +9 -10
- data/lib/celluloid/system_events.rb +16 -15
- data/lib/celluloid/{tasks.rb → task.rb} +21 -21
- data/lib/celluloid/task/fibered.rb +45 -0
- data/lib/celluloid/task/threaded.rb +59 -0
- data/lib/celluloid/test.rb +1 -1
- data/lib/celluloid/thread.rb +6 -1
- data/lib/celluloid/version.rb +3 -0
- data/spec/celluloid/actor_spec.rb +2 -2
- data/spec/celluloid/actor_system_spec.rb +35 -21
- data/spec/celluloid/block_spec.rb +3 -5
- data/spec/celluloid/calls_spec.rb +33 -11
- data/spec/celluloid/condition_spec.rb +16 -13
- data/spec/celluloid/evented_mailbox_spec.rb +1 -31
- data/spec/celluloid/future_spec.rb +13 -10
- data/spec/celluloid/group/elastic_spec.rb +0 -0
- data/spec/celluloid/group/manager_spec.rb +0 -0
- data/spec/celluloid/group/pool_spec.rb +8 -0
- data/spec/celluloid/group/spawner_spec.rb +8 -0
- data/spec/celluloid/mailbox/evented_spec.rb +27 -0
- data/spec/celluloid/mailbox_spec.rb +1 -3
- data/spec/celluloid/misc/leak_spec.rb +73 -0
- data/spec/celluloid/task/fibered_spec.rb +5 -0
- data/spec/celluloid/task/threaded_spec.rb +5 -0
- data/spec/celluloid/timer_spec.rb +14 -16
- data/spec/deprecate/actor_system_spec.rb +72 -0
- data/spec/deprecate/block_spec.rb +52 -0
- data/spec/deprecate/calls_spec.rb +57 -0
- data/spec/deprecate/evented_mailbox_spec.rb +34 -0
- data/spec/deprecate/future_spec.rb +32 -0
- data/spec/deprecate/internal_pool_spec.rb +4 -0
- data/spec/shared/actor_examples.rb +1237 -0
- data/spec/shared/group_examples.rb +121 -0
- data/{lib/celluloid/rspec → spec/shared}/mailbox_examples.rb +20 -17
- data/{lib/celluloid/rspec → spec/shared}/task_examples.rb +9 -8
- data/spec/spec_helper.rb +72 -16
- data/spec/support/coverage.rb +4 -0
- data/spec/support/crash_checking.rb +68 -0
- data/spec/support/debugging.rb +31 -0
- data/spec/support/env.rb +16 -0
- data/{lib/celluloid/rspec/example_actor_class.rb → spec/support/examples/actor_class.rb} +21 -2
- data/spec/support/examples/evented_mailbox_class.rb +27 -0
- data/spec/support/includer.rb +9 -0
- data/spec/support/logging.rb +63 -0
- data/spec/support/loose_threads.rb +65 -0
- data/spec/support/reset_class_variables.rb +27 -0
- data/spec/support/sleep_and_wait.rb +14 -0
- data/spec/support/split_logs.rb +1 -0
- data/spec/support/stubbing.rb +14 -0
- metadata +255 -95
- data/lib/celluloid/call_chain.rb +0 -13
- data/lib/celluloid/cpu_counter.rb +0 -34
- data/lib/celluloid/evented_mailbox.rb +0 -73
- data/lib/celluloid/fsm.rb +0 -186
- data/lib/celluloid/handlers.rb +0 -41
- data/lib/celluloid/internal_pool.rb +0 -159
- data/lib/celluloid/legacy.rb +0 -9
- data/lib/celluloid/links.rb +0 -36
- data/lib/celluloid/logger.rb +0 -93
- data/lib/celluloid/logging/incident.rb +0 -21
- data/lib/celluloid/logging/incident_logger.rb +0 -129
- data/lib/celluloid/logging/incident_reporter.rb +0 -48
- data/lib/celluloid/logging/log_event.rb +0 -20
- data/lib/celluloid/logging/ring_buffer.rb +0 -65
- data/lib/celluloid/method.rb +0 -32
- data/lib/celluloid/notifications.rb +0 -83
- data/lib/celluloid/pool_manager.rb +0 -146
- data/lib/celluloid/probe.rb +0 -73
- data/lib/celluloid/properties.rb +0 -24
- data/lib/celluloid/proxies/abstract_proxy.rb +0 -20
- data/lib/celluloid/proxies/actor_proxy.rb +0 -38
- data/lib/celluloid/proxies/async_proxy.rb +0 -31
- data/lib/celluloid/proxies/block_proxy.rb +0 -29
- data/lib/celluloid/proxies/cell_proxy.rb +0 -68
- data/lib/celluloid/proxies/future_proxy.rb +0 -35
- data/lib/celluloid/proxies/sync_proxy.rb +0 -36
- data/lib/celluloid/receivers.rb +0 -63
- data/lib/celluloid/registry.rb +0 -57
- data/lib/celluloid/responses.rb +0 -44
- data/lib/celluloid/rspec/actor_examples.rb +0 -1054
- data/lib/celluloid/signals.rb +0 -23
- data/lib/celluloid/stack_dump.rb +0 -133
- data/lib/celluloid/supervision_group.rb +0 -169
- data/lib/celluloid/supervisor.rb +0 -22
- data/lib/celluloid/task_set.rb +0 -49
- data/lib/celluloid/tasks/task_fiber.rb +0 -43
- data/lib/celluloid/tasks/task_thread.rb +0 -53
- data/lib/celluloid/thread_handle.rb +0 -50
- data/lib/celluloid/uuid.rb +0 -38
- data/spec/celluloid/cpu_counter_spec.rb +0 -82
- data/spec/celluloid/fsm_spec.rb +0 -107
- data/spec/celluloid/internal_pool_spec.rb +0 -52
- data/spec/celluloid/links_spec.rb +0 -45
- data/spec/celluloid/logging/ring_buffer_spec.rb +0 -38
- data/spec/celluloid/notifications_spec.rb +0 -120
- data/spec/celluloid/pool_spec.rb +0 -92
- data/spec/celluloid/probe_spec.rb +0 -121
- data/spec/celluloid/properties_spec.rb +0 -42
- data/spec/celluloid/registry_spec.rb +0 -64
- data/spec/celluloid/stack_dump_spec.rb +0 -64
- data/spec/celluloid/supervision_group_spec.rb +0 -65
- data/spec/celluloid/supervisor_spec.rb +0 -103
- data/spec/celluloid/tasks/task_fiber_spec.rb +0 -5
- data/spec/celluloid/tasks/task_thread_spec.rb +0 -5
- data/spec/celluloid/thread_handle_spec.rb +0 -26
- data/spec/celluloid/uuid_spec.rb +0 -11
data/lib/celluloid/call_chain.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
module Celluloid
|
2
|
-
class CallChain
|
3
|
-
def self.current_id=(value)
|
4
|
-
Thread.current[:celluloid_chain_id] = value
|
5
|
-
task = Thread.current[:celluloid_task]
|
6
|
-
task.chain_id = value if task
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.current_id
|
10
|
-
Thread.current[:celluloid_chain_id]
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
module Celluloid
|
2
|
-
module CPUCounter
|
3
|
-
class << self
|
4
|
-
def cores
|
5
|
-
@cores ||= count_cores
|
6
|
-
end
|
7
|
-
|
8
|
-
private
|
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
|
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
|
@@ -1,73 +0,0 @@
|
|
1
|
-
module Celluloid
|
2
|
-
# An alternative implementation of Celluloid::Mailbox using Reactor
|
3
|
-
class EventedMailbox < Celluloid::Mailbox
|
4
|
-
attr_reader :reactor
|
5
|
-
|
6
|
-
def initialize(reactor_class)
|
7
|
-
super()
|
8
|
-
# @condition won't be used in the class.
|
9
|
-
@reactor = reactor_class.new
|
10
|
-
end
|
11
|
-
|
12
|
-
# Add a message to the Mailbox
|
13
|
-
def <<(message)
|
14
|
-
@mutex.lock
|
15
|
-
begin
|
16
|
-
if mailbox_full || @dead
|
17
|
-
dead_letter(message)
|
18
|
-
return
|
19
|
-
end
|
20
|
-
if message.is_a?(SystemEvent)
|
21
|
-
# SystemEvents are high priority messages so they get added to the
|
22
|
-
# head of our message queue instead of the end
|
23
|
-
@messages.unshift message
|
24
|
-
else
|
25
|
-
@messages << message
|
26
|
-
end
|
27
|
-
|
28
|
-
current_actor = Thread.current[:celluloid_actor]
|
29
|
-
@reactor.wakeup unless current_actor && current_actor.mailbox == self
|
30
|
-
rescue IOError
|
31
|
-
Logger.crash "reactor crashed", $!
|
32
|
-
dead_letter(message)
|
33
|
-
ensure
|
34
|
-
@mutex.unlock rescue nil
|
35
|
-
end
|
36
|
-
nil
|
37
|
-
end
|
38
|
-
|
39
|
-
# Receive a message from the Mailbox
|
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
|
44
|
-
end
|
45
|
-
|
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
|
52
|
-
rescue IOError
|
53
|
-
raise MailboxShutdown, "mailbox shutdown called during receive"
|
54
|
-
end
|
55
|
-
|
56
|
-
# Obtain the next message from the mailbox that matches the given block
|
57
|
-
def next_message(block)
|
58
|
-
@mutex.lock
|
59
|
-
begin
|
60
|
-
super(&block)
|
61
|
-
ensure
|
62
|
-
@mutex.unlock rescue nil
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
# Cleanup any IO objects this Mailbox may be using
|
67
|
-
def shutdown
|
68
|
-
super do
|
69
|
-
@reactor.shutdown
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
data/lib/celluloid/fsm.rb
DELETED
@@ -1,186 +0,0 @@
|
|
1
|
-
module Celluloid
|
2
|
-
# Simple finite state machines with integrated Celluloid timeout support
|
3
|
-
# Inspired by Erlang's gen_fsm (http://www.erlang.org/doc/man/gen_fsm.html)
|
4
|
-
#
|
5
|
-
# Basic usage:
|
6
|
-
#
|
7
|
-
# class MyMachine
|
8
|
-
# include Celluloid::FSM # NOTE: this does NOT pull in the Celluloid module
|
9
|
-
# end
|
10
|
-
#
|
11
|
-
# Inside an actor:
|
12
|
-
#
|
13
|
-
# #
|
14
|
-
# machine = MyMachine.new(current_actor)
|
15
|
-
module FSM
|
16
|
-
class UnattachedError < Celluloid::Error; end # Not attached to an actor
|
17
|
-
|
18
|
-
DEFAULT_STATE = :default # Default state name unless one is explicitly set
|
19
|
-
|
20
|
-
# Included hook to extend class methods
|
21
|
-
def self.included(klass)
|
22
|
-
klass.send :extend, ClassMethods
|
23
|
-
end
|
24
|
-
|
25
|
-
module ClassMethods
|
26
|
-
# Obtain or set the default state
|
27
|
-
# Passing a state name sets the default state
|
28
|
-
def default_state(new_default = nil)
|
29
|
-
if new_default
|
30
|
-
@default_state = new_default.to_sym
|
31
|
-
else
|
32
|
-
defined?(@default_state) ? @default_state : DEFAULT_STATE
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# Obtain the valid states for this FSM
|
37
|
-
def states
|
38
|
-
@states ||= {}
|
39
|
-
end
|
40
|
-
|
41
|
-
# Declare an FSM state and optionally provide a callback block to fire
|
42
|
-
# Options:
|
43
|
-
# * to: a state or array of states this state can transition to
|
44
|
-
def state(*args, &block)
|
45
|
-
if args.last.is_a? Hash
|
46
|
-
# Stringify keys :/
|
47
|
-
options = args.pop.inject({}) { |h,(k,v)| h[k.to_s] = v; h }
|
48
|
-
else
|
49
|
-
options = {}
|
50
|
-
end
|
51
|
-
|
52
|
-
args.each do |name|
|
53
|
-
name = name.to_sym
|
54
|
-
default_state name if options['default']
|
55
|
-
states[name] = State.new(name, options['to'], &block)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
attr_reader :actor
|
61
|
-
|
62
|
-
# Be kind and call super if you must redefine initialize
|
63
|
-
def initialize(actor = nil)
|
64
|
-
@state = self.class.default_state
|
65
|
-
@delayed_transition = nil
|
66
|
-
@actor = actor
|
67
|
-
@actor ||= Celluloid.current_actor if Celluloid.actor?
|
68
|
-
end
|
69
|
-
|
70
|
-
# Obtain the current state of the FSM
|
71
|
-
attr_reader :state
|
72
|
-
|
73
|
-
# Attach this FSM to an actor. This allows FSMs to wait for and initiate
|
74
|
-
# events in the context of a particular actor
|
75
|
-
def attach(actor)
|
76
|
-
@actor = actor
|
77
|
-
end
|
78
|
-
alias_method :actor=, :attach
|
79
|
-
|
80
|
-
# Transition to another state
|
81
|
-
# Options:
|
82
|
-
# * delay: don't transition immediately, wait the given number of seconds.
|
83
|
-
# This will return a Celluloid::Timer object you can use to
|
84
|
-
# cancel the pending state transition.
|
85
|
-
#
|
86
|
-
# Note: making additional state transitions will cancel delayed transitions
|
87
|
-
def transition(state_name, options = {})
|
88
|
-
new_state = validate_and_sanitize_new_state(state_name)
|
89
|
-
return unless new_state
|
90
|
-
|
91
|
-
if handle_delayed_transitions(new_state, options[:delay])
|
92
|
-
return @delayed_transition
|
93
|
-
end
|
94
|
-
|
95
|
-
transition_with_callbacks!(new_state)
|
96
|
-
end
|
97
|
-
|
98
|
-
# Immediate state transition with no sanity checks, or callbacks. "Dangerous!"
|
99
|
-
def transition!(state_name)
|
100
|
-
@state = state_name
|
101
|
-
end
|
102
|
-
|
103
|
-
protected
|
104
|
-
|
105
|
-
def validate_and_sanitize_new_state(state_name)
|
106
|
-
state_name = state_name.to_sym
|
107
|
-
|
108
|
-
return if current_state_name == state_name
|
109
|
-
|
110
|
-
if current_state and not current_state.valid_transition? state_name
|
111
|
-
valid = current_state.transitions.map(&:to_s).join(", ")
|
112
|
-
raise ArgumentError, "#{self.class} can't change state from '#{@state}' to '#{state_name}', only to: #{valid}"
|
113
|
-
end
|
114
|
-
|
115
|
-
new_state = states[state_name]
|
116
|
-
|
117
|
-
unless new_state
|
118
|
-
return if state_name == default_state
|
119
|
-
raise ArgumentError, "invalid state for #{self.class}: #{state_name}"
|
120
|
-
end
|
121
|
-
|
122
|
-
new_state
|
123
|
-
end
|
124
|
-
|
125
|
-
def transition_with_callbacks!(state_name)
|
126
|
-
transition! state_name.name
|
127
|
-
state_name.call(self)
|
128
|
-
end
|
129
|
-
|
130
|
-
def states
|
131
|
-
self.class.states
|
132
|
-
end
|
133
|
-
|
134
|
-
def default_state
|
135
|
-
self.class.default_state
|
136
|
-
end
|
137
|
-
|
138
|
-
def current_state
|
139
|
-
states[@state]
|
140
|
-
end
|
141
|
-
|
142
|
-
def current_state_name
|
143
|
-
current_state && current_state.name || ''
|
144
|
-
end
|
145
|
-
|
146
|
-
def handle_delayed_transitions(new_state, delay)
|
147
|
-
if delay
|
148
|
-
raise UnattachedError, "can't delay unless attached" unless @actor
|
149
|
-
@delayed_transition.cancel if @delayed_transition
|
150
|
-
|
151
|
-
@delayed_transition = @actor.after(delay) do
|
152
|
-
transition_with_callbacks!(new_state)
|
153
|
-
end
|
154
|
-
|
155
|
-
return @delayed_transition
|
156
|
-
end
|
157
|
-
|
158
|
-
if defined?(@delayed_transition) and @delayed_transition
|
159
|
-
@delayed_transition.cancel
|
160
|
-
@delayed_transition = nil
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
# FSM states as declared by Celluloid::FSM.state
|
165
|
-
class State
|
166
|
-
attr_reader :name, :transitions
|
167
|
-
|
168
|
-
def initialize(name, transitions = nil, &block)
|
169
|
-
@name, @block = name, block
|
170
|
-
@transitions = nil
|
171
|
-
@transitions = Array(transitions).map { |t| t.to_sym } if transitions
|
172
|
-
end
|
173
|
-
|
174
|
-
def call(obj)
|
175
|
-
obj.instance_eval(&@block) if @block
|
176
|
-
end
|
177
|
-
|
178
|
-
def valid_transition?(new_state)
|
179
|
-
# All transitions are allowed unless expressly
|
180
|
-
return true unless @transitions
|
181
|
-
|
182
|
-
@transitions.include? new_state.to_sym
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
data/lib/celluloid/handlers.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'set'
|
2
|
-
|
3
|
-
module Celluloid
|
4
|
-
class Handlers
|
5
|
-
def initialize
|
6
|
-
@handlers = Set.new
|
7
|
-
end
|
8
|
-
|
9
|
-
def handle(*patterns, &block)
|
10
|
-
patterns.each do |pattern|
|
11
|
-
handler = Handler.new pattern, block
|
12
|
-
@handlers << handler
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
# Handle incoming messages
|
17
|
-
def handle_message(message)
|
18
|
-
if handler = @handlers.find { |h| h.match(message) }
|
19
|
-
handler.call message
|
20
|
-
handler
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
# Methods blocking on a call to receive
|
26
|
-
class Handler
|
27
|
-
def initialize(pattern, block)
|
28
|
-
@pattern = pattern
|
29
|
-
@block = block
|
30
|
-
end
|
31
|
-
|
32
|
-
# Match a message with this receiver's block
|
33
|
-
def match(message)
|
34
|
-
@pattern === message
|
35
|
-
end
|
36
|
-
|
37
|
-
def call(message)
|
38
|
-
@block.call message
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,159 +0,0 @@
|
|
1
|
-
require 'thread'
|
2
|
-
|
3
|
-
module Celluloid
|
4
|
-
# Maintain a thread pool FOR SPEED!!
|
5
|
-
class InternalPool
|
6
|
-
attr_accessor :max_idle
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
@mutex = Mutex.new
|
10
|
-
@idle_threads = []
|
11
|
-
@all_threads = []
|
12
|
-
@busy_size = 0
|
13
|
-
@idle_size = 0
|
14
|
-
|
15
|
-
# TODO: should really adjust this based on usage
|
16
|
-
@max_idle = 16
|
17
|
-
@running = true
|
18
|
-
end
|
19
|
-
|
20
|
-
def busy_size
|
21
|
-
@busy_size
|
22
|
-
end
|
23
|
-
|
24
|
-
def idle_size
|
25
|
-
@idle_size
|
26
|
-
end
|
27
|
-
|
28
|
-
def assert_running
|
29
|
-
raise Error, "Thread pool is not running" unless running?
|
30
|
-
end
|
31
|
-
|
32
|
-
def assert_inactive
|
33
|
-
if active?
|
34
|
-
message = "Thread pool is still active"
|
35
|
-
if defined?(JRUBY_VERSION)
|
36
|
-
Celluloid.logger.warn message
|
37
|
-
else
|
38
|
-
raise Error, message
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def running?
|
44
|
-
@running
|
45
|
-
end
|
46
|
-
|
47
|
-
def active?
|
48
|
-
busy_size + idle_size > 0
|
49
|
-
end
|
50
|
-
|
51
|
-
def each
|
52
|
-
to_a.each {|thread| yield thread }
|
53
|
-
end
|
54
|
-
|
55
|
-
def to_a
|
56
|
-
@mutex.synchronize { @all_threads.dup }
|
57
|
-
end
|
58
|
-
|
59
|
-
# Get a thread from the pool, running the given block
|
60
|
-
def get(&block)
|
61
|
-
@mutex.synchronize do
|
62
|
-
assert_running
|
63
|
-
|
64
|
-
begin
|
65
|
-
if @idle_threads.empty?
|
66
|
-
thread = create
|
67
|
-
else
|
68
|
-
thread = @idle_threads.pop
|
69
|
-
@idle_size = @idle_threads.length
|
70
|
-
end
|
71
|
-
end until thread.status # handle crashed threads
|
72
|
-
|
73
|
-
thread.busy = true
|
74
|
-
@busy_size += 1
|
75
|
-
thread[:celluloid_queue] << block
|
76
|
-
thread
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
# Return a thread to the pool
|
81
|
-
def put(thread)
|
82
|
-
@mutex.synchronize do
|
83
|
-
thread.busy = false
|
84
|
-
if idle_size + 1 >= @max_idle
|
85
|
-
thread[:celluloid_queue] << nil
|
86
|
-
@busy_size -= 1
|
87
|
-
@all_threads.delete(thread)
|
88
|
-
else
|
89
|
-
@idle_threads.push thread
|
90
|
-
@busy_size -= 1
|
91
|
-
@idle_size = @idle_threads.length
|
92
|
-
clean_thread_locals(thread)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
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
|
-
|
124
|
-
# Create a new thread with an associated queue of procs to run
|
125
|
-
def create
|
126
|
-
queue = Queue.new
|
127
|
-
thread = Thread.new do
|
128
|
-
while proc = queue.pop
|
129
|
-
begin
|
130
|
-
proc.call
|
131
|
-
rescue => ex
|
132
|
-
Logger.crash("thread crashed", ex)
|
133
|
-
end
|
134
|
-
|
135
|
-
put thread
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
thread[:celluloid_queue] = queue
|
140
|
-
# @idle_threads << thread
|
141
|
-
@all_threads << thread
|
142
|
-
thread
|
143
|
-
end
|
144
|
-
|
145
|
-
# Clean the thread locals of an incoming thread
|
146
|
-
def clean_thread_locals(thread)
|
147
|
-
thread.keys.each do |key|
|
148
|
-
next if key == :celluloid_queue
|
149
|
-
|
150
|
-
# Ruby seems to lack an API for deleting thread locals. WTF, Ruby?
|
151
|
-
thread[key] = nil
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def finalize
|
156
|
-
@max_idle = 0
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|