celluloid 0.15.2 → 0.16.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/celluloid/celluloid/trend.png)](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
|