celluloid 0.16.0 → 0.17.3
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/CHANGES.md +394 -0
- data/LICENSE.txt +1 -1
- data/README.md +28 -15
- data/culture/CONDUCT.md +28 -0
- data/culture/Gemfile +9 -0
- data/culture/LICENSE.txt +22 -0
- data/culture/README.md +22 -0
- data/culture/Rakefile +5 -0
- data/culture/SYNC.md +70 -0
- data/culture/celluloid-culture.gemspec +18 -0
- data/culture/gems/README.md +39 -0
- data/culture/gems/dependencies.yml +85 -0
- data/culture/gems/loader.rb +101 -0
- data/culture/rubocop/README.md +38 -0
- data/culture/rubocop/lint.yml +8 -0
- data/culture/rubocop/metrics.yml +15 -0
- data/culture/rubocop/perf.yml +0 -0
- data/culture/rubocop/rubocop.yml +5 -0
- data/culture/rubocop/style.yml +57 -0
- data/culture/spec/gems_spec.rb +2 -0
- data/culture/spec/spec_helper.rb +0 -0
- data/culture/spec/sync_spec.rb +2 -0
- data/culture/sync.rb +56 -0
- data/culture/tasks/rspec.rake +5 -0
- data/culture/tasks/rubocop.rake +2 -0
- data/examples/basic_usage.rb +49 -0
- data/examples/futures.rb +38 -0
- data/examples/ring.rb +61 -0
- data/examples/simple_pmap.rb +14 -0
- data/examples/stack.rb +47 -0
- data/examples/timers.rb +72 -0
- data/lib/celluloid/actor/manager.rb +7 -0
- data/lib/celluloid/actor/system.rb +163 -0
- data/lib/celluloid/actor.rb +53 -71
- data/lib/celluloid/autostart.rb +1 -1
- data/lib/celluloid/backported.rb +2 -0
- data/lib/celluloid/call/async.rb +16 -0
- data/lib/celluloid/call/block.rb +22 -0
- data/lib/celluloid/call/sync.rb +70 -0
- data/lib/celluloid/calls.rb +24 -114
- data/lib/celluloid/cell.rb +32 -20
- data/lib/celluloid/condition.rb +5 -6
- data/lib/celluloid/core_ext.rb +1 -1
- data/lib/celluloid/current.rb +2 -0
- data/lib/celluloid/debug.rb +1 -0
- data/lib/celluloid/deprecate.rb +21 -0
- data/lib/celluloid/exceptions.rb +22 -16
- data/lib/celluloid/fiber.rb +3 -3
- data/lib/celluloid/future.rb +46 -8
- data/lib/celluloid/group/pool.rb +125 -0
- data/lib/celluloid/group/spawner.rb +68 -0
- data/lib/celluloid/group.rb +61 -0
- data/lib/celluloid/logging.rb +5 -5
- data/lib/celluloid/mailbox/evented.rb +74 -0
- data/lib/celluloid/mailbox.rb +15 -14
- data/lib/celluloid/managed.rb +3 -0
- data/lib/celluloid/notices.rb +15 -0
- data/lib/celluloid/proxies.rb +11 -0
- data/lib/celluloid/proxy/abstract.rb +50 -0
- data/lib/celluloid/proxy/actor.rb +37 -0
- data/lib/celluloid/proxy/async.rb +15 -0
- data/lib/celluloid/proxy/block.rb +28 -0
- data/lib/celluloid/proxy/cell.rb +66 -0
- data/lib/celluloid/proxy/future.rb +20 -0
- data/lib/celluloid/proxy/sync.rb +24 -0
- data/lib/celluloid/rspec.rb +67 -9
- data/lib/celluloid/system_events.rb +69 -14
- data/lib/celluloid/task/fibered.rb +45 -0
- data/lib/celluloid/task/threaded.rb +59 -0
- data/lib/celluloid/{tasks.rb → task.rb} +30 -38
- data/lib/celluloid/test.rb +1 -1
- data/lib/celluloid/thread.rb +6 -1
- data/lib/celluloid/version.rb +3 -0
- data/lib/celluloid.rb +151 -130
- data/spec/celluloid/actor/system_spec.rb +83 -0
- data/spec/celluloid/actor_spec.rb +2 -2
- data/spec/celluloid/block_spec.rb +67 -8
- data/spec/celluloid/calls_spec.rb +28 -23
- data/spec/celluloid/condition_spec.rb +23 -14
- data/spec/celluloid/evented_mailbox_spec.rb +1 -31
- data/spec/celluloid/future_spec.rb +15 -12
- data/spec/celluloid/group/elastic_spec.rb +0 -0
- data/spec/celluloid/group/pool_spec.rb +8 -0
- data/spec/celluloid/group/spawner_spec.rb +17 -0
- data/spec/celluloid/mailbox/evented_spec.rb +40 -0
- data/spec/celluloid/mailbox_spec.rb +1 -3
- data/spec/celluloid/misc/leak_spec.rb +73 -0
- data/spec/celluloid/proxy_spec.rb +33 -0
- data/spec/celluloid/task/fibered_spec.rb +5 -0
- data/spec/celluloid/task/threaded_spec.rb +5 -0
- data/spec/celluloid/timer_spec.rb +14 -16
- data/spec/deprecate/actor_system_spec.rb +72 -0
- data/spec/deprecate/block_spec.rb +52 -0
- data/spec/deprecate/calls_spec.rb +39 -0
- data/spec/deprecate/evented_mailbox_spec.rb +34 -0
- data/spec/deprecate/future_spec.rb +32 -0
- data/spec/deprecate/internal_pool_spec.rb +4 -0
- data/spec/shared/actor_examples.rb +1259 -0
- data/spec/shared/group_examples.rb +121 -0
- data/spec/shared/mailbox_examples.rb +87 -0
- data/{lib/celluloid/rspec → spec/shared}/task_examples.rb +9 -8
- data/spec/spec_helper.rb +5 -42
- data/spec/support/configure_rspec.rb +77 -0
- data/spec/support/coverage.rb +4 -0
- data/spec/support/crash_checking.rb +68 -0
- data/spec/support/debugging.rb +31 -0
- data/spec/support/env.rb +21 -0
- data/{lib/celluloid/rspec/example_actor_class.rb → spec/support/examples/actor_class.rb} +21 -2
- data/spec/support/examples/call_class.rb +37 -0
- data/spec/support/examples/evented_mailbox_class.rb +27 -0
- data/spec/support/includer.rb +6 -0
- data/spec/support/logging.rb +55 -0
- data/spec/support/loose_threads.rb +68 -0
- data/spec/support/reset_class_variables.rb +27 -0
- data/spec/support/sleep_and_wait.rb +14 -0
- data/spec/support/stubbing.rb +14 -0
- metadata +276 -78
- data/lib/celluloid/actor_system.rb +0 -107
- data/lib/celluloid/call_chain.rb +0 -13
- data/lib/celluloid/cpu_counter.rb +0 -34
- data/lib/celluloid/evented_mailbox.rb +0 -73
- data/lib/celluloid/fsm.rb +0 -186
- data/lib/celluloid/handlers.rb +0 -41
- data/lib/celluloid/internal_pool.rb +0 -159
- data/lib/celluloid/legacy.rb +0 -9
- data/lib/celluloid/links.rb +0 -36
- data/lib/celluloid/logger.rb +0 -93
- data/lib/celluloid/logging/incident.rb +0 -21
- data/lib/celluloid/logging/incident_logger.rb +0 -129
- data/lib/celluloid/logging/incident_reporter.rb +0 -48
- data/lib/celluloid/logging/log_event.rb +0 -20
- data/lib/celluloid/logging/ring_buffer.rb +0 -65
- data/lib/celluloid/method.rb +0 -32
- data/lib/celluloid/notifications.rb +0 -83
- data/lib/celluloid/pool_manager.rb +0 -146
- data/lib/celluloid/probe.rb +0 -73
- data/lib/celluloid/properties.rb +0 -24
- data/lib/celluloid/proxies/abstract_proxy.rb +0 -20
- data/lib/celluloid/proxies/actor_proxy.rb +0 -38
- data/lib/celluloid/proxies/async_proxy.rb +0 -31
- data/lib/celluloid/proxies/block_proxy.rb +0 -29
- data/lib/celluloid/proxies/cell_proxy.rb +0 -68
- data/lib/celluloid/proxies/future_proxy.rb +0 -35
- data/lib/celluloid/proxies/sync_proxy.rb +0 -36
- data/lib/celluloid/receivers.rb +0 -63
- data/lib/celluloid/registry.rb +0 -57
- data/lib/celluloid/responses.rb +0 -44
- data/lib/celluloid/rspec/actor_examples.rb +0 -1054
- data/lib/celluloid/rspec/mailbox_examples.rb +0 -84
- data/lib/celluloid/signals.rb +0 -23
- data/lib/celluloid/stack_dump.rb +0 -133
- data/lib/celluloid/supervision_group.rb +0 -169
- data/lib/celluloid/supervisor.rb +0 -22
- data/lib/celluloid/task_set.rb +0 -49
- data/lib/celluloid/tasks/task_fiber.rb +0 -43
- data/lib/celluloid/tasks/task_thread.rb +0 -53
- data/lib/celluloid/thread_handle.rb +0 -50
- data/lib/celluloid/uuid.rb +0 -38
- data/spec/celluloid/actor_system_spec.rb +0 -69
- data/spec/celluloid/cpu_counter_spec.rb +0 -82
- data/spec/celluloid/fsm_spec.rb +0 -107
- data/spec/celluloid/internal_pool_spec.rb +0 -52
- data/spec/celluloid/links_spec.rb +0 -45
- data/spec/celluloid/logging/ring_buffer_spec.rb +0 -38
- data/spec/celluloid/notifications_spec.rb +0 -120
- data/spec/celluloid/pool_spec.rb +0 -92
- data/spec/celluloid/probe_spec.rb +0 -121
- data/spec/celluloid/properties_spec.rb +0 -42
- data/spec/celluloid/registry_spec.rb +0 -64
- data/spec/celluloid/stack_dump_spec.rb +0 -64
- data/spec/celluloid/supervision_group_spec.rb +0 -65
- data/spec/celluloid/supervisor_spec.rb +0 -103
- data/spec/celluloid/tasks/task_fiber_spec.rb +0 -5
- data/spec/celluloid/tasks/task_thread_spec.rb +0 -5
- data/spec/celluloid/thread_handle_spec.rb +0 -26
- data/spec/celluloid/uuid_spec.rb +0 -11
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
require "thread"
|
|
2
|
+
|
|
3
|
+
module Celluloid
|
|
4
|
+
class Group
|
|
5
|
+
class Spawner < Group
|
|
6
|
+
attr_accessor :finalizer
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
super
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def get(&block)
|
|
13
|
+
assert_active
|
|
14
|
+
fail ArgumentError.new("No block sent to Spawner.get()") unless block_given?
|
|
15
|
+
instantiate block
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def shutdown
|
|
19
|
+
@running = false
|
|
20
|
+
queue = []
|
|
21
|
+
@mutex.synchronize do
|
|
22
|
+
loop do
|
|
23
|
+
break if @group.empty?
|
|
24
|
+
th = @group.shift
|
|
25
|
+
th.kill
|
|
26
|
+
queue << th
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
Thread.pass unless queue.empty?
|
|
30
|
+
loop do
|
|
31
|
+
break if queue.empty?
|
|
32
|
+
queue.pop.join
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def idle?
|
|
37
|
+
to_a.select { |t| t[:celluloid_thread_state] == :running }.empty?
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def busy?
|
|
41
|
+
to_a.select { |t| t[:celluloid_thread_state] == :running }.any?
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def instantiate(proc)
|
|
47
|
+
thread = Thread.new do
|
|
48
|
+
Thread.current[:celluloid_thread_state] = :running
|
|
49
|
+
begin
|
|
50
|
+
proc.call
|
|
51
|
+
rescue ::Exception => ex
|
|
52
|
+
Internals::Logger.crash("thread crashed", ex)
|
|
53
|
+
Thread.current[:celluloid_thread_state] = :error
|
|
54
|
+
ensure
|
|
55
|
+
unless Thread.current[:celluloid_thread_state] == :error
|
|
56
|
+
Thread.current[:celluloid_thread_state] = :finished
|
|
57
|
+
end
|
|
58
|
+
@mutex.synchronize { @group.delete Thread.current }
|
|
59
|
+
Thread.exit
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
@mutex.synchronize { @group << thread }
|
|
64
|
+
thread
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module Celluloid
|
|
2
|
+
class Group
|
|
3
|
+
attr_accessor :group
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
@mutex = Mutex.new
|
|
7
|
+
@group = []
|
|
8
|
+
@running = true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def assert_active
|
|
12
|
+
fail Celluloid::NotActive unless active?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def assert_inactive
|
|
16
|
+
return unless active?
|
|
17
|
+
if RUBY_PLATFORM == "java"
|
|
18
|
+
Celluloid.logger.warn "Group is still active"
|
|
19
|
+
else
|
|
20
|
+
fail Celluloid::StillActive
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def each
|
|
25
|
+
to_a.each { |thread| yield thread }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def to_a
|
|
29
|
+
res = nil
|
|
30
|
+
@mutex.synchronize { res = @group.dup }
|
|
31
|
+
res
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def purge(thread)
|
|
35
|
+
@mutex.synchronize do
|
|
36
|
+
@group.delete(thread)
|
|
37
|
+
thread.kill rescue nil
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def each_actor(&block)
|
|
42
|
+
to_a.lazy.select { |t| t[:celluloid_role] == :actor }.each(&block)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def active?
|
|
46
|
+
@running
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def get
|
|
50
|
+
fail NotImplementedError
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def create
|
|
54
|
+
fail NotImplementedError
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def shutdown
|
|
58
|
+
fail NotImplementedError
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
data/lib/celluloid/logging.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
1
|
+
require "celluloid/logging/log_event"
|
|
2
|
+
require "celluloid/logging/incident"
|
|
3
|
+
require "celluloid/logging/ring_buffer"
|
|
4
|
+
require "celluloid/logging/incident_logger"
|
|
5
|
+
require "celluloid/logging/incident_reporter"
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
module Celluloid
|
|
2
|
+
class Mailbox
|
|
3
|
+
# An alternative implementation of Celluloid::Mailbox using Reactor
|
|
4
|
+
class Evented < Celluloid::Mailbox
|
|
5
|
+
attr_reader :reactor
|
|
6
|
+
|
|
7
|
+
def initialize(reactor_class)
|
|
8
|
+
super()
|
|
9
|
+
# @condition won't be used in the class.
|
|
10
|
+
@reactor = reactor_class.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Add a message to the Mailbox
|
|
14
|
+
def <<(message)
|
|
15
|
+
@mutex.lock
|
|
16
|
+
begin
|
|
17
|
+
if mailbox_full || @dead
|
|
18
|
+
dead_letter(message)
|
|
19
|
+
return
|
|
20
|
+
end
|
|
21
|
+
if message.is_a?(SystemEvent)
|
|
22
|
+
# SystemEvents are high priority messages so they get added to the
|
|
23
|
+
# head of our message queue instead of the end
|
|
24
|
+
@messages.unshift message
|
|
25
|
+
else
|
|
26
|
+
@messages << message
|
|
27
|
+
end
|
|
28
|
+
ensure
|
|
29
|
+
@mutex.unlock rescue nil
|
|
30
|
+
end
|
|
31
|
+
begin
|
|
32
|
+
current_actor = Thread.current[:celluloid_actor]
|
|
33
|
+
@reactor.wakeup unless current_actor && current_actor.mailbox == self
|
|
34
|
+
rescue
|
|
35
|
+
Internals::Logger.crash "reactor crashed", $ERROR_INFO
|
|
36
|
+
dead_letter(message)
|
|
37
|
+
end
|
|
38
|
+
nil
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Receive a message from the Mailbox
|
|
42
|
+
def check(timeout = nil, &block)
|
|
43
|
+
# Get a message if it is available and process it immediately if possible:
|
|
44
|
+
if message = next_message(block)
|
|
45
|
+
return message
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# ... otherwise, run the reactor once, either blocking or will return
|
|
49
|
+
# after the given timeout:
|
|
50
|
+
@reactor.run_once(timeout)
|
|
51
|
+
|
|
52
|
+
# No message was received:
|
|
53
|
+
return nil
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Obtain the next message from the mailbox that matches the given block
|
|
57
|
+
def next_message(block)
|
|
58
|
+
@mutex.lock
|
|
59
|
+
begin
|
|
60
|
+
super(&block)
|
|
61
|
+
ensure
|
|
62
|
+
@mutex.unlock rescue nil
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Cleanup any IO objects this Mailbox may be using
|
|
67
|
+
def shutdown
|
|
68
|
+
super do
|
|
69
|
+
@reactor.shutdown
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
data/lib/celluloid/mailbox.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "thread"
|
|
2
2
|
|
|
3
3
|
module Celluloid
|
|
4
4
|
class MailboxDead < Celluloid::Error; end # you can't receive from the dead
|
|
@@ -52,37 +52,38 @@ module Celluloid
|
|
|
52
52
|
|
|
53
53
|
@mutex.lock
|
|
54
54
|
begin
|
|
55
|
-
|
|
55
|
+
fail MailboxDead, "attempted to receive from a dead mailbox" if @dead
|
|
56
56
|
|
|
57
|
+
message = nil
|
|
57
58
|
Timers::Wait.for(timeout) do |remaining|
|
|
58
59
|
message = next_message(&block)
|
|
59
60
|
|
|
60
|
-
break
|
|
61
|
+
break if message
|
|
61
62
|
|
|
62
63
|
@condition.wait(@mutex, remaining)
|
|
63
64
|
end
|
|
64
65
|
ensure
|
|
65
66
|
@mutex.unlock rescue nil
|
|
66
67
|
end
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
|
|
69
|
+
message
|
|
69
70
|
end
|
|
70
71
|
|
|
71
72
|
# Receive a letter from the mailbox. Guaranteed to return a message. If
|
|
72
|
-
# timeout is exceeded, raise a
|
|
73
|
+
# timeout is exceeded, raise a TaskTimeout.
|
|
73
74
|
def receive(timeout = nil, &block)
|
|
75
|
+
message = nil
|
|
74
76
|
Timers::Wait.for(timeout) do |remaining|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
end
|
|
77
|
+
message = check(timeout, &block)
|
|
78
|
+
break if message
|
|
78
79
|
end
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
return message if message
|
|
81
|
+
fail TaskTimeout.new("receive timeout exceeded")
|
|
81
82
|
end
|
|
82
83
|
|
|
83
84
|
# Shut down this mailbox and clean up its contents
|
|
84
85
|
def shutdown
|
|
85
|
-
|
|
86
|
+
fail MailboxDead, "mailbox already shutdown" if @dead
|
|
86
87
|
|
|
87
88
|
@mutex.lock
|
|
88
89
|
begin
|
|
@@ -118,7 +119,7 @@ module Celluloid
|
|
|
118
119
|
|
|
119
120
|
# Inspect the contents of the Mailbox
|
|
120
121
|
def inspect
|
|
121
|
-
"#<#{self.class}:#{object_id.to_s(16)} @messages=[#{map
|
|
122
|
+
"#<#{self.class}:#{object_id.to_s(16)} @messages=[#{map(&:inspect).join(', ')}]>"
|
|
122
123
|
end
|
|
123
124
|
|
|
124
125
|
# Number of messages in the Mailbox
|
|
@@ -146,7 +147,7 @@ module Celluloid
|
|
|
146
147
|
end
|
|
147
148
|
|
|
148
149
|
def dead_letter(message)
|
|
149
|
-
Logger.debug "Discarded message (mailbox is dead): #{message}" if $CELLULOID_DEBUG
|
|
150
|
+
Internals::Logger.debug "Discarded message (mailbox is dead): #{message}" if $CELLULOID_DEBUG
|
|
150
151
|
end
|
|
151
152
|
|
|
152
153
|
def mailbox_full
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Celluloid
|
|
2
|
+
module Notices
|
|
3
|
+
class << self
|
|
4
|
+
@@notices = []
|
|
5
|
+
|
|
6
|
+
def backported
|
|
7
|
+
@@notices << [:info, "Celluloid #{Celluloid::VERSION} is running in BACKPORTED mode. [ http://git.io/vJf3J ]"]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def output
|
|
11
|
+
@@notices.each { |type, notice| Celluloid::Internals::Logger.send type, notice }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module Celluloid
|
|
2
|
+
module Proxy
|
|
3
|
+
require "celluloid/proxy/abstract"
|
|
4
|
+
require "celluloid/proxy/sync"
|
|
5
|
+
require "celluloid/proxy/cell"
|
|
6
|
+
require "celluloid/proxy/actor"
|
|
7
|
+
require "celluloid/proxy/async"
|
|
8
|
+
require "celluloid/proxy/future"
|
|
9
|
+
require "celluloid/proxy/block"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module Celluloid::Proxy
|
|
2
|
+
# Looks up the actual class of instance, even if instance is a proxy.
|
|
3
|
+
def self.class_of(instance)
|
|
4
|
+
(class << instance; self; end).superclass
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# Base class of Celluloid proxies
|
|
9
|
+
class Celluloid::Proxy::Abstract < BasicObject
|
|
10
|
+
# Needed for storing proxies in data structures
|
|
11
|
+
needed = [:object_id, :__id__, :hash, :eql?, :private_methods] - instance_methods
|
|
12
|
+
if needed.any?
|
|
13
|
+
include ::Kernel.dup.module_eval {
|
|
14
|
+
undef_method(*(instance_methods - needed))
|
|
15
|
+
self
|
|
16
|
+
}
|
|
17
|
+
# rubinius bug? These methods disappear when we include hacked kernel
|
|
18
|
+
define_method :==, ::BasicObject.instance_method(:==) unless instance_methods.include?(:==)
|
|
19
|
+
alias_method(:equal?, :==) unless instance_methods.include?(:equal?)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def __class__
|
|
23
|
+
@class ||= ::Celluloid::Proxy.class_of(self)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class Celluloid::Proxy::AbstractCall < Celluloid::Proxy::Abstract
|
|
28
|
+
attr_reader :mailbox
|
|
29
|
+
|
|
30
|
+
def initialize(mailbox, klass)
|
|
31
|
+
@mailbox = mailbox
|
|
32
|
+
@klass = klass
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def eql?(other)
|
|
36
|
+
self.__class__.eql?(::Celluloid::Proxy.class_of(other)) and @mailbox.eql?(other.mailbox)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def hash
|
|
40
|
+
@mailbox.hash
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def __klass__
|
|
44
|
+
@klass
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def inspect
|
|
48
|
+
"#<#{self.__class__}(#{@klass})>"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# A proxy which controls the Actor lifecycle
|
|
2
|
+
class Celluloid::Proxy::Actor < Celluloid::Proxy::Abstract
|
|
3
|
+
attr_reader :thread, :mailbox
|
|
4
|
+
|
|
5
|
+
def initialize(mailbox, thread)
|
|
6
|
+
@mailbox = mailbox
|
|
7
|
+
@thread = thread
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def inspect
|
|
11
|
+
# TODO: use a system event to fetch actor state: tasks?
|
|
12
|
+
"#<Celluloid::Proxy::Actor(#{@mailbox.address}) alive>"
|
|
13
|
+
rescue DeadActorError
|
|
14
|
+
"#<Celluloid::Proxy::Actor(#{@mailbox.address}) dead>"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def alive?
|
|
18
|
+
@mailbox.alive?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def dead?
|
|
22
|
+
!alive?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Terminate the associated actor
|
|
26
|
+
def terminate
|
|
27
|
+
terminate!
|
|
28
|
+
::Celluloid::Actor.join(self)
|
|
29
|
+
nil
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Terminate the associated actor asynchronously
|
|
33
|
+
def terminate!
|
|
34
|
+
::Kernel.raise ::Celluloid::DeadActorError, "actor already terminated" unless alive?
|
|
35
|
+
@mailbox << ::Celluloid::TerminationRequest.new
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# A proxy which sends asynchronous calls to an actor
|
|
2
|
+
class Celluloid::Proxy::Async < Celluloid::Proxy::AbstractCall
|
|
3
|
+
def method_missing(meth, *args, &block)
|
|
4
|
+
if @mailbox == ::Thread.current[:celluloid_mailbox]
|
|
5
|
+
args.unshift meth
|
|
6
|
+
meth = :__send__
|
|
7
|
+
end
|
|
8
|
+
if block_given?
|
|
9
|
+
# FIXME: nicer exception
|
|
10
|
+
fail "Cannot use blocks with async yet"
|
|
11
|
+
end
|
|
12
|
+
@mailbox << ::Celluloid::Call::Async.new(meth, args, block)
|
|
13
|
+
self
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
class Celluloid::Proxy::Block
|
|
2
|
+
attr_writer :execution
|
|
3
|
+
attr_reader :call, :block
|
|
4
|
+
|
|
5
|
+
def initialize(mailbox, call, block)
|
|
6
|
+
@mailbox = mailbox
|
|
7
|
+
@call = call
|
|
8
|
+
@block = block
|
|
9
|
+
@execution = :sender
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def to_proc
|
|
13
|
+
if @execution == :sender
|
|
14
|
+
lambda do |*values|
|
|
15
|
+
if task = Thread.current[:celluloid_task]
|
|
16
|
+
@mailbox << ::Celluloid::Call::Block.new(self, ::Celluloid::Actor.current.mailbox, values)
|
|
17
|
+
# TODO: if respond fails, the Task will never be resumed
|
|
18
|
+
task.suspend(:invokeblock)
|
|
19
|
+
else
|
|
20
|
+
# FIXME: better exception
|
|
21
|
+
fail "No task to suspend"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
else
|
|
25
|
+
@block
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
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
|
+
def initialize(mailbox, actor_proxy, klass)
|
|
5
|
+
super(mailbox, klass)
|
|
6
|
+
@actor_proxy = actor_proxy
|
|
7
|
+
@async_proxy = ::Celluloid::Proxy::Async.new(mailbox, klass)
|
|
8
|
+
@future_proxy = ::Celluloid::Proxy::Future.new(mailbox, klass)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def _send_(meth, *args, &block)
|
|
12
|
+
method_missing :__send__, meth, *args, &block
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def inspect
|
|
16
|
+
method_missing :inspect
|
|
17
|
+
rescue ::Celluloid::DeadActorError
|
|
18
|
+
"#<::Celluloid::Proxy::Cell(#{@klass}) dead>"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def method(name)
|
|
22
|
+
::Celluloid::Internals::Method.new(self, name)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
alias_method :sync, :method_missing
|
|
26
|
+
|
|
27
|
+
# Obtain an async proxy or explicitly invoke a named async method
|
|
28
|
+
def async(method_name = nil, *args, &block)
|
|
29
|
+
if method_name
|
|
30
|
+
@async_proxy.method_missing method_name, *args, &block
|
|
31
|
+
else
|
|
32
|
+
@async_proxy
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Obtain a future proxy or explicitly invoke a named future method
|
|
37
|
+
def future(method_name = nil, *args, &block)
|
|
38
|
+
if method_name
|
|
39
|
+
@future_proxy.method_missing method_name, *args, &block
|
|
40
|
+
else
|
|
41
|
+
@future_proxy
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def alive?
|
|
46
|
+
@actor_proxy.alive?
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def dead?
|
|
50
|
+
@actor_proxy.dead?
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def thread
|
|
54
|
+
@actor_proxy.thread
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Terminate the associated actor
|
|
58
|
+
def terminate
|
|
59
|
+
@actor_proxy.terminate
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Terminate the associated actor asynchronously
|
|
63
|
+
def terminate!
|
|
64
|
+
@actor_proxy.terminate!
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# A proxy which creates future calls to an actor
|
|
2
|
+
class Celluloid::Proxy::Future < Celluloid::Proxy::AbstractCall
|
|
3
|
+
def method_missing(meth, *args, &block)
|
|
4
|
+
unless @mailbox.alive?
|
|
5
|
+
fail ::Celluloid::DeadActorError, "attempted to call a dead actor: #{meth}"
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
if block_given?
|
|
9
|
+
# FIXME: nicer exception
|
|
10
|
+
fail "Cannot use blocks with futures yet"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
future = ::Celluloid::Future.new
|
|
14
|
+
call = ::Celluloid::Call::Sync.new(future, meth, args, block)
|
|
15
|
+
|
|
16
|
+
@mailbox << call
|
|
17
|
+
|
|
18
|
+
future
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# A proxy which sends synchronous calls to an actor
|
|
2
|
+
class Celluloid::Proxy::Sync < Celluloid::Proxy::AbstractCall
|
|
3
|
+
def respond_to?(meth, include_private = false)
|
|
4
|
+
__class__.instance_methods.include?(meth) || method_missing(:respond_to?, meth, include_private)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def method_missing(meth, *args, &block)
|
|
8
|
+
unless @mailbox.alive?
|
|
9
|
+
fail ::Celluloid::DeadActorError, "attempted to call a dead actor: #{meth}"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
if @mailbox == ::Thread.current[:celluloid_mailbox]
|
|
13
|
+
args.unshift meth
|
|
14
|
+
meth = :__send__
|
|
15
|
+
# actor = Thread.current[:celluloid_actor]
|
|
16
|
+
# actor = actor.behavior.subject.bare_object
|
|
17
|
+
# return actor.__send__(*args, &block)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
call = ::Celluloid::Call::Sync.new(::Celluloid.mailbox, meth, args, block)
|
|
21
|
+
@mailbox << call
|
|
22
|
+
call.value
|
|
23
|
+
end
|
|
24
|
+
end
|
data/lib/celluloid/rspec.rb
CHANGED
|
@@ -1,13 +1,71 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
3
|
-
|
|
4
|
-
require
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
require "dotenv"
|
|
2
|
+
require "nenv"
|
|
3
|
+
|
|
4
|
+
require "celluloid/test"
|
|
5
|
+
|
|
6
|
+
# To help produce better bug reports in Rubinius
|
|
7
|
+
if RUBY_ENGINE == "rbx"
|
|
8
|
+
# $DEBUG = true # would be nice if this didn't fail ... :(
|
|
9
|
+
require "rspec/matchers"
|
|
10
|
+
require "rspec/matchers/built_in/be"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
require "rspec/retry"
|
|
14
|
+
|
|
15
|
+
module Specs
|
|
16
|
+
|
|
17
|
+
CHECK_LOOSE_THREADS = !Nenv.ci? unless defined? CHECK_LOOSE_THREADS
|
|
18
|
+
ALLOW_RETRIES = 3 unless defined? ALLOW_RETRIES
|
|
19
|
+
|
|
20
|
+
INCLUDE_SUPPORT = [
|
|
21
|
+
"env",
|
|
22
|
+
"logging",
|
|
23
|
+
"sleep_and_wait",
|
|
24
|
+
"reset_class_variables",
|
|
25
|
+
"crash_checking",
|
|
26
|
+
"loose_threads",
|
|
27
|
+
"stubbing",
|
|
28
|
+
"coverage",
|
|
29
|
+
"includer",
|
|
30
|
+
"configure_rspec"
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
INCLUDE_PATHS = [
|
|
34
|
+
"./spec/support/*.rb",
|
|
35
|
+
"./spec/support/examples/*.rb",
|
|
36
|
+
"./spec/shared/*.rb"
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
MAX_EXECUTION = 13
|
|
40
|
+
MAX_ATTEMPTS = 20
|
|
41
|
+
|
|
42
|
+
TIMER_QUANTUM = 0.05 # Timer accuracy enforced by the tests (50ms)
|
|
43
|
+
|
|
44
|
+
BACKTRACE_OMITTED = [
|
|
45
|
+
"rspec-expectations",
|
|
46
|
+
"rspec-core",
|
|
47
|
+
"rspec-mocks",
|
|
48
|
+
"rspec-retry",
|
|
49
|
+
"rubysl-thread",
|
|
50
|
+
"rubysl-timeout"
|
|
51
|
+
]
|
|
9
52
|
end
|
|
10
53
|
|
|
11
54
|
$CELLULOID_DEBUG = true
|
|
12
55
|
|
|
13
|
-
|
|
56
|
+
# Require but disable, so it has to be explicitly enabled in tests
|
|
57
|
+
require "celluloid/probe"
|
|
58
|
+
$CELLULOID_MONITORING = false
|
|
59
|
+
|
|
60
|
+
Celluloid.shutdown_timeout = 1
|
|
61
|
+
|
|
62
|
+
# Load shared examples and test support code for other gems to use.
|
|
63
|
+
|
|
64
|
+
Specs::INCLUDE_SUPPORT.each { |f|
|
|
65
|
+
require "#{File.expand_path('../../../spec/support', __FILE__)}/#{f}.rb"
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
Specs.reset_probe(nil)
|
|
69
|
+
|
|
70
|
+
Dir["#{File.expand_path('../../../spec/support/examples', __FILE__)}/*.rb"].map { |f| require f }
|
|
71
|
+
Dir["#{File.expand_path('../../../spec/shared', __FILE__)}/*.rb"].map { |f| require f }
|