celluloid 0.6.0 → 0.6.1
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.
- data/README.md +34 -3
- data/lib/celluloid.rb +38 -29
- data/lib/celluloid/actor.rb +14 -26
- data/lib/celluloid/actor_proxy.rb +4 -0
- data/lib/celluloid/calls.rb +1 -1
- data/lib/celluloid/core_ext.rb +3 -9
- data/lib/celluloid/{fibers_are_hard.rb → fiber.rb} +31 -1
- data/lib/celluloid/io/reactor.rb +1 -1
- data/lib/celluloid/links.rb +61 -0
- data/lib/celluloid/mailbox.rb +3 -0
- data/lib/celluloid/receivers.rb +1 -1
- data/lib/celluloid/signals.rb +2 -4
- data/lib/celluloid/supervisor.rb +7 -2
- data/lib/celluloid/version.rb +1 -1
- metadata +25 -26
- data/lib/celluloid/linking.rb +0 -89
data/README.md
CHANGED
@@ -329,6 +329,35 @@ working, freshly-restarted version.
|
|
329
329
|
The main use of the registry is for interfacing with actors that are
|
330
330
|
automatically restarted by supervisors when they crash.
|
331
331
|
|
332
|
+
Applications
|
333
|
+
------------
|
334
|
+
|
335
|
+
Celluloid provides a DSL for describing all of the actors in a given
|
336
|
+
application. This lets you start a group of actors in one swoop and
|
337
|
+
also provides an additional level of supervision: applications supervise
|
338
|
+
the supervisors of all the actors in your system, an approach known
|
339
|
+
as supervision trees.
|
340
|
+
|
341
|
+
Define Celluloid::Applications with the following syntax:
|
342
|
+
|
343
|
+
class MyApplication < Celluloid::Application
|
344
|
+
supervise MyActor, :as => :my_actor
|
345
|
+
supervise AnotherActor, :as => :another_actor
|
346
|
+
end
|
347
|
+
|
348
|
+
This will start the MyActor and AnotherActor actors under a supervisor and
|
349
|
+
automatically register them as Celluloid::Actor[:my_actor] and
|
350
|
+
Celluloid::Actor[:another_actor].
|
351
|
+
|
352
|
+
To launch your application, do:
|
353
|
+
|
354
|
+
MyApplication.run
|
355
|
+
|
356
|
+
This launches your application in the foreground. To launch in in the
|
357
|
+
background, do:
|
358
|
+
|
359
|
+
MyApplication.run!
|
360
|
+
|
332
361
|
Signaling
|
333
362
|
---------
|
334
363
|
|
@@ -458,9 +487,11 @@ Here are a few rules you can follow to keep this from happening:
|
|
458
487
|
|
459
488
|
1. ***NEVER RETURN SELF*** (or pass self as an argument to other actors): in
|
460
489
|
cases where you want to pass an actor around to other actors or threads,
|
461
|
-
use Celluloid.current_actor
|
462
|
-
|
463
|
-
|
490
|
+
use Celluloid.current_actor, or if you're within an actor itself, you can
|
491
|
+
just call the #current_actor method. If you really need to get ahold of
|
492
|
+
"self" in order to add instance-specific behavior, e.g for metaprogramming
|
493
|
+
purposes or adding stubs during tests, call MyActor#wrapped_object to
|
494
|
+
obtain the actual object an actor is wrapping.
|
464
495
|
|
465
496
|
2. Don't mutate the state of objects you've sent in calls to other actors:
|
466
497
|
This means you must think about data in one of two different ways: either
|
data/lib/celluloid.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'logger'
|
2
2
|
require 'thread'
|
3
|
-
require 'celluloid/fibers_are_hard'
|
4
3
|
|
5
4
|
module Celluloid
|
6
5
|
@logger = Logger.new STDERR
|
@@ -9,8 +8,7 @@ module Celluloid
|
|
9
8
|
attr_accessor :logger # Thread-safe logger class
|
10
9
|
|
11
10
|
def included(klass)
|
12
|
-
klass.send :extend,
|
13
|
-
klass.send :include, Linking
|
11
|
+
klass.send :extend, ClassMethods
|
14
12
|
end
|
15
13
|
|
16
14
|
# Are we currently inside of an actor?
|
@@ -20,10 +18,10 @@ module Celluloid
|
|
20
18
|
|
21
19
|
# Obtain the currently running actor (if one exists)
|
22
20
|
def current_actor
|
23
|
-
actor = Thread.current[:
|
21
|
+
actor = Thread.current[:actor]
|
24
22
|
raise NotActorError, "not in actor scope" unless actor
|
25
23
|
|
26
|
-
actor
|
24
|
+
actor.proxy
|
27
25
|
end
|
28
26
|
|
29
27
|
# Receive an asynchronous message
|
@@ -32,33 +30,13 @@ module Celluloid
|
|
32
30
|
if actor
|
33
31
|
actor.receive(&block)
|
34
32
|
else
|
35
|
-
Thread.
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# Create a fiber that participates in the Celluloid protocol
|
40
|
-
def fiber(*args)
|
41
|
-
actor = Thread.current[:actor]
|
42
|
-
proxy = Thread.current[:actor_proxy]
|
43
|
-
mailbox = Thread.current[:mailbox]
|
44
|
-
|
45
|
-
Fiber.new do
|
46
|
-
Thread.current[:actor] = actor
|
47
|
-
Thread.current[:actor_proxy] = proxy
|
48
|
-
Thread.current[:mailbox] = mailbox
|
49
|
-
|
50
|
-
yield(*args)
|
33
|
+
Thread.mailbox.receive(&block)
|
51
34
|
end
|
52
35
|
end
|
53
36
|
|
54
37
|
# Resume a fiber that participates in the Celluloid protocol
|
55
38
|
def resume_fiber(fiber, value = nil)
|
56
|
-
|
57
|
-
if actor
|
58
|
-
actor.run_fiber fiber, value
|
59
|
-
else
|
60
|
-
fiber.resume value
|
61
|
-
end
|
39
|
+
fiber.resume value
|
62
40
|
end
|
63
41
|
end
|
64
42
|
|
@@ -74,7 +52,7 @@ module Celluloid
|
|
74
52
|
|
75
53
|
# Create a new actor and link to the current one
|
76
54
|
def new_link(*args, &block)
|
77
|
-
current_actor =
|
55
|
+
current_actor = Celluloid.current_actor
|
78
56
|
raise NotActorError, "can't link outside actor context" unless current_actor
|
79
57
|
|
80
58
|
proxy = Celluloid::Actor.new(allocate).proxy
|
@@ -165,6 +143,36 @@ module Celluloid
|
|
165
143
|
# be shared with at least the actor thread. Tread carefully.
|
166
144
|
def wrapped_object; self; end
|
167
145
|
|
146
|
+
# Obtain the Celluloid::Links for this actor
|
147
|
+
def links
|
148
|
+
Thread.current[:actor].links
|
149
|
+
end
|
150
|
+
|
151
|
+
# Link this actor to another, allowing it to crash or react to errors
|
152
|
+
def link(actor)
|
153
|
+
actor.notify_link current_actor
|
154
|
+
notify_link actor
|
155
|
+
end
|
156
|
+
|
157
|
+
# Remove links to another actor
|
158
|
+
def unlink(actor)
|
159
|
+
actor.notify_unlink current_actor
|
160
|
+
notify_unlink actor
|
161
|
+
end
|
162
|
+
|
163
|
+
def notify_link(actor)
|
164
|
+
links << actor
|
165
|
+
end
|
166
|
+
|
167
|
+
def notify_unlink(actor)
|
168
|
+
links.delete actor
|
169
|
+
end
|
170
|
+
|
171
|
+
# Is this actor linked to another?
|
172
|
+
def linked_to?(actor)
|
173
|
+
Thread.current[:actor].links.include? actor
|
174
|
+
end
|
175
|
+
|
168
176
|
# Receive an asynchronous message via the actor protocol
|
169
177
|
def receive(&block)
|
170
178
|
Celluloid.receive(&block)
|
@@ -207,7 +215,8 @@ require 'celluloid/actor_proxy'
|
|
207
215
|
require 'celluloid/calls'
|
208
216
|
require 'celluloid/core_ext'
|
209
217
|
require 'celluloid/events'
|
210
|
-
require 'celluloid/
|
218
|
+
require 'celluloid/fiber'
|
219
|
+
require 'celluloid/links'
|
211
220
|
require 'celluloid/mailbox'
|
212
221
|
require 'celluloid/receivers'
|
213
222
|
require 'celluloid/registry'
|
data/lib/celluloid/actor.rb
CHANGED
@@ -20,7 +20,6 @@ module Celluloid
|
|
20
20
|
# messages.
|
21
21
|
class Actor
|
22
22
|
extend Registry
|
23
|
-
include Linking
|
24
23
|
|
25
24
|
attr_reader :proxy
|
26
25
|
attr_reader :links
|
@@ -28,8 +27,7 @@ module Celluloid
|
|
28
27
|
|
29
28
|
# Invoke a method on the given actor via its mailbox
|
30
29
|
def self.call(mailbox, meth, *args, &block)
|
31
|
-
|
32
|
-
call = SyncCall.new(our_mailbox, meth, args, block)
|
30
|
+
call = SyncCall.new(Thread.mailbox, meth, args, block)
|
33
31
|
|
34
32
|
begin
|
35
33
|
mailbox << call
|
@@ -42,8 +40,8 @@ module Celluloid
|
|
42
40
|
response = Fiber.yield(call)
|
43
41
|
else
|
44
42
|
# Otherwise we're inside a normal thread, so block
|
45
|
-
response =
|
46
|
-
msg.
|
43
|
+
response = Thread.mailbox.receive do |msg|
|
44
|
+
msg.respond_to?(:call_id) and msg.call_id == call.id
|
47
45
|
end
|
48
46
|
end
|
49
47
|
|
@@ -52,9 +50,8 @@ module Celluloid
|
|
52
50
|
|
53
51
|
# Invoke a method asynchronously on an actor via its mailbox
|
54
52
|
def self.async(mailbox, meth, *args, &block)
|
55
|
-
our_mailbox = Thread.current.mailbox
|
56
53
|
begin
|
57
|
-
mailbox << AsyncCall.new(
|
54
|
+
mailbox << AsyncCall.new(Thread.mailbox, meth, args, block)
|
58
55
|
rescue MailboxError
|
59
56
|
# Silently swallow asynchronous calls to dead actors. There's no way
|
60
57
|
# to reliably generate DeadActorErrors for async calls, so users of
|
@@ -76,14 +73,13 @@ module Celluloid
|
|
76
73
|
@links = Links.new
|
77
74
|
@signals = Signals.new
|
78
75
|
@receivers = Receivers.new
|
79
|
-
@proxy = ActorProxy.new(@mailbox)
|
76
|
+
@proxy = ActorProxy.new(@mailbox, self.class.to_s)
|
80
77
|
@running = true
|
81
78
|
@pending_calls = {}
|
82
79
|
|
83
80
|
@thread = Pool.get do
|
84
|
-
Thread.current[:actor]
|
85
|
-
Thread.current[:
|
86
|
-
Thread.current[:mailbox] = @mailbox
|
81
|
+
Thread.current[:actor] = self
|
82
|
+
Thread.current[:mailbox] = @mailbox
|
87
83
|
|
88
84
|
run
|
89
85
|
end
|
@@ -121,8 +117,7 @@ module Celluloid
|
|
121
117
|
begin
|
122
118
|
message = @mailbox.receive
|
123
119
|
rescue ExitEvent => exit_event
|
124
|
-
|
125
|
-
run_fiber fiber
|
120
|
+
Celluloid::Fiber.new { handle_exit_event exit_event; nil }.resume
|
126
121
|
retry
|
127
122
|
end
|
128
123
|
|
@@ -140,29 +135,22 @@ module Celluloid
|
|
140
135
|
Pool.put @thread
|
141
136
|
end
|
142
137
|
|
143
|
-
#
|
144
|
-
def
|
145
|
-
|
146
|
-
|
147
|
-
@pending_calls[result.id] = fiber if fiber.alive?
|
148
|
-
elsif result
|
149
|
-
warning = "non-call returned from fiber: #{result.class}"
|
150
|
-
Celluloid.logger.debug warning if Celluloid.logger
|
151
|
-
end
|
152
|
-
nil
|
138
|
+
# Register a fiber waiting for the response to a Celluloid::Call
|
139
|
+
def register_fiber(call, fiber)
|
140
|
+
raise ArgumentError, "attempted to register a dead fiber" unless fiber.alive?
|
141
|
+
@pending_calls[call.id] = fiber
|
153
142
|
end
|
154
143
|
|
155
144
|
# Handle an incoming message
|
156
145
|
def handle_message(message)
|
157
146
|
case message
|
158
147
|
when Call
|
159
|
-
|
160
|
-
run_fiber fiber
|
148
|
+
Celluloid::Fiber.new { message.dispatch(@subject); nil }.resume
|
161
149
|
when Response
|
162
150
|
fiber = @pending_calls.delete(message.call_id)
|
163
151
|
|
164
152
|
if fiber
|
165
|
-
|
153
|
+
fiber.resume message
|
166
154
|
else
|
167
155
|
warning = "spurious response to call #{message.call_id}"
|
168
156
|
Celluloid.logger.debug if Celluloid.logger
|
data/lib/celluloid/calls.rb
CHANGED
@@ -87,7 +87,7 @@ module Celluloid
|
|
87
87
|
obj.send(@method, *@arguments, &@block)
|
88
88
|
rescue AbortError => ex
|
89
89
|
# Swallow aborted async calls, as they indicate the caller made a mistake
|
90
|
-
|
90
|
+
log_error ex, "#{obj.class}: async call aborted!"
|
91
91
|
end
|
92
92
|
|
93
93
|
def log_error(ex, message)
|
data/lib/celluloid/core_ext.rb
CHANGED
@@ -1,13 +1,7 @@
|
|
1
1
|
# Monkeypatch Thread to allow lazy access to its Celluloid::Mailbox
|
2
2
|
class Thread
|
3
|
-
# Retrieve the current
|
4
|
-
def mailbox
|
5
|
-
|
6
|
-
if Thread.current != self
|
7
|
-
raise "attempt to access an uninitialized mailbox"
|
8
|
-
end
|
9
|
-
|
10
|
-
self[:mailbox] = Celluloid::Mailbox.new
|
11
|
-
end
|
3
|
+
# Retrieve the mailbox for the current thread or lazily initialize it
|
4
|
+
def self.mailbox
|
5
|
+
current[:mailbox] ||= Celluloid::Mailbox.new
|
12
6
|
end
|
13
7
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# Every time I look at this code a little part of me dies...
|
2
2
|
begin
|
3
3
|
require 'fiber'
|
4
4
|
rescue LoadError => ex
|
@@ -31,3 +31,33 @@ rescue LoadError => ex
|
|
31
31
|
raise ex
|
32
32
|
end
|
33
33
|
end
|
34
|
+
|
35
|
+
module Celluloid
|
36
|
+
class Fiber < ::Fiber
|
37
|
+
def initialize(*args)
|
38
|
+
actor = Thread.current[:actor]
|
39
|
+
mailbox = Thread.current[:mailbox]
|
40
|
+
|
41
|
+
super do
|
42
|
+
Thread.current[:actor] = actor
|
43
|
+
Thread.current[:mailbox] = mailbox
|
44
|
+
|
45
|
+
yield(*args)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def resume(value = nil)
|
50
|
+
result = super
|
51
|
+
actor = Thread.current[:actor]
|
52
|
+
return result unless actor
|
53
|
+
|
54
|
+
if result.is_a? Celluloid::Call
|
55
|
+
actor.register_fiber result, self
|
56
|
+
elsif result
|
57
|
+
warning = "non-call returned from fiber: #{result.class}"
|
58
|
+
Celluloid.logger.debug warning if Celluloid.logger
|
59
|
+
end
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/celluloid/io/reactor.rb
CHANGED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module Celluloid
|
4
|
+
# Thread safe storage of inter-actor links
|
5
|
+
class Links
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@links = {}
|
10
|
+
@lock = Mutex.new
|
11
|
+
end
|
12
|
+
|
13
|
+
# Add an actor to the current links
|
14
|
+
def <<(actor)
|
15
|
+
@lock.synchronize do
|
16
|
+
@links[actor.mailbox.address] = actor
|
17
|
+
end
|
18
|
+
actor
|
19
|
+
end
|
20
|
+
|
21
|
+
# Do links include the given actor?
|
22
|
+
def include?(actor)
|
23
|
+
@lock.synchronize do
|
24
|
+
@links.has_key? actor.mailbox.address
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Remove an actor from the links
|
29
|
+
def delete(actor)
|
30
|
+
@lock.synchronize do
|
31
|
+
@links.delete actor.mailbox.address
|
32
|
+
end
|
33
|
+
actor
|
34
|
+
end
|
35
|
+
|
36
|
+
# Iterate through all links
|
37
|
+
def each
|
38
|
+
@lock.synchronize do
|
39
|
+
@links.each { |_, actor| yield(actor) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Map across links
|
44
|
+
def map
|
45
|
+
result = []
|
46
|
+
each { |actor| result << yield(actor) }
|
47
|
+
result
|
48
|
+
end
|
49
|
+
|
50
|
+
# Send an event message to all actors
|
51
|
+
def send_event(event)
|
52
|
+
each { |actor| actor.mailbox.system_event event }
|
53
|
+
end
|
54
|
+
|
55
|
+
# Generate a string representation
|
56
|
+
def inspect
|
57
|
+
links = self.map(&:inspect).join(',')
|
58
|
+
"#<#{self.class}[#{links}]>"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/celluloid/mailbox.rb
CHANGED
data/lib/celluloid/receivers.rb
CHANGED
data/lib/celluloid/signals.rb
CHANGED
data/lib/celluloid/supervisor.rb
CHANGED
@@ -26,11 +26,16 @@ module Celluloid
|
|
26
26
|
|
27
27
|
begin
|
28
28
|
@actor = @klass.new_link(*@args, &@block)
|
29
|
-
rescue
|
29
|
+
rescue => ex
|
30
30
|
failures += 1
|
31
31
|
if failures >= start_attempts
|
32
32
|
failures = 0
|
33
|
-
|
33
|
+
|
34
|
+
warning = "#{@klass} is crashing on initialize repeatedly, sleeping for #{sleep_interval} seconds\n"
|
35
|
+
warning << "#{ex.class}: #{ex}\n "
|
36
|
+
warning << "#{ex.backtrace.join("\n ")}"
|
37
|
+
|
38
|
+
Celluloid.logger.warn warning if Celluloid.logger
|
34
39
|
sleep sleep_interval
|
35
40
|
end
|
36
41
|
retry
|
data/lib/celluloid/version.rb
CHANGED
metadata
CHANGED
@@ -1,38 +1,38 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: celluloid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
4
|
+
version: 0.6.1
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Tony Arcieri
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-11-
|
12
|
+
date: 2011-11-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
|
16
|
+
requirement: &70242345718900 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
17
18
|
requirements:
|
18
19
|
- - ! '>='
|
19
20
|
- !ruby/object:Gem::Version
|
20
21
|
version: '0'
|
21
|
-
none: false
|
22
|
-
requirement: *2056
|
23
|
-
prerelease: false
|
24
22
|
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70242345718900
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
|
27
|
+
requirement: &70242345718300 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
28
29
|
requirements:
|
29
30
|
- - ! '>='
|
30
31
|
- !ruby/object:Gem::Version
|
31
32
|
version: 2.7.0
|
32
|
-
none: false
|
33
|
-
requirement: *2074
|
34
|
-
prerelease: false
|
35
33
|
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70242345718300
|
36
36
|
description: Celluloid is a concurrent object framework inspired by the Actor Model
|
37
37
|
email:
|
38
38
|
- tony@medioh.com
|
@@ -41,7 +41,6 @@ extensions: []
|
|
41
41
|
extra_rdoc_files: []
|
42
42
|
files:
|
43
43
|
- README.md
|
44
|
-
- lib/celluloid.rb
|
45
44
|
- lib/celluloid/actor.rb
|
46
45
|
- lib/celluloid/actor_pool.rb
|
47
46
|
- lib/celluloid/actor_proxy.rb
|
@@ -49,10 +48,13 @@ files:
|
|
49
48
|
- lib/celluloid/calls.rb
|
50
49
|
- lib/celluloid/core_ext.rb
|
51
50
|
- lib/celluloid/events.rb
|
52
|
-
- lib/celluloid/
|
51
|
+
- lib/celluloid/fiber.rb
|
53
52
|
- lib/celluloid/future.rb
|
53
|
+
- lib/celluloid/io/mailbox.rb
|
54
|
+
- lib/celluloid/io/reactor.rb
|
55
|
+
- lib/celluloid/io/waker.rb
|
54
56
|
- lib/celluloid/io.rb
|
55
|
-
- lib/celluloid/
|
57
|
+
- lib/celluloid/links.rb
|
56
58
|
- lib/celluloid/mailbox.rb
|
57
59
|
- lib/celluloid/receivers.rb
|
58
60
|
- lib/celluloid/registry.rb
|
@@ -62,34 +64,31 @@ files:
|
|
62
64
|
- lib/celluloid/supervisor.rb
|
63
65
|
- lib/celluloid/tcp_server.rb
|
64
66
|
- lib/celluloid/version.rb
|
65
|
-
- lib/celluloid
|
66
|
-
- lib/celluloid/io/reactor.rb
|
67
|
-
- lib/celluloid/io/waker.rb
|
67
|
+
- lib/celluloid.rb
|
68
68
|
homepage: https://github.com/tarcieri/celluloid
|
69
69
|
licenses:
|
70
70
|
- MIT
|
71
|
-
post_install_message:
|
71
|
+
post_install_message:
|
72
72
|
rdoc_options: []
|
73
73
|
require_paths:
|
74
74
|
- lib
|
75
75
|
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
76
77
|
requirements:
|
77
78
|
- - ! '>='
|
78
79
|
- !ruby/object:Gem::Version
|
79
80
|
version: '0'
|
80
|
-
none: false
|
81
81
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
82
83
|
requirements:
|
83
84
|
- - ! '>='
|
84
85
|
- !ruby/object:Gem::Version
|
85
86
|
version: 1.3.6
|
86
|
-
none: false
|
87
87
|
requirements: []
|
88
|
-
rubyforge_project:
|
89
|
-
rubygems_version: 1.8.
|
90
|
-
signing_key:
|
88
|
+
rubyforge_project:
|
89
|
+
rubygems_version: 1.8.10
|
90
|
+
signing_key:
|
91
91
|
specification_version: 3
|
92
92
|
summary: Celluloid is a concurrent object framework inspired by the Actor Model
|
93
93
|
test_files: []
|
94
|
-
has_rdoc:
|
95
|
-
...
|
94
|
+
has_rdoc:
|
data/lib/celluloid/linking.rb
DELETED
@@ -1,89 +0,0 @@
|
|
1
|
-
require 'set'
|
2
|
-
require 'thread'
|
3
|
-
|
4
|
-
module Celluloid
|
5
|
-
# Thread safe storage of inter-actor links
|
6
|
-
class Links
|
7
|
-
include Enumerable
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
@links = Set.new
|
11
|
-
@lock = Mutex.new
|
12
|
-
end
|
13
|
-
|
14
|
-
# Add an actor to the current links
|
15
|
-
def <<(actor)
|
16
|
-
@lock.synchronize do
|
17
|
-
@links << actor
|
18
|
-
end
|
19
|
-
actor
|
20
|
-
end
|
21
|
-
|
22
|
-
# Do links include the given actor?
|
23
|
-
def include?(actor)
|
24
|
-
@lock.synchronize do
|
25
|
-
@links.include? actor
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# Remove an actor from the links
|
30
|
-
def delete(actor)
|
31
|
-
@lock.synchronize do
|
32
|
-
@links.delete actor
|
33
|
-
end
|
34
|
-
actor
|
35
|
-
end
|
36
|
-
|
37
|
-
# Iterate through all links
|
38
|
-
def each(&block)
|
39
|
-
@lock.synchronize do
|
40
|
-
@links.each(&block)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# Send an event message to all actors
|
45
|
-
def send_event(event)
|
46
|
-
each { |actor| actor.mailbox.system_event event }
|
47
|
-
end
|
48
|
-
|
49
|
-
# Generate a string representation
|
50
|
-
def inspect
|
51
|
-
@lock.synchronize do
|
52
|
-
links = @links.to_a.map { |l| "#{l.class}:#{l.object_id}" }.join(',')
|
53
|
-
"#<#{self.class}[#{links}]>"
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# Support for linking actors together so they can crash or react to errors
|
59
|
-
module Linking
|
60
|
-
# Link this actor to another, allowing it to crash or react to errors
|
61
|
-
def link(actor)
|
62
|
-
current_actor = Thread.current[:actor]
|
63
|
-
|
64
|
-
actor.notify_link(current_actor.proxy)
|
65
|
-
current_actor.notify_link(actor)
|
66
|
-
end
|
67
|
-
|
68
|
-
# Remove links to another actor
|
69
|
-
def unlink(actor)
|
70
|
-
current_actor = Thread.current[:actor]
|
71
|
-
|
72
|
-
actor.notify_unlink(current_actor.proxy)
|
73
|
-
current_actor.notify_unlink(actor)
|
74
|
-
end
|
75
|
-
|
76
|
-
def notify_link(actor)
|
77
|
-
Thread.current[:actor].links << actor
|
78
|
-
end
|
79
|
-
|
80
|
-
def notify_unlink(actor)
|
81
|
-
Thread.current[:actor].links.delete actor
|
82
|
-
end
|
83
|
-
|
84
|
-
# Is this actor linked to another?
|
85
|
-
def linked_to?(actor)
|
86
|
-
Thread.current[:actor].links.include? actor
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|