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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +20 -0
  3. data/README.md +25 -2
  4. data/lib/celluloid/actor.rb +88 -147
  5. data/lib/celluloid/actor_system.rb +107 -0
  6. data/lib/celluloid/call_chain.rb +1 -1
  7. data/lib/celluloid/calls.rb +16 -16
  8. data/lib/celluloid/cell.rb +89 -0
  9. data/lib/celluloid/condition.rb +25 -8
  10. data/lib/celluloid/cpu_counter.rb +27 -18
  11. data/lib/celluloid/evented_mailbox.rb +10 -16
  12. data/lib/celluloid/exceptions.rb +23 -0
  13. data/lib/celluloid/future.rb +1 -1
  14. data/lib/celluloid/handlers.rb +41 -0
  15. data/lib/celluloid/internal_pool.rb +49 -40
  16. data/lib/celluloid/logger.rb +30 -0
  17. data/lib/celluloid/logging/incident_logger.rb +1 -1
  18. data/lib/celluloid/mailbox.rb +35 -31
  19. data/lib/celluloid/method.rb +8 -0
  20. data/lib/celluloid/pool_manager.rb +19 -2
  21. data/lib/celluloid/probe.rb +73 -0
  22. data/lib/celluloid/properties.rb +2 -2
  23. data/lib/celluloid/proxies/actor_proxy.rb +9 -41
  24. data/lib/celluloid/proxies/cell_proxy.rb +68 -0
  25. data/lib/celluloid/proxies/sync_proxy.rb +1 -1
  26. data/lib/celluloid/receivers.rb +5 -13
  27. data/lib/celluloid/registry.rb +1 -8
  28. data/lib/celluloid/stack_dump.rb +34 -11
  29. data/lib/celluloid/supervision_group.rb +26 -14
  30. data/lib/celluloid/tasks/task_fiber.rb +6 -0
  31. data/lib/celluloid/tasks/task_thread.rb +2 -1
  32. data/lib/celluloid/tasks.rb +28 -9
  33. data/lib/celluloid/thread_handle.rb +2 -2
  34. data/lib/celluloid.rb +68 -73
  35. data/spec/celluloid/actor_spec.rb +1 -1
  36. data/spec/celluloid/actor_system_spec.rb +69 -0
  37. data/spec/celluloid/block_spec.rb +1 -1
  38. data/spec/celluloid/calls_spec.rb +1 -1
  39. data/spec/celluloid/condition_spec.rb +14 -3
  40. data/spec/celluloid/cpu_counter_spec.rb +82 -0
  41. data/spec/celluloid/fsm_spec.rb +1 -1
  42. data/spec/celluloid/future_spec.rb +1 -1
  43. data/spec/celluloid/notifications_spec.rb +1 -1
  44. data/spec/celluloid/pool_spec.rb +34 -1
  45. data/spec/celluloid/probe_spec.rb +121 -0
  46. data/spec/celluloid/registry_spec.rb +6 -6
  47. data/spec/celluloid/stack_dump_spec.rb +37 -8
  48. data/spec/celluloid/supervision_group_spec.rb +7 -1
  49. data/spec/celluloid/supervisor_spec.rb +12 -1
  50. data/spec/celluloid/tasks/task_fiber_spec.rb +1 -1
  51. data/spec/celluloid/tasks/task_thread_spec.rb +1 -1
  52. data/spec/celluloid/thread_handle_spec.rb +7 -3
  53. data/spec/celluloid/timer_spec.rb +48 -0
  54. data/spec/spec_helper.rb +20 -7
  55. data/spec/support/actor_examples.rb +58 -15
  56. data/spec/support/mailbox_examples.rb +9 -3
  57. data/spec/support/task_examples.rb +2 -0
  58. 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
@@ -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 object returned from Celluloid::Actor.new/new_link which converts
3
- # the normal Ruby method protocol into an inter-actor message protocol
4
- class ActorProxy < SyncProxy
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(actor)
11
- @thread = actor.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
- method_missing :inspect
15
+ # TODO: use a system event to fetch actor state: tasks?
16
+ "#<Celluloid::ActorProxy(#{@mailbox.address}) alive>"
25
17
  rescue DeadActorError
26
- "#<Celluloid::ActorProxy(#{@klass}) dead>"
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) || super
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)
@@ -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,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
- @timers.cancel receiver.timer if receiver.timer
38
+ receiver.timer.cancel if receiver.timer
48
39
  receiver.resume message
40
+ message
49
41
  end
50
42
  end
51
43
 
@@ -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? ActorProxy
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
@@ -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#{subject_id.to_s(16)}: #{subject_class}"
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 ThreadState < Struct.new(:thread_id, :backtrace)
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
- Celluloid.internal_pool.each do |thread|
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.subject_id = actor.subject.object_id
82
- state.subject_class = actor.subject.class
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 dump(output = STDERR)
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 || Registry.root
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
- finalizer :finalize
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
- member.restart(reason)
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(reason)
145
+ def restart
141
146
  @actor = nil
142
- @registry.delete(@name) if @name
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
- @registry.delete(@name) if @name
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
- @thread = Celluloid::ThreadHandle.new(:task) do
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)
@@ -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
- warning = "Dangerously suspending task: "
78
- warning << [
79
- "type=#{@type.inspect}",
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
- Celluloid.logger.warn "Terminating task: type=#{@type.inspect}, meta=#{@meta.inspect}, status=#{@status.inspect}"
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 = Celluloid.internal_pool.get do
10
+ @thread = actor_system.get_thread do
11
11
  Thread.current.role = role
12
12
  begin
13
13
  yield