celluloid 0.17.0 → 0.17.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of celluloid might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGES.md +10 -2
- data/LICENSE.txt +1 -1
- data/README.md +26 -14
- data/culture/gems/dependencies.yml +8 -2
- data/examples/stack.rb +47 -0
- data/lib/celluloid.rb +9 -6
- data/lib/celluloid/actor.rb +7 -32
- data/lib/celluloid/actor/manager.rb +7 -0
- data/lib/celluloid/actor/system.rb +163 -0
- data/lib/celluloid/call/sync.rb +1 -1
- data/lib/celluloid/calls.rb +3 -3
- data/lib/celluloid/cell.rb +1 -1
- data/lib/celluloid/condition.rb +3 -4
- data/lib/celluloid/debug.rb +1 -0
- data/lib/celluloid/deprecate.rb +3 -0
- data/lib/celluloid/exceptions.rb +20 -15
- data/lib/celluloid/future.rb +40 -3
- data/lib/celluloid/group.rb +5 -9
- data/lib/celluloid/group/pool.rb +1 -1
- data/lib/celluloid/group/spawner.rb +1 -2
- data/lib/celluloid/mailbox.rb +2 -2
- data/lib/celluloid/managed.rb +3 -0
- data/lib/celluloid/notices.rb +1 -1
- data/lib/celluloid/proxies.rb +7 -8
- data/lib/celluloid/proxy/abstract.rb +16 -21
- data/lib/celluloid/proxy/actor.rb +33 -37
- data/lib/celluloid/proxy/async.rb +24 -29
- data/lib/celluloid/proxy/block.rb +20 -24
- data/lib/celluloid/proxy/cell.rb +58 -62
- data/lib/celluloid/proxy/future.rb +33 -37
- data/lib/celluloid/proxy/sync.rb +31 -35
- data/lib/celluloid/system_events.rb +53 -1
- data/lib/celluloid/task.rb +13 -21
- data/lib/celluloid/task/fibered.rb +1 -1
- data/lib/celluloid/task/threaded.rb +2 -2
- data/lib/celluloid/version.rb +1 -1
- data/spec/celluloid/{group → actor}/manager_spec.rb +0 -0
- data/spec/celluloid/{actor_system_spec.rb → actor/system_spec.rb} +4 -4
- data/spec/celluloid/block_spec.rb +64 -3
- data/spec/celluloid/condition_spec.rb +6 -0
- data/spec/celluloid/future_spec.rb +2 -2
- data/spec/deprecate/actor_system_spec.rb +1 -1
- data/spec/deprecate/future_spec.rb +2 -2
- data/spec/shared/actor_examples.rb +20 -4
- data/spec/shared/group_examples.rb +1 -1
- data/spec/shared/mailbox_examples.rb +1 -1
- data/spec/spec_helper.rb +3 -3
- metadata +110 -76
- data/lib/celluloid/actor_system.rb +0 -160
- data/lib/celluloid/group/manager.rb +0 -27
@@ -1,36 +1,31 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
class Async < Abstract
|
5
|
-
attr_reader :mailbox
|
1
|
+
# A proxy which sends asynchronous calls to an actor
|
2
|
+
class Celluloid::Proxy::Async < Celluloid::Proxy::Abstract
|
3
|
+
attr_reader :mailbox
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
def initialize(mailbox, klass)
|
13
|
-
@mailbox = mailbox
|
14
|
-
@klass = klass
|
15
|
-
end
|
16
|
-
|
17
|
-
def inspect
|
18
|
-
"#<Celluloid::Proxy::Async(#{@klass})>"
|
19
|
-
end
|
5
|
+
# Used for reflecting on proxy objects themselves
|
6
|
+
def __class__
|
7
|
+
::Celluloid::Proxy::Async
|
8
|
+
end
|
20
9
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
10
|
+
def initialize(mailbox, klass)
|
11
|
+
@mailbox = mailbox
|
12
|
+
@klass = klass
|
13
|
+
end
|
26
14
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
15
|
+
def inspect
|
16
|
+
"#<Celluloid::Proxy::Async(#{@klass})>"
|
17
|
+
end
|
31
18
|
|
32
|
-
|
33
|
-
|
19
|
+
def method_missing(meth, *args, &block)
|
20
|
+
if @mailbox == ::Thread.current[:celluloid_mailbox]
|
21
|
+
args.unshift meth
|
22
|
+
meth = :__send__
|
23
|
+
end
|
24
|
+
if block_given?
|
25
|
+
# FIXME: nicer exception
|
26
|
+
fail "Cannot use blocks with async yet"
|
34
27
|
end
|
28
|
+
@mailbox << ::Celluloid::Call::Async.new(meth, args, block)
|
29
|
+
self
|
35
30
|
end
|
36
31
|
end
|
@@ -1,31 +1,27 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
attr_writer :execution
|
11
|
-
attr_reader :call, :block
|
1
|
+
class Celluloid::Proxy::Block
|
2
|
+
attr_writer :execution
|
3
|
+
attr_reader :call, :block
|
4
|
+
def initialize(mailbox, call, block)
|
5
|
+
@mailbox = mailbox
|
6
|
+
@call = call
|
7
|
+
@block = block
|
8
|
+
@execution = :sender
|
9
|
+
end
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
else
|
21
|
-
# FIXME: better exception
|
22
|
-
fail "No task to suspend"
|
23
|
-
end
|
24
|
-
end
|
11
|
+
def to_proc
|
12
|
+
if @execution == :sender
|
13
|
+
lambda do |*values|
|
14
|
+
if task = Thread.current[:celluloid_task]
|
15
|
+
@mailbox << ::Celluloid::Call::Block.new(self, ::Celluloid::Actor.current.mailbox, values)
|
16
|
+
# TODO: if respond fails, the Task will never be resumed
|
17
|
+
task.suspend(:invokeblock)
|
25
18
|
else
|
26
|
-
|
19
|
+
# FIXME: better exception
|
20
|
+
fail "No task to suspend"
|
27
21
|
end
|
28
22
|
end
|
23
|
+
else
|
24
|
+
@block
|
29
25
|
end
|
30
26
|
end
|
31
27
|
end
|
data/lib/celluloid/proxy/cell.rb
CHANGED
@@ -1,76 +1,72 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
Proxy::Cell
|
9
|
-
end
|
1
|
+
# A proxy object returned from Celluloid::Actor.new/new_link which converts
|
2
|
+
# the normal Ruby method protocol into an inter-actor message protocol
|
3
|
+
class Celluloid::Proxy::Cell < Celluloid::Proxy::Sync
|
4
|
+
# Used for reflecting on proxy objects themselves
|
5
|
+
def __class__
|
6
|
+
::Celluloid::Proxy::Cell
|
7
|
+
end
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
def initialize(mailbox, actor_proxy, klass)
|
10
|
+
super(mailbox, klass)
|
11
|
+
@actor_proxy = actor_proxy
|
12
|
+
@sync_proxy = ::Celluloid::Proxy::Sync.new(mailbox, klass)
|
13
|
+
@async_proxy = ::Celluloid::Proxy::Async.new(mailbox, klass)
|
14
|
+
@future_proxy = ::Celluloid::Proxy::Future.new(mailbox, klass)
|
15
|
+
end
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
def _send_(meth, *args, &block)
|
18
|
+
method_missing :__send__, meth, *args, &block
|
19
|
+
end
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
21
|
+
def inspect
|
22
|
+
method_missing :inspect
|
23
|
+
rescue ::Celluloid::DeadActorError
|
24
|
+
"#<::Celluloid::Proxy::Cell(#{@klass}) dead>"
|
25
|
+
end
|
28
26
|
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
def method(name)
|
28
|
+
::Celluloid::Internals::Method.new(self, name)
|
29
|
+
end
|
32
30
|
|
33
|
-
|
31
|
+
alias_method :sync, :method_missing
|
34
32
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
33
|
+
# Obtain an async proxy or explicitly invoke a named async method
|
34
|
+
def async(method_name = nil, *args, &block)
|
35
|
+
if method_name
|
36
|
+
@async_proxy.method_missing method_name, *args, &block
|
37
|
+
else
|
38
|
+
@async_proxy
|
39
|
+
end
|
40
|
+
end
|
43
41
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
42
|
+
# Obtain a future proxy or explicitly invoke a named future method
|
43
|
+
def future(method_name = nil, *args, &block)
|
44
|
+
if method_name
|
45
|
+
@future_proxy.method_missing method_name, *args, &block
|
46
|
+
else
|
47
|
+
@future_proxy
|
48
|
+
end
|
49
|
+
end
|
52
50
|
|
53
|
-
|
54
|
-
|
55
|
-
|
51
|
+
def alive?
|
52
|
+
@actor_proxy.alive?
|
53
|
+
end
|
56
54
|
|
57
|
-
|
58
|
-
|
59
|
-
|
55
|
+
def dead?
|
56
|
+
@actor_proxy.dead?
|
57
|
+
end
|
60
58
|
|
61
|
-
|
62
|
-
|
63
|
-
|
59
|
+
def thread
|
60
|
+
@actor_proxy.thread
|
61
|
+
end
|
64
62
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
63
|
+
# Terminate the associated actor
|
64
|
+
def terminate
|
65
|
+
@actor_proxy.terminate
|
66
|
+
end
|
69
67
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
74
|
-
end
|
68
|
+
# Terminate the associated actor asynchronously
|
69
|
+
def terminate!
|
70
|
+
@actor_proxy.terminate!
|
75
71
|
end
|
76
72
|
end
|
@@ -1,40 +1,36 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
# FIXME: nicer exception
|
28
|
-
fail "Cannot use blocks with futures yet"
|
29
|
-
end
|
30
|
-
|
31
|
-
future = ::Celluloid::Future.new
|
32
|
-
call = Call::Sync.new(future, meth, args, block)
|
33
|
-
|
34
|
-
@mailbox << call
|
35
|
-
|
36
|
-
future
|
37
|
-
end
|
1
|
+
# A proxy which creates future calls to an actor
|
2
|
+
class Celluloid::Proxy::Future < Celluloid::Proxy::Abstract
|
3
|
+
attr_reader :mailbox
|
4
|
+
|
5
|
+
# Used for reflecting on proxy objects themselves
|
6
|
+
def __class__
|
7
|
+
::Celluloid::Proxy::Future
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(mailbox, klass)
|
11
|
+
@mailbox = mailbox
|
12
|
+
@klass = klass
|
13
|
+
end
|
14
|
+
|
15
|
+
def inspect
|
16
|
+
"#<Celluloid::Proxy::Future(#{@klass})>"
|
17
|
+
end
|
18
|
+
|
19
|
+
def method_missing(meth, *args, &block)
|
20
|
+
unless @mailbox.alive?
|
21
|
+
fail ::Celluloid::DeadActorError, "attempted to call a dead actor"
|
22
|
+
end
|
23
|
+
|
24
|
+
if block_given?
|
25
|
+
# FIXME: nicer exception
|
26
|
+
fail "Cannot use blocks with futures yet"
|
38
27
|
end
|
28
|
+
|
29
|
+
future = ::Celluloid::Future.new
|
30
|
+
call = ::Celluloid::Call::Sync.new(future, meth, args, block)
|
31
|
+
|
32
|
+
@mailbox << call
|
33
|
+
|
34
|
+
future
|
39
35
|
end
|
40
36
|
end
|
data/lib/celluloid/proxy/sync.rb
CHANGED
@@ -1,44 +1,40 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
class Sync < Abstract
|
5
|
-
attr_reader :mailbox
|
1
|
+
# A proxy which sends synchronous calls to an actor
|
2
|
+
class Celluloid::Proxy::Sync < Celluloid::Proxy::Abstract
|
3
|
+
attr_reader :mailbox
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
def initialize(mailbox, klass)
|
13
|
-
@mailbox = mailbox
|
14
|
-
@klass = klass
|
15
|
-
end
|
5
|
+
# Used for reflecting on proxy objects themselves
|
6
|
+
def __class__
|
7
|
+
::Celluloid::Proxy::Sync
|
8
|
+
end
|
16
9
|
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
def initialize(mailbox, klass)
|
11
|
+
@mailbox = mailbox
|
12
|
+
@klass = klass
|
13
|
+
end
|
20
14
|
|
21
|
-
|
22
|
-
|
23
|
-
|
15
|
+
def inspect
|
16
|
+
"#<Celluloid::Proxy::Sync(#{@klass})>"
|
17
|
+
end
|
24
18
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
19
|
+
def respond_to?(meth, include_private = false)
|
20
|
+
__class__.instance_methods.include?(meth) || method_missing(:respond_to?, meth, include_private)
|
21
|
+
end
|
29
22
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
# actor = actor.behavior.subject.bare_object
|
35
|
-
# return actor.__send__(*args, &block)
|
36
|
-
end
|
23
|
+
def method_missing(meth, *args, &block)
|
24
|
+
unless @mailbox.alive?
|
25
|
+
fail ::Celluloid::DeadActorError, "attempted to call a dead actor"
|
26
|
+
end
|
37
27
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
28
|
+
if @mailbox == ::Thread.current[:celluloid_mailbox]
|
29
|
+
args.unshift meth
|
30
|
+
meth = :__send__
|
31
|
+
# actor = Thread.current[:celluloid_actor]
|
32
|
+
# actor = actor.behavior.subject.bare_object
|
33
|
+
# return actor.__send__(*args, &block)
|
42
34
|
end
|
35
|
+
|
36
|
+
call = ::Celluloid::Call::Sync.new(::Celluloid.mailbox, meth, args, block)
|
37
|
+
@mailbox << call
|
38
|
+
call.value
|
43
39
|
end
|
44
40
|
end
|
@@ -1,6 +1,38 @@
|
|
1
1
|
module Celluloid
|
2
|
+
class Actor
|
3
|
+
# Handle high-priority system event messages
|
4
|
+
def handle_system_event(event)
|
5
|
+
if handler = SystemEvent.handle(event.class)
|
6
|
+
send(handler, event)
|
7
|
+
else
|
8
|
+
Internals::Logger.debug "Discarded message (unhandled): #{message}" if $CELLULOID_DEBUG
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
2
12
|
# High-priority internal system events
|
3
13
|
class SystemEvent
|
14
|
+
class << self
|
15
|
+
@@system_events = {}
|
16
|
+
def handle(type)
|
17
|
+
@@system_events[type]
|
18
|
+
end
|
19
|
+
|
20
|
+
def handler(&block)
|
21
|
+
fail ArgumentError, "SystemEvent handlers must be defined with a block." unless block
|
22
|
+
method = begin
|
23
|
+
handler = name
|
24
|
+
.split("::").last
|
25
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, "\1_\2")
|
26
|
+
.gsub(/([a-z\d])([A-Z])/, "\1_\2")
|
27
|
+
.tr("-", "_")
|
28
|
+
.downcase
|
29
|
+
:"handle_#{handler}"
|
30
|
+
end
|
31
|
+
Actor.send(:define_method, method, &block)
|
32
|
+
@@system_events[self] = method
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
4
36
|
class LinkingEvent < SystemEvent
|
5
37
|
# Shared initializer for LinkingRequest and LinkingResponse
|
6
38
|
def initialize(actor, type)
|
@@ -15,6 +47,10 @@ module Celluloid
|
|
15
47
|
class LinkingRequest < SystemEvent::LinkingEvent
|
16
48
|
attr_reader :actor, :type
|
17
49
|
|
50
|
+
handler do |event|
|
51
|
+
event.process(links)
|
52
|
+
end
|
53
|
+
|
18
54
|
def process(links)
|
19
55
|
case type
|
20
56
|
when :link then links << actor
|
@@ -34,6 +70,11 @@ module Celluloid
|
|
34
70
|
class ExitEvent < SystemEvent
|
35
71
|
attr_reader :actor, :reason
|
36
72
|
|
73
|
+
handler do |event|
|
74
|
+
@links.delete event.actor
|
75
|
+
@exit_handler.call(event)
|
76
|
+
end
|
77
|
+
|
37
78
|
def initialize(actor, reason = nil)
|
38
79
|
@actor = actor
|
39
80
|
@reason = reason
|
@@ -44,13 +85,22 @@ module Celluloid
|
|
44
85
|
class NamingRequest < SystemEvent
|
45
86
|
attr_reader :name
|
46
87
|
|
88
|
+
handler do |event|
|
89
|
+
@name = event.name
|
90
|
+
Celluloid::Probe.actor_named(self) if $CELLULOID_MONITORING
|
91
|
+
end
|
92
|
+
|
47
93
|
def initialize(name)
|
48
94
|
@name = name
|
49
95
|
end
|
50
96
|
end
|
51
97
|
|
52
98
|
# Request for an actor to terminate
|
53
|
-
class TerminationRequest < SystemEvent
|
99
|
+
class TerminationRequest < SystemEvent
|
100
|
+
handler do |event|
|
101
|
+
terminate
|
102
|
+
end
|
103
|
+
end
|
54
104
|
|
55
105
|
# Signal a condition
|
56
106
|
class SignalConditionRequest < SystemEvent
|
@@ -60,6 +110,8 @@ module Celluloid
|
|
60
110
|
end
|
61
111
|
attr_reader :task, :value
|
62
112
|
|
113
|
+
handler(&:call)
|
114
|
+
|
63
115
|
def call
|
64
116
|
@task.resume(@value)
|
65
117
|
end
|