celluloid 0.15.2 → 0.16.0.pre
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 +29 -2
- data/lib/celluloid.rb +68 -73
- data/lib/celluloid/actor.rb +69 -123
- data/lib/celluloid/actor_system.rb +107 -0
- 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 +2 -0
- data/lib/celluloid/evented_mailbox.rb +2 -1
- 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 +1 -1
- 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 +1 -0
- 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.rb +6 -9
- data/lib/celluloid/tasks/task_fiber.rb +6 -0
- data/lib/celluloid/tasks/task_thread.rb +2 -1
- data/lib/celluloid/thread_handle.rb +2 -2
- 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 +9 -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 +1 -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 +32 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f9e4bf5d8e26e99c5321bc02c61cafa9de48600
|
4
|
+
data.tar.gz: b239f25215d8c3ca0c9c27cd3e08954fa62ee35c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be0d373d83500400c1135176382097f8bdffeb378fbce48f95852195975984a626221292ade6182ba84cc5a9ca06fa0849461d28c68e9adea33c129396ab39a3
|
7
|
+
data.tar.gz: 6f6cd39aec05a5b8f4b461ad88cd6c960a37d5832ca36ee5f633bf0e3229b294fb714668dcf87d843e162749507c301d14d32d2ae2d344c726b3f55346f9e6c8
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011-2014 Tony Arcieri
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -94,6 +94,28 @@ The following API documentation is also available:
|
|
94
94
|
* [Celluloid class methods](http://rubydoc.info/gems/celluloid/Celluloid/ClassMethods)
|
95
95
|
* [All Celluloid classes](http://rubydoc.info/gems/celluloid/index)
|
96
96
|
|
97
|
+
Related Projects
|
98
|
+
----------------
|
99
|
+
|
100
|
+
Celluloid is the parent project of a related ecosystem of other projects. If you
|
101
|
+
like Celluloid we definitely recommend you check them out:
|
102
|
+
|
103
|
+
* [Celluloid::IO][celluloid-io]: "Evented" IO support for Celluloid actors
|
104
|
+
* [Celluloid::ZMQ][celluloid-zmq]: "Evented" 0MQ support for Celluloid actors
|
105
|
+
* [DCell][dcell]: The Celluloid actor protocol distributed over 0MQ
|
106
|
+
* [Reel][reel]: An "evented" web server based on Celluloid::IO
|
107
|
+
* [Lattice][lattice]: A concurrent realtime web framework based on Celluloid::IO
|
108
|
+
* [nio4r][nio4r]: "New IO for Ruby": high performance IO selectors
|
109
|
+
* [Timers][timers]: A generic Ruby timer library for event-based systems
|
110
|
+
|
111
|
+
[celluloid-io]: https://github.com/celluloid/celluloid-io/
|
112
|
+
[celluloid-zmq]: https://github.com/celluloid/celluloid-zmq/
|
113
|
+
[dcell]: https://github.com/celluloid/dcell/
|
114
|
+
[reel]: https://github.com/celluloid/reel/
|
115
|
+
[lattice]: https://github.com/celluloid/lattice/
|
116
|
+
[nio4r]: https://github.com/celluloid/nio4r/
|
117
|
+
[timers]: https://github.com/celluloid/timers/
|
118
|
+
|
97
119
|
Installation
|
98
120
|
------------
|
99
121
|
|
@@ -131,7 +153,8 @@ Celluloid requires Ruby 1.9 mode on all interpreters.
|
|
131
153
|
Additional Reading
|
132
154
|
------------------
|
133
155
|
|
134
|
-
* [Concurrent Object-Oriented Programming in Python with
|
156
|
+
* [Concurrent Object-Oriented Programming in Python with
|
157
|
+
ATOM](http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=11A3EACE78AAFF6D6D62A64118AFCA7C?doi=10.1.1.47.5074&rep=rep1&type=pdf):
|
135
158
|
a similar system to Celluloid written in Python
|
136
159
|
|
137
160
|
Contributing to Celluloid
|
@@ -145,5 +168,9 @@ Contributing to Celluloid
|
|
145
168
|
License
|
146
169
|
-------
|
147
170
|
|
148
|
-
Copyright (c)
|
171
|
+
Copyright (c) 2011-2014 Tony Arcieri. Distributed under the MIT License. See
|
149
172
|
LICENSE.txt for further details.
|
173
|
+
|
174
|
+
|
175
|
+
[](https://bitdeli.com/free "Bitdeli Badge")
|
176
|
+
|
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.pre'
|
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)
|
data/lib/celluloid/actor.rb
CHANGED
@@ -1,56 +1,27 @@
|
|
1
1
|
require 'timers'
|
2
2
|
|
3
3
|
module Celluloid
|
4
|
-
# Don't do Actor-like things outside Actor scope
|
5
|
-
class NotActorError < Celluloid::Error; end
|
6
|
-
|
7
|
-
# Trying to do something to a dead actor
|
8
|
-
class DeadActorError < Celluloid::Error; end
|
9
|
-
|
10
|
-
# A timeout occured before the given request could complete
|
11
|
-
class TimeoutError < Celluloid::Error; end
|
12
|
-
|
13
|
-
# The sender made an error, not the current actor
|
14
|
-
class AbortError < Celluloid::Error
|
15
|
-
attr_reader :cause
|
16
|
-
|
17
|
-
def initialize(cause)
|
18
|
-
@cause = cause
|
19
|
-
super "caused by #{cause.inspect}: #{cause.to_s}"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
LINKING_TIMEOUT = 5 # linking times out after 5 seconds
|
24
|
-
OWNER_IVAR = :@celluloid_owner # reference to owning actor
|
25
|
-
|
26
4
|
# Actors are Celluloid's concurrency primitive. They're implemented as
|
27
5
|
# normal Ruby objects wrapped in threads which communicate with asynchronous
|
28
6
|
# messages.
|
29
7
|
class Actor
|
30
|
-
attr_reader :
|
8
|
+
attr_reader :behavior, :proxy, :tasks, :links, :mailbox, :thread, :name, :timers
|
9
|
+
attr_writer :exit_handler
|
31
10
|
|
32
11
|
class << self
|
33
12
|
extend Forwardable
|
34
13
|
|
35
|
-
def_delegators "Celluloid
|
36
|
-
|
37
|
-
def registered
|
38
|
-
Registry.root.names
|
39
|
-
end
|
40
|
-
|
41
|
-
def clear_registry
|
42
|
-
Registry.root.clear
|
43
|
-
end
|
14
|
+
def_delegators "Celluloid.actor_system", :[], :[]=, :delete, :registered, :clear_registry
|
44
15
|
|
45
16
|
# Obtain the current actor
|
46
17
|
def current
|
47
18
|
actor = Thread.current[:celluloid_actor]
|
48
19
|
raise NotActorError, "not in actor scope" unless actor
|
49
|
-
actor.
|
20
|
+
actor.behavior_proxy
|
50
21
|
end
|
51
22
|
|
52
23
|
# Obtain the name of the current actor
|
53
|
-
def
|
24
|
+
def registered_name
|
54
25
|
actor = Thread.current[:celluloid_actor]
|
55
26
|
raise NotActorError, "not in actor scope" unless actor
|
56
27
|
actor.name
|
@@ -76,12 +47,7 @@ module Celluloid
|
|
76
47
|
|
77
48
|
# Obtain all running actors in the system
|
78
49
|
def all
|
79
|
-
|
80
|
-
Celluloid.internal_pool.each do |t|
|
81
|
-
next unless t.role == :actor
|
82
|
-
actors << t.actor.proxy if t.actor && t.actor.respond_to?(:proxy)
|
83
|
-
end
|
84
|
-
actors
|
50
|
+
Celluloid.actor_system.running
|
85
51
|
end
|
86
52
|
|
87
53
|
# Watch for exit events from another actor
|
@@ -131,34 +97,44 @@ module Celluloid
|
|
131
97
|
end
|
132
98
|
end
|
133
99
|
|
134
|
-
|
135
|
-
|
136
|
-
@subject = subject
|
100
|
+
def initialize(behavior, options)
|
101
|
+
@behavior = behavior
|
137
102
|
|
103
|
+
@actor_system = options.fetch(:actor_system)
|
138
104
|
@mailbox = options.fetch(:mailbox_class, Mailbox).new
|
139
105
|
@mailbox.max_size = options.fetch(:mailbox_size, nil)
|
140
106
|
|
141
107
|
@task_class = options[:task_class] || Celluloid.task_class
|
142
|
-
@exit_handler =
|
143
|
-
@
|
144
|
-
@receiver_block_executions = options[:receiver_block_executions]
|
108
|
+
@exit_handler = method(:default_exit_handler)
|
109
|
+
@exclusive = options.fetch(:exclusive, false)
|
145
110
|
|
146
111
|
@tasks = TaskSet.new
|
147
112
|
@links = Links.new
|
148
113
|
@signals = Signals.new
|
149
114
|
@receivers = Receivers.new
|
150
115
|
@timers = Timers.new
|
151
|
-
@
|
152
|
-
@
|
116
|
+
@handlers = Handlers.new
|
117
|
+
@running = false
|
153
118
|
@name = nil
|
154
119
|
|
155
|
-
|
120
|
+
handle(SystemEvent) do |message|
|
121
|
+
handle_system_event message
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def start
|
126
|
+
@running = true
|
127
|
+
@thread = ThreadHandle.new(@actor_system, :actor) do
|
156
128
|
setup_thread
|
157
129
|
run
|
158
130
|
end
|
159
131
|
|
160
|
-
@proxy =
|
161
|
-
|
132
|
+
@proxy = ActorProxy.new(@thread, @mailbox)
|
133
|
+
Celluloid::Probe.actor_created(self) if $CELLULOID_MONITORING
|
134
|
+
end
|
135
|
+
|
136
|
+
def behavior_proxy
|
137
|
+
@behavior.proxy
|
162
138
|
end
|
163
139
|
|
164
140
|
def setup_thread
|
@@ -168,18 +144,16 @@ module Celluloid
|
|
168
144
|
|
169
145
|
# Run the actor loop
|
170
146
|
def run
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
147
|
+
while @running
|
148
|
+
begin
|
149
|
+
message = @mailbox.receive(timeout_interval)
|
150
|
+
handle_message message
|
151
|
+
rescue TimeoutError
|
152
|
+
@timers.fire
|
153
|
+
@receivers.fire_timers
|
154
|
+
rescue MailboxShutdown
|
155
|
+
@running = false
|
180
156
|
end
|
181
|
-
rescue MailboxShutdown
|
182
|
-
# If the mailbox detects shutdown, exit the actor
|
183
157
|
end
|
184
158
|
|
185
159
|
shutdown
|
@@ -208,14 +182,14 @@ module Celluloid
|
|
208
182
|
msg.type == type
|
209
183
|
end
|
210
184
|
|
211
|
-
|
212
|
-
|
185
|
+
if message.instance_of? LinkingResponse
|
186
|
+
Celluloid::Probe.actors_linked(self, receiver) if $CELLULOID_MONITORING
|
213
187
|
# We're done!
|
214
|
-
system_events.each { |ev|
|
188
|
+
system_events.each { |ev| @mailbox << ev }
|
215
189
|
return
|
216
|
-
|
190
|
+
elsif message.instance_of? NilClass
|
217
191
|
raise TimeoutError, "linking timeout of #{LINKING_TIMEOUT} seconds exceeded"
|
218
|
-
|
192
|
+
elsif message.instance_of? SystemEvent
|
219
193
|
# Queue up pending system events to be processed after we've successfully linked
|
220
194
|
system_events << message
|
221
195
|
else raise 'wtf'
|
@@ -234,6 +208,10 @@ module Celluloid
|
|
234
208
|
@signals.wait name
|
235
209
|
end
|
236
210
|
|
211
|
+
def handle(*patterns, &block)
|
212
|
+
@handlers.handle(*patterns, &block)
|
213
|
+
end
|
214
|
+
|
237
215
|
# Receive an asynchronous message
|
238
216
|
def receive(timeout = nil, &block)
|
239
217
|
loop do
|
@@ -304,28 +282,7 @@ module Celluloid
|
|
304
282
|
|
305
283
|
# Handle standard low-priority messages
|
306
284
|
def handle_message(message)
|
307
|
-
|
308
|
-
when SystemEvent
|
309
|
-
handle_system_event message
|
310
|
-
when Call
|
311
|
-
meth = message.method
|
312
|
-
if meth == :__send__
|
313
|
-
meth = message.arguments.first
|
314
|
-
end
|
315
|
-
if @receiver_block_executions && meth
|
316
|
-
if @receiver_block_executions.include?(meth.to_sym)
|
317
|
-
message.execute_block_on_receiver
|
318
|
-
end
|
319
|
-
end
|
320
|
-
|
321
|
-
task(:call, :method_name => meth, :dangerous_suspend => meth == :initialize) {
|
322
|
-
message.dispatch(@subject)
|
323
|
-
}
|
324
|
-
when BlockCall
|
325
|
-
task(:invoke_block) { message.dispatch }
|
326
|
-
when BlockResponse, Response
|
327
|
-
message.dispatch
|
328
|
-
else
|
285
|
+
unless @handlers.handle_message(message)
|
329
286
|
unless @receivers.handle_message(message)
|
330
287
|
Logger.debug "Discarded message (unhandled): #{message}" if $CELLULOID_DEBUG
|
331
288
|
end
|
@@ -335,17 +292,19 @@ module Celluloid
|
|
335
292
|
|
336
293
|
# Handle high-priority system event messages
|
337
294
|
def handle_system_event(event)
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
when LinkingRequest
|
295
|
+
if event.instance_of? ExitEvent
|
296
|
+
handle_exit_event(event)
|
297
|
+
elsif event.instance_of? LinkingRequest
|
342
298
|
event.process(links)
|
343
|
-
|
299
|
+
elsif event.instance_of? NamingRequest
|
344
300
|
@name = event.name
|
345
|
-
|
301
|
+
Celluloid::Probe.actor_named(self) if $CELLULOID_MONITORING
|
302
|
+
elsif event.instance_of? TerminationRequest
|
346
303
|
terminate
|
347
|
-
|
304
|
+
elsif event.instance_of? SignalConditionRequest
|
348
305
|
event.call
|
306
|
+
else
|
307
|
+
Logger.debug "Discarded message (unhandled): #{message}" if $CELLULOID_DEBUG
|
349
308
|
end
|
350
309
|
end
|
351
310
|
|
@@ -353,47 +312,34 @@ module Celluloid
|
|
353
312
|
def handle_exit_event(event)
|
354
313
|
@links.delete event.actor
|
355
314
|
|
356
|
-
|
357
|
-
|
315
|
+
@exit_handler.call(event)
|
316
|
+
end
|
358
317
|
|
359
|
-
|
360
|
-
# If no reason is given, actor terminated cleanly
|
318
|
+
def default_exit_handler(event)
|
361
319
|
raise event.reason if event.reason
|
362
320
|
end
|
363
321
|
|
364
322
|
# Handle any exceptions that occur within a running actor
|
365
323
|
def handle_crash(exception)
|
366
|
-
|
367
|
-
|
324
|
+
# TODO: add meta info
|
325
|
+
Logger.crash("Actor crashed!", exception)
|
326
|
+
shutdown ExitEvent.new(behavior_proxy, exception)
|
368
327
|
rescue => ex
|
369
|
-
Logger.crash("
|
328
|
+
Logger.crash("ERROR HANDLER CRASHED!", ex)
|
370
329
|
end
|
371
330
|
|
372
331
|
# Handle cleaning up this actor after it exits
|
373
|
-
def shutdown(exit_event = ExitEvent.new(
|
374
|
-
|
332
|
+
def shutdown(exit_event = ExitEvent.new(behavior_proxy))
|
333
|
+
@behavior.shutdown
|
375
334
|
cleanup exit_event
|
376
335
|
ensure
|
377
336
|
Thread.current[:celluloid_actor] = nil
|
378
337
|
Thread.current[:celluloid_mailbox] = nil
|
379
338
|
end
|
380
339
|
|
381
|
-
# Run the user-defined finalizer, if one is set
|
382
|
-
def run_finalizer
|
383
|
-
finalizer = @subject.class.finalizer
|
384
|
-
return unless finalizer && @subject.respond_to?(finalizer, true)
|
385
|
-
|
386
|
-
task(:finalizer, :method_name => finalizer, :dangerous_suspend => true) do
|
387
|
-
begin
|
388
|
-
@subject.__send__(finalizer)
|
389
|
-
rescue => ex
|
390
|
-
Logger.crash("#{@subject.class}#finalize crashed!", ex)
|
391
|
-
end
|
392
|
-
end
|
393
|
-
end
|
394
|
-
|
395
340
|
# Clean up after this actor
|
396
341
|
def cleanup(exit_event)
|
342
|
+
Celluloid::Probe.actor_died(self) if $CELLULOID_MONITORING
|
397
343
|
@mailbox.shutdown
|
398
344
|
@links.each do |actor|
|
399
345
|
if actor.mailbox.alive?
|
@@ -401,16 +347,16 @@ module Celluloid
|
|
401
347
|
end
|
402
348
|
end
|
403
349
|
|
404
|
-
tasks.to_a.each
|
350
|
+
tasks.to_a.each(&:terminate)
|
405
351
|
rescue => ex
|
406
|
-
|
352
|
+
# TODO: metadata
|
353
|
+
Logger.crash("CLEANUP CRASHED!", ex)
|
407
354
|
end
|
408
355
|
|
409
356
|
# Run a method inside a task unless it's exclusive
|
410
357
|
def task(task_type, meta = nil)
|
411
|
-
method_name = meta && meta.fetch(:method_name, nil)
|
412
358
|
@task_class.new(task_type, meta) {
|
413
|
-
if @
|
359
|
+
if @exclusive
|
414
360
|
Celluloid.exclusive { yield }
|
415
361
|
else
|
416
362
|
yield
|