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
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require 'celluloid'
|
|
2
|
+
|
|
3
|
+
$CELLULOID_MONITORING = true
|
|
4
|
+
|
|
5
|
+
module Celluloid
|
|
6
|
+
class Probe
|
|
7
|
+
include Celluloid
|
|
8
|
+
include Celluloid::Notifications
|
|
9
|
+
|
|
10
|
+
NOTIFICATIONS_TOPIC_BASE = 'celluloid.events.%s'
|
|
11
|
+
INITIAL_EVENTS = Queue.new
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
def run
|
|
15
|
+
# spawn the actor if not found
|
|
16
|
+
supervise_as(:probe_actor) unless Actor[:probe_actor] && Actor[:probe_actor].alive?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def actor_created(actor)
|
|
20
|
+
trigger_event(:actor_created, actor)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def actor_named(actor)
|
|
24
|
+
trigger_event(:actor_named, actor)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def actor_died(actor)
|
|
28
|
+
trigger_event(:actor_died, actor)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def actors_linked(a, b)
|
|
32
|
+
a = find_actor(a)
|
|
33
|
+
b = find_actor(b)
|
|
34
|
+
trigger_event(:actors_linked, a, b)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def trigger_event(name, *args)
|
|
40
|
+
return unless $CELLULOID_MONITORING
|
|
41
|
+
probe_actor = Actor[:probe_actor]
|
|
42
|
+
if probe_actor
|
|
43
|
+
probe_actor.async.dispatch_event(name, args)
|
|
44
|
+
else
|
|
45
|
+
INITIAL_EVENTS << [name, args]
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def find_actor(obj)
|
|
50
|
+
if obj.__send__(:class) == Actor
|
|
51
|
+
obj
|
|
52
|
+
elsif owner = obj.instance_variable_get(OWNER_IVAR)
|
|
53
|
+
owner
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def initialize
|
|
59
|
+
async.first_run
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def first_run
|
|
63
|
+
until INITIAL_EVENTS.size == 0
|
|
64
|
+
event = INITIAL_EVENTS.pop
|
|
65
|
+
dispatch_event(*event)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def dispatch_event(cmd, args)
|
|
70
|
+
publish(NOTIFICATIONS_TOPIC_BASE % cmd, args)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
data/lib/celluloid/properties.rb
CHANGED
|
@@ -9,7 +9,7 @@ module Celluloid
|
|
|
9
9
|
|
|
10
10
|
ancestors.first.send(:define_singleton_method, name) do |value = nil, *extra|
|
|
11
11
|
if value
|
|
12
|
-
value = value ? [value, *extra] : [] if multi
|
|
12
|
+
value = value ? [value, *send(name), *extra].uniq : [] if multi
|
|
13
13
|
instance_variable_set(ivar_name, value)
|
|
14
14
|
elsif instance_variables.include?(ivar_name)
|
|
15
15
|
instance_variable_get(ivar_name)
|
|
@@ -21,4 +21,4 @@ module Celluloid
|
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
|
-
end
|
|
24
|
+
end
|
|
@@ -1,59 +1,27 @@
|
|
|
1
1
|
module Celluloid
|
|
2
|
-
# A proxy
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
attr_reader :thread
|
|
2
|
+
# A proxy which controls the Actor lifecycle
|
|
3
|
+
class ActorProxy < AbstractProxy
|
|
4
|
+
attr_reader :thread, :mailbox
|
|
6
5
|
|
|
7
6
|
# Used for reflecting on proxy objects themselves
|
|
8
7
|
def __class__; ActorProxy; end
|
|
9
8
|
|
|
10
|
-
def initialize(
|
|
11
|
-
@thread =
|
|
12
|
-
|
|
13
|
-
super(actor.mailbox, actor.subject.class.to_s)
|
|
14
|
-
@sync_proxy = SyncProxy.new(@mailbox, @klass)
|
|
15
|
-
@async_proxy = AsyncProxy.new(@mailbox, @klass)
|
|
16
|
-
@future_proxy = FutureProxy.new(@mailbox, @klass)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def _send_(meth, *args, &block)
|
|
20
|
-
method_missing :__send__, meth, *args, &block
|
|
9
|
+
def initialize(thread, mailbox)
|
|
10
|
+
@thread = thread
|
|
11
|
+
@mailbox = mailbox
|
|
21
12
|
end
|
|
22
13
|
|
|
23
14
|
def inspect
|
|
24
|
-
|
|
15
|
+
# TODO: use a system event to fetch actor state: tasks?
|
|
16
|
+
"#<Celluloid::ActorProxy(#{@mailbox.address}) alive>"
|
|
25
17
|
rescue DeadActorError
|
|
26
|
-
"#<Celluloid::ActorProxy(#{@
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def method(name)
|
|
30
|
-
Method.new(self, name)
|
|
18
|
+
"#<Celluloid::ActorProxy(#{@mailbox.address}) dead>"
|
|
31
19
|
end
|
|
32
20
|
|
|
33
21
|
def alive?
|
|
34
22
|
@mailbox.alive?
|
|
35
23
|
end
|
|
36
24
|
|
|
37
|
-
alias_method :sync, :method_missing
|
|
38
|
-
|
|
39
|
-
# Obtain an async proxy or explicitly invoke a named async method
|
|
40
|
-
def async(method_name = nil, *args, &block)
|
|
41
|
-
if method_name
|
|
42
|
-
@async_proxy.method_missing method_name, *args, &block
|
|
43
|
-
else
|
|
44
|
-
@async_proxy
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# Obtain a future proxy or explicitly invoke a named future method
|
|
49
|
-
def future(method_name = nil, *args, &block)
|
|
50
|
-
if method_name
|
|
51
|
-
@future_proxy.method_missing method_name, *args, &block
|
|
52
|
-
else
|
|
53
|
-
@future_proxy
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
25
|
# Terminate the associated actor
|
|
58
26
|
def terminate
|
|
59
27
|
terminate!
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module Celluloid
|
|
2
|
+
# A proxy object returned from Celluloid::Actor.new/new_link which converts
|
|
3
|
+
# the normal Ruby method protocol into an inter-actor message protocol
|
|
4
|
+
class CellProxy < SyncProxy
|
|
5
|
+
# Used for reflecting on proxy objects themselves
|
|
6
|
+
def __class__; CellProxy; end
|
|
7
|
+
|
|
8
|
+
def initialize(actor_proxy, mailbox, klass)
|
|
9
|
+
super(mailbox, klass)
|
|
10
|
+
@actor_proxy = actor_proxy
|
|
11
|
+
@sync_proxy = SyncProxy.new(mailbox, klass)
|
|
12
|
+
@async_proxy = AsyncProxy.new(mailbox, klass)
|
|
13
|
+
@future_proxy = FutureProxy.new(mailbox, klass)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def _send_(meth, *args, &block)
|
|
17
|
+
method_missing :__send__, meth, *args, &block
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def inspect
|
|
21
|
+
method_missing :inspect
|
|
22
|
+
rescue DeadActorError
|
|
23
|
+
"#<Celluloid::CellProxy(#{@klass}) dead>"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def method(name)
|
|
27
|
+
Method.new(self, name)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
alias_method :sync, :method_missing
|
|
31
|
+
|
|
32
|
+
# Obtain an async proxy or explicitly invoke a named async method
|
|
33
|
+
def async(method_name = nil, *args, &block)
|
|
34
|
+
if method_name
|
|
35
|
+
@async_proxy.method_missing method_name, *args, &block
|
|
36
|
+
else
|
|
37
|
+
@async_proxy
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Obtain a future proxy or explicitly invoke a named future method
|
|
42
|
+
def future(method_name = nil, *args, &block)
|
|
43
|
+
if method_name
|
|
44
|
+
@future_proxy.method_missing method_name, *args, &block
|
|
45
|
+
else
|
|
46
|
+
@future_proxy
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def alive?
|
|
51
|
+
@actor_proxy.alive?
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def thread
|
|
55
|
+
@actor_proxy.thread
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Terminate the associated actor
|
|
59
|
+
def terminate
|
|
60
|
+
@actor_proxy.terminate
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Terminate the associated actor asynchronously
|
|
64
|
+
def terminate!
|
|
65
|
+
@actor_proxy.terminate!
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -15,7 +15,7 @@ module Celluloid
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def respond_to?(meth, include_private = false)
|
|
18
|
-
__class__.instance_methods.include?(meth) ||
|
|
18
|
+
__class__.instance_methods.include?(meth) || method_missing(:respond_to?, meth, include_private)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def method_missing(meth, *args, &block)
|
data/lib/celluloid/receivers.rb
CHANGED
|
@@ -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 =
|
|
10
|
+
@timers = timers
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
# Receive an asynchronous message
|
|
@@ -28,24 +29,15 @@ 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
|
-
|
|
38
|
+
receiver.timer.cancel if receiver.timer
|
|
48
39
|
receiver.resume message
|
|
40
|
+
message
|
|
49
41
|
end
|
|
50
42
|
end
|
|
51
43
|
|
data/lib/celluloid/registry.rb
CHANGED
|
@@ -3,10 +3,6 @@ require 'thread'
|
|
|
3
3
|
module Celluloid
|
|
4
4
|
# The Registry allows us to refer to specific actors by human-meaningful names
|
|
5
5
|
class Registry
|
|
6
|
-
class << self
|
|
7
|
-
attr_reader :root
|
|
8
|
-
end
|
|
9
|
-
|
|
10
6
|
def initialize
|
|
11
7
|
@registry = {}
|
|
12
8
|
@registry_lock = Mutex.new
|
|
@@ -15,7 +11,7 @@ module Celluloid
|
|
|
15
11
|
# Register an Actor
|
|
16
12
|
def []=(name, actor)
|
|
17
13
|
actor_singleton = class << actor; self; end
|
|
18
|
-
unless actor_singleton.ancestors.include?
|
|
14
|
+
unless actor_singleton.ancestors.include? AbstractProxy
|
|
19
15
|
raise TypeError, "not an actor"
|
|
20
16
|
end
|
|
21
17
|
|
|
@@ -57,8 +53,5 @@ module Celluloid
|
|
|
57
53
|
end
|
|
58
54
|
hash
|
|
59
55
|
end
|
|
60
|
-
|
|
61
|
-
# Create the default registry
|
|
62
|
-
@root = new
|
|
63
56
|
end
|
|
64
57
|
end
|
data/lib/celluloid/stack_dump.rb
CHANGED
|
@@ -16,17 +16,21 @@ module Celluloid
|
|
|
16
16
|
|
|
17
17
|
class ActorState
|
|
18
18
|
include DisplayBacktrace
|
|
19
|
-
|
|
20
|
-
attr_accessor :subject_id, :subject_class, :name
|
|
19
|
+
attr_accessor :name, :id, :cell
|
|
21
20
|
attr_accessor :status, :tasks
|
|
22
21
|
attr_accessor :backtrace
|
|
23
22
|
|
|
24
23
|
def dump
|
|
25
24
|
string = ""
|
|
26
|
-
string << "Celluloid::Actor 0x#{
|
|
25
|
+
string << "Celluloid::Actor 0x#{id.to_s(16)}"
|
|
27
26
|
string << " [#{name}]" if name
|
|
28
27
|
string << "\n"
|
|
29
28
|
|
|
29
|
+
if cell
|
|
30
|
+
string << cell.dump
|
|
31
|
+
string << "\n"
|
|
32
|
+
end
|
|
33
|
+
|
|
30
34
|
if status == :idle
|
|
31
35
|
string << "State: Idle (waiting for messages)\n"
|
|
32
36
|
display_backtrace backtrace, string
|
|
@@ -46,12 +50,18 @@ module Celluloid
|
|
|
46
50
|
end
|
|
47
51
|
end
|
|
48
52
|
|
|
49
|
-
class
|
|
53
|
+
class CellState < Struct.new(:subject_id, :subject_class)
|
|
54
|
+
def dump
|
|
55
|
+
"Celluloid::Cell 0x#{subject_id.to_s(16)}: #{subject_class}"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class ThreadState < Struct.new(:thread_id, :backtrace, :role)
|
|
50
60
|
include DisplayBacktrace
|
|
51
61
|
|
|
52
62
|
def dump
|
|
53
63
|
string = ""
|
|
54
|
-
string << "Thread 0x#{thread_id.to_s(16)}:\n"
|
|
64
|
+
string << "Thread 0x#{thread_id.to_s(16)} (#{role}):\n"
|
|
55
65
|
display_backtrace backtrace, string
|
|
56
66
|
string
|
|
57
67
|
end
|
|
@@ -59,7 +69,9 @@ module Celluloid
|
|
|
59
69
|
|
|
60
70
|
attr_accessor :actors, :threads
|
|
61
71
|
|
|
62
|
-
def initialize
|
|
72
|
+
def initialize(internal_pool)
|
|
73
|
+
@internal_pool = internal_pool
|
|
74
|
+
|
|
63
75
|
@actors = []
|
|
64
76
|
@threads = []
|
|
65
77
|
|
|
@@ -67,7 +79,7 @@ module Celluloid
|
|
|
67
79
|
end
|
|
68
80
|
|
|
69
81
|
def snapshot
|
|
70
|
-
|
|
82
|
+
@internal_pool.each do |thread|
|
|
71
83
|
if thread.role == :actor
|
|
72
84
|
@actors << snapshot_actor(thread.actor) if thread.actor
|
|
73
85
|
else
|
|
@@ -78,8 +90,12 @@ module Celluloid
|
|
|
78
90
|
|
|
79
91
|
def snapshot_actor(actor)
|
|
80
92
|
state = ActorState.new
|
|
81
|
-
state.
|
|
82
|
-
|
|
93
|
+
state.id = actor.object_id
|
|
94
|
+
|
|
95
|
+
# TODO: delegate to the behavior
|
|
96
|
+
if actor.behavior.is_a?(Cell)
|
|
97
|
+
state.cell = snapshot_cell(actor.behavior)
|
|
98
|
+
end
|
|
83
99
|
|
|
84
100
|
tasks = actor.tasks
|
|
85
101
|
if tasks.empty?
|
|
@@ -93,11 +109,18 @@ module Celluloid
|
|
|
93
109
|
state
|
|
94
110
|
end
|
|
95
111
|
|
|
112
|
+
def snapshot_cell(behavior)
|
|
113
|
+
state = CellState.new
|
|
114
|
+
state.subject_id = behavior.subject.object_id
|
|
115
|
+
state.subject_class = behavior.subject.class
|
|
116
|
+
state
|
|
117
|
+
end
|
|
118
|
+
|
|
96
119
|
def snapshot_thread(thread)
|
|
97
|
-
ThreadState.new(thread.object_id, thread.backtrace)
|
|
120
|
+
ThreadState.new(thread.object_id, thread.backtrace, thread.role)
|
|
98
121
|
end
|
|
99
122
|
|
|
100
|
-
def
|
|
123
|
+
def print(output = STDERR)
|
|
101
124
|
@actors.each do |actor|
|
|
102
125
|
output.print actor.dump
|
|
103
126
|
end
|
|
@@ -5,6 +5,7 @@ module Celluloid
|
|
|
5
5
|
trap_exit :restart_actor
|
|
6
6
|
|
|
7
7
|
class << self
|
|
8
|
+
|
|
8
9
|
# Actors or sub-applications to be supervised
|
|
9
10
|
def blocks
|
|
10
11
|
@blocks ||= []
|
|
@@ -55,10 +56,12 @@ module Celluloid
|
|
|
55
56
|
end
|
|
56
57
|
end
|
|
57
58
|
|
|
59
|
+
finalizer :finalize
|
|
60
|
+
|
|
58
61
|
# Start the group
|
|
59
62
|
def initialize(registry = nil)
|
|
60
63
|
@members = []
|
|
61
|
-
@registry = registry ||
|
|
64
|
+
@registry = registry || Celluloid.actor_system.registry
|
|
62
65
|
|
|
63
66
|
yield current_actor if block_given?
|
|
64
67
|
end
|
|
@@ -81,18 +84,15 @@ module Celluloid
|
|
|
81
84
|
def add(klass, options)
|
|
82
85
|
member = Member.new(@registry, klass, options)
|
|
83
86
|
@members << member
|
|
84
|
-
member
|
|
87
|
+
member.actor
|
|
85
88
|
end
|
|
86
89
|
|
|
87
90
|
def actors
|
|
88
91
|
@members.map(&:actor)
|
|
89
92
|
end
|
|
90
93
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
# Terminate the group
|
|
94
|
-
def finalize
|
|
95
|
-
@members.reverse_each(&:terminate)
|
|
94
|
+
def [](actor_name)
|
|
95
|
+
@registry[actor_name]
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
# Restart a crashed actor
|
|
@@ -102,7 +102,12 @@ module Celluloid
|
|
|
102
102
|
end
|
|
103
103
|
raise "a group member went missing. This shouldn't be!" unless member
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
if reason
|
|
106
|
+
member.restart
|
|
107
|
+
else
|
|
108
|
+
member.cleanup
|
|
109
|
+
@members.delete(member)
|
|
110
|
+
end
|
|
106
111
|
end
|
|
107
112
|
|
|
108
113
|
# A member of the group
|
|
@@ -137,21 +142,28 @@ module Celluloid
|
|
|
137
142
|
@registry[@name] = @actor if @name
|
|
138
143
|
end
|
|
139
144
|
|
|
140
|
-
def restart
|
|
145
|
+
def restart
|
|
141
146
|
@actor = nil
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
# Ignore supervisors that shut down cleanly
|
|
145
|
-
return unless reason
|
|
147
|
+
cleanup
|
|
146
148
|
|
|
147
149
|
start
|
|
148
150
|
end
|
|
149
151
|
|
|
150
152
|
def terminate
|
|
151
|
-
|
|
153
|
+
cleanup
|
|
152
154
|
@actor.terminate if @actor
|
|
153
155
|
rescue DeadActorError
|
|
154
156
|
end
|
|
157
|
+
|
|
158
|
+
def cleanup
|
|
159
|
+
@registry.delete(@name) if @name
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
private
|
|
164
|
+
|
|
165
|
+
def finalize
|
|
166
|
+
@members.reverse_each(&:terminate) if @members
|
|
155
167
|
end
|
|
156
168
|
end
|
|
157
169
|
end
|
|
@@ -6,10 +6,12 @@ module Celluloid
|
|
|
6
6
|
|
|
7
7
|
def create
|
|
8
8
|
queue = Thread.current[:celluloid_queue]
|
|
9
|
+
actor_system = Thread.current[:celluloid_actor_system]
|
|
9
10
|
@fiber = Fiber.new do
|
|
10
11
|
# FIXME: cannot use the writer as specs run inside normal Threads
|
|
11
12
|
Thread.current[:celluloid_role] = :actor
|
|
12
13
|
Thread.current[:celluloid_queue] = queue
|
|
14
|
+
Thread.current[:celluloid_actor_system] = actor_system
|
|
13
15
|
yield
|
|
14
16
|
end
|
|
15
17
|
end
|
|
@@ -33,5 +35,9 @@ module Celluloid
|
|
|
33
35
|
rescue FiberError
|
|
34
36
|
# If we're getting this the task should already be dead
|
|
35
37
|
end
|
|
38
|
+
|
|
39
|
+
def backtrace
|
|
40
|
+
["#{self.class} backtrace unavailable. Please try `Celluloid.task_class = Celluloid::TaskThread` if you need backtraces here."]
|
|
41
|
+
end
|
|
36
42
|
end
|
|
37
43
|
end
|
|
@@ -12,7 +12,8 @@ module Celluloid
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def create
|
|
15
|
-
|
|
15
|
+
# TODO: move this to ActorSystem#get_thread (ThreadHandle inside InternalPool)
|
|
16
|
+
@thread = ThreadHandle.new(Thread.current[:celluloid_actor_system], :task) do
|
|
16
17
|
begin
|
|
17
18
|
ex = @resume_queue.pop
|
|
18
19
|
raise ex if ex.is_a?(Task::TerminatedError)
|
data/lib/celluloid/tasks.rb
CHANGED
|
@@ -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
|
|
@@ -74,14 +77,9 @@ module Celluloid
|
|
|
74
77
|
@status = status
|
|
75
78
|
|
|
76
79
|
if $CELLULOID_DEBUG && @dangerous_suspend
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
"meta=#{@meta.inspect}",
|
|
81
|
-
"status=#{@status.inspect}"
|
|
82
|
-
].join(", ")
|
|
83
|
-
|
|
84
|
-
Logger.warn [warning, *caller[2..8]].join("\n\t")
|
|
80
|
+
Logger.with_backtrace(caller[2...8]) do |logger|
|
|
81
|
+
logger.warn "Dangerously suspending task: type=#{@type.inspect}, meta=#{@meta.inspect}, status=#{@status.inspect}"
|
|
82
|
+
end
|
|
85
83
|
end
|
|
86
84
|
|
|
87
85
|
value = signal
|
|
@@ -118,7 +116,9 @@ module Celluloid
|
|
|
118
116
|
raise "Cannot terminate an exclusive task" if exclusive?
|
|
119
117
|
|
|
120
118
|
if running?
|
|
121
|
-
|
|
119
|
+
Logger.with_backtrace(backtrace) do |logger|
|
|
120
|
+
logger.warn "Terminating task: type=#{@type.inspect}, meta=#{@meta.inspect}, status=#{@status.inspect}"
|
|
121
|
+
end
|
|
122
122
|
exception = Task::TerminatedError.new("task was terminated")
|
|
123
123
|
exception.set_backtrace(caller)
|
|
124
124
|
resume exception
|
|
@@ -150,6 +150,25 @@ module Celluloid
|
|
|
150
150
|
raise message if $CELLULOID_DEBUG
|
|
151
151
|
end
|
|
152
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
|
|
153
172
|
end
|
|
154
173
|
end
|
|
155
174
|
|
|
@@ -3,11 +3,11 @@ module Celluloid
|
|
|
3
3
|
# accidentally do things to threads which have been returned to the pool,
|
|
4
4
|
# such as, say, killing them
|
|
5
5
|
class ThreadHandle
|
|
6
|
-
def initialize(role = nil)
|
|
6
|
+
def initialize(actor_system, role = nil)
|
|
7
7
|
@mutex = Mutex.new
|
|
8
8
|
@join = ConditionVariable.new
|
|
9
9
|
|
|
10
|
-
@thread =
|
|
10
|
+
@thread = actor_system.get_thread do
|
|
11
11
|
Thread.current.role = role
|
|
12
12
|
begin
|
|
13
13
|
yield
|