celluloid 0.15.2 → 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/LICENSE.txt +20 -0
- data/README.md +25 -2
- data/lib/celluloid/actor.rb +86 -133
- 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 +8 -15
- 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 +0 -3
- data/lib/celluloid/logger.rb +30 -0
- data/lib/celluloid/logging/incident_logger.rb +1 -1
- data/lib/celluloid/mailbox.rb +19 -18
- 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 +3 -1
- 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 +6 -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/spec_helper.rb +20 -7
- data/spec/support/actor_examples.rb +33 -15
- data/spec/support/mailbox_examples.rb +9 -3
- data/spec/support/task_examples.rb +2 -0
- metadata +46 -22
|
@@ -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,4 +1,5 @@
|
|
|
1
1
|
require 'set'
|
|
2
|
+
|
|
2
3
|
require 'timers'
|
|
3
4
|
|
|
4
5
|
module Celluloid
|
|
@@ -6,7 +7,7 @@ module Celluloid
|
|
|
6
7
|
class Receivers
|
|
7
8
|
def initialize
|
|
8
9
|
@receivers = Set.new
|
|
9
|
-
@timers = Timers.new
|
|
10
|
+
@timers = Timers::Group.new
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
# Receive an asynchronous message
|
|
@@ -46,6 +47,7 @@ module Celluloid
|
|
|
46
47
|
@receivers.delete receiver
|
|
47
48
|
@timers.cancel receiver.timer if receiver.timer
|
|
48
49
|
receiver.resume message
|
|
50
|
+
message
|
|
49
51
|
end
|
|
50
52
|
end
|
|
51
53
|
|
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
|
@@ -74,14 +74,9 @@ module Celluloid
|
|
|
74
74
|
@status = status
|
|
75
75
|
|
|
76
76
|
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")
|
|
77
|
+
Logger.with_backtrace(caller[2...8]) do |logger|
|
|
78
|
+
logger.warn "Dangerously suspending task: type=#{@type.inspect}, meta=#{@meta.inspect}, status=#{@status.inspect}"
|
|
79
|
+
end
|
|
85
80
|
end
|
|
86
81
|
|
|
87
82
|
value = signal
|
|
@@ -118,7 +113,9 @@ module Celluloid
|
|
|
118
113
|
raise "Cannot terminate an exclusive task" if exclusive?
|
|
119
114
|
|
|
120
115
|
if running?
|
|
121
|
-
|
|
116
|
+
Logger.with_backtrace(backtrace) do |logger|
|
|
117
|
+
logger.warn "Terminating task: type=#{@type.inspect}, meta=#{@meta.inspect}, status=#{@status.inspect}"
|
|
118
|
+
end
|
|
122
119
|
exception = Task::TerminatedError.new("task was terminated")
|
|
123
120
|
exception.set_backtrace(caller)
|
|
124
121
|
resume exception
|
|
@@ -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
|
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.pre2'
|
|
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)
|