celluloid 0.18.0.pre → 0.18.0.pre2
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 +5 -5
- data/CHANGES.md +114 -39
- data/CONDUCT.md +13 -0
- data/CONTRIBUTING.md +39 -0
- data/README.md +59 -55
- data/architecture.md +120 -0
- data/examples/basic_usage.rb +1 -1
- data/examples/configurations.rb +78 -0
- data/examples/futures.rb +1 -1
- data/examples/ring.rb +5 -4
- data/examples/simple_pmap.rb +1 -1
- data/examples/stack.rb +2 -2
- data/examples/supervisors_and_registry.rb +82 -0
- data/examples/timers.rb +1 -1
- data/lib/celluloid.rb +72 -47
- data/lib/celluloid/actor.rb +27 -17
- data/lib/celluloid/actor/system.rb +13 -29
- data/lib/celluloid/autostart.rb +5 -5
- data/lib/celluloid/backported.rb +6 -2
- data/lib/celluloid/call/async.rb +2 -0
- data/lib/celluloid/call/sync.rb +10 -3
- data/lib/celluloid/calls.rb +5 -12
- data/lib/celluloid/cell.rb +5 -9
- data/lib/celluloid/condition.rb +3 -3
- data/lib/celluloid/core_ext.rb +0 -2
- data/lib/celluloid/current.rb +3 -1
- data/lib/celluloid/debug.rb +3 -0
- data/lib/celluloid/exceptions.rb +2 -2
- data/lib/celluloid/future.rb +7 -9
- data/lib/celluloid/group.rb +12 -8
- data/lib/celluloid/group/pool.rb +1 -3
- data/lib/celluloid/group/spawner.rb +2 -6
- data/lib/celluloid/internals/call_chain.rb +15 -0
- data/lib/celluloid/internals/cpu_counter.rb +62 -0
- data/lib/celluloid/internals/handlers.rb +42 -0
- data/lib/celluloid/internals/links.rb +38 -0
- data/lib/celluloid/internals/logger.rb +104 -0
- data/lib/celluloid/internals/method.rb +34 -0
- data/lib/celluloid/internals/properties.rb +32 -0
- data/lib/celluloid/internals/receivers.rb +64 -0
- data/lib/celluloid/internals/registry.rb +102 -0
- data/lib/celluloid/internals/responses.rb +46 -0
- data/lib/celluloid/internals/signals.rb +24 -0
- data/lib/celluloid/internals/stack.rb +74 -0
- data/lib/celluloid/internals/stack/dump.rb +12 -0
- data/lib/celluloid/internals/stack/states.rb +72 -0
- data/lib/celluloid/internals/stack/summary.rb +12 -0
- data/lib/celluloid/internals/task_set.rb +51 -0
- data/lib/celluloid/internals/thread_handle.rb +52 -0
- data/lib/celluloid/internals/uuid.rb +40 -0
- data/lib/celluloid/logging/incident.rb +21 -0
- data/lib/celluloid/logging/incident_logger.rb +147 -0
- data/lib/celluloid/logging/incident_reporter.rb +49 -0
- data/lib/celluloid/logging/log_event.rb +20 -0
- data/lib/celluloid/logging/ring_buffer.rb +64 -0
- data/lib/celluloid/mailbox.rb +22 -9
- data/lib/celluloid/mailbox/evented.rb +13 -5
- data/lib/celluloid/managed.rb +6 -3
- data/lib/celluloid/notifications.rb +95 -0
- data/lib/celluloid/pool.rb +6 -0
- data/lib/celluloid/probe.rb +81 -0
- data/lib/celluloid/proxy/abstract.rb +9 -9
- data/lib/celluloid/proxy/async.rb +1 -1
- data/lib/celluloid/proxy/block.rb +2 -2
- data/lib/celluloid/proxy/cell.rb +1 -1
- data/lib/celluloid/proxy/future.rb +2 -4
- data/lib/celluloid/proxy/sync.rb +1 -3
- data/lib/celluloid/rspec.rb +22 -33
- data/lib/celluloid/supervision.rb +17 -0
- data/lib/celluloid/supervision/configuration.rb +169 -0
- data/lib/celluloid/supervision/configuration/injections.rb +8 -0
- data/lib/celluloid/supervision/configuration/instance.rb +113 -0
- data/lib/celluloid/supervision/constants.rb +123 -0
- data/lib/celluloid/supervision/container.rb +144 -0
- data/lib/celluloid/supervision/container/behavior.rb +89 -0
- data/lib/celluloid/supervision/container/behavior/pool.rb +71 -0
- data/lib/celluloid/supervision/container/behavior/tree.rb +23 -0
- data/lib/celluloid/supervision/container/injections.rb +8 -0
- data/lib/celluloid/supervision/container/instance.rb +116 -0
- data/lib/celluloid/supervision/container/pool.rb +210 -0
- data/{culture/rubocop/perf.yml → lib/celluloid/supervision/container/tree.rb} +0 -0
- data/lib/celluloid/supervision/deprecate.rb +9 -0
- data/lib/celluloid/supervision/deprecate/supervise.rb +105 -0
- data/lib/celluloid/supervision/deprecate/validation.rb +54 -0
- data/lib/celluloid/supervision/service.rb +27 -0
- data/lib/celluloid/supervision/supervise.rb +34 -0
- data/lib/celluloid/supervision/validation.rb +40 -0
- data/lib/celluloid/supervision/version.rb +5 -0
- data/lib/celluloid/system_events.rb +11 -6
- data/lib/celluloid/task.rb +25 -12
- data/lib/celluloid/task/fibered.rb +2 -0
- data/lib/celluloid/task/threaded.rb +3 -3
- data/lib/celluloid/test.rb +5 -2
- data/lib/celluloid/thread.rb +0 -2
- data/lib/celluloid/version.rb +1 -1
- data/spec/celluloid/block_spec.rb +29 -32
- data/spec/celluloid/calls_spec.rb +5 -15
- data/spec/celluloid/future_spec.rb +2 -2
- data/spec/celluloid/internals/cpu_counter_spec.rb +129 -0
- data/spec/celluloid/internals/links_spec.rb +43 -0
- data/spec/celluloid/internals/properties_spec.rb +40 -0
- data/spec/celluloid/internals/registry_spec.rb +62 -0
- data/spec/celluloid/internals/stack/dump_spec.rb +4 -0
- data/spec/celluloid/internals/stack/summary_spec.rb +4 -0
- data/spec/celluloid/internals/thread_handle_spec.rb +60 -0
- data/spec/celluloid/internals/uuid_spec.rb +9 -0
- data/spec/celluloid/logging/ring_buffer_spec.rb +36 -0
- data/spec/celluloid/mailbox/evented_spec.rb +11 -22
- data/spec/celluloid/misc/leak_spec.rb +3 -4
- data/spec/celluloid/notifications_spec.rb +140 -0
- data/spec/celluloid/probe_spec.rb +102 -0
- data/spec/celluloid/proxy_spec.rb +30 -30
- data/spec/celluloid/supervision/behavior_spec.rb +74 -0
- data/spec/celluloid/supervision/configuration_spec.rb +181 -0
- data/spec/celluloid/supervision/container_spec.rb +72 -0
- data/spec/celluloid/supervision/instance_spec.rb +13 -0
- data/spec/celluloid/supervision/root_spec.rb +28 -0
- data/spec/celluloid/supervision/supervisor_spec.rb +93 -0
- data/spec/celluloid/task/fibered_spec.rb +1 -3
- data/spec/celluloid/task/threaded_spec.rb +1 -3
- data/spec/shared/actor_examples.rb +58 -33
- data/spec/shared/group_examples.rb +2 -2
- data/spec/shared/mailbox_examples.rb +1 -1
- data/spec/shared/stack_examples.rb +87 -0
- data/spec/shared/task_examples.rb +2 -3
- data/spec/spec_helper.rb +2 -4
- data/spec/support/configure_rspec.rb +2 -3
- data/spec/support/coverage.rb +2 -4
- data/spec/support/crash_checking.rb +2 -2
- data/spec/support/examples/actor_class.rb +3 -8
- data/spec/support/examples/call_class.rb +2 -2
- data/spec/support/examples/container_class.rb +35 -0
- data/spec/support/examples/evented_mailbox_class.rb +1 -2
- data/spec/support/examples/stack_classes.rb +58 -0
- data/spec/support/examples/stack_methods.rb +23 -0
- data/spec/support/examples/subordinate_class.rb +19 -0
- data/spec/support/logging.rb +2 -34
- data/spec/support/loose_threads.rb +3 -16
- data/spec/support/reset_class_variables.rb +5 -1
- data/spec/support/stubbing.rb +1 -1
- metadata +91 -316
- data/culture/CONDUCT.md +0 -38
- data/culture/GSoC/1010-why_we_will_participate.md +0 -17
- data/culture/GSoC/1020-how_mentors_stay_engaged.md +0 -7
- data/culture/GSoC/1030-keeping_students_on_schedule.md +0 -9
- data/culture/GSoC/1040-getting_students_involved.md +0 -5
- data/culture/GSoC/1050-student_involvement_after.md +0 -5
- data/culture/GSoC/README.md +0 -16
- data/culture/Gemfile +0 -9
- data/culture/LICENSE.txt +0 -22
- data/culture/README.md +0 -22
- data/culture/Rakefile +0 -5
- data/culture/SYNC.md +0 -70
- data/culture/celluloid-culture.gemspec +0 -18
- data/culture/gems/README.md +0 -39
- data/culture/gems/dependencies.yml +0 -93
- data/culture/gems/loader.rb +0 -101
- data/culture/rubocop/README.md +0 -38
- data/culture/rubocop/lint.yml +0 -8
- data/culture/rubocop/metrics.yml +0 -15
- data/culture/rubocop/rubocop.yml +0 -5
- data/culture/rubocop/style.yml +0 -61
- data/culture/spec/gems_spec.rb +0 -2
- data/culture/spec/spec_helper.rb +0 -0
- data/culture/spec/sync_spec.rb +0 -2
- data/culture/sync.rb +0 -56
- data/culture/tasks/rspec.rake +0 -5
- data/culture/tasks/rubocop.rake +0 -2
- data/lib/celluloid/actor/manager.rb +0 -7
- data/lib/celluloid/deprecate.rb +0 -34
- data/lib/celluloid/fiber.rb +0 -32
- data/lib/celluloid/notices.rb +0 -15
- data/spec/deprecate/actor_system_spec.rb +0 -72
- data/spec/deprecate/block_spec.rb +0 -52
- data/spec/deprecate/calls_spec.rb +0 -39
- data/spec/deprecate/evented_mailbox_spec.rb +0 -34
- data/spec/deprecate/future_spec.rb +0 -32
- data/spec/deprecate/internal_pool_spec.rb +0 -4
- data/spec/support/env.rb +0 -21
data/lib/celluloid/group.rb
CHANGED
@@ -3,14 +3,14 @@ module Celluloid
|
|
3
3
|
attr_accessor :group
|
4
4
|
|
5
5
|
def initialize
|
6
|
-
@pid =
|
6
|
+
@pid = $PROCESS_ID
|
7
7
|
@mutex = Mutex.new
|
8
8
|
@group = []
|
9
9
|
@running = true
|
10
10
|
end
|
11
11
|
|
12
12
|
def assert_active
|
13
|
-
|
13
|
+
raise Celluloid::NotActive unless active?
|
14
14
|
end
|
15
15
|
|
16
16
|
def assert_inactive
|
@@ -18,7 +18,7 @@ module Celluloid
|
|
18
18
|
if RUBY_PLATFORM == "java"
|
19
19
|
Celluloid.logger.warn "Group is still active"
|
20
20
|
else
|
21
|
-
|
21
|
+
raise Celluloid::StillActive
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -27,7 +27,7 @@ module Celluloid
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def forked?
|
30
|
-
@pid !=
|
30
|
+
@pid != $PROCESS_ID
|
31
31
|
end
|
32
32
|
|
33
33
|
def to_a
|
@@ -40,7 +40,11 @@ module Celluloid
|
|
40
40
|
def purge(thread)
|
41
41
|
@mutex.synchronize do
|
42
42
|
@group.delete(thread)
|
43
|
-
|
43
|
+
begin
|
44
|
+
thread.kill
|
45
|
+
rescue
|
46
|
+
nil
|
47
|
+
end
|
44
48
|
end
|
45
49
|
end
|
46
50
|
|
@@ -53,15 +57,15 @@ module Celluloid
|
|
53
57
|
end
|
54
58
|
|
55
59
|
def get
|
56
|
-
|
60
|
+
raise NotImplementedError
|
57
61
|
end
|
58
62
|
|
59
63
|
def create
|
60
|
-
|
64
|
+
raise NotImplementedError
|
61
65
|
end
|
62
66
|
|
63
67
|
def shutdown
|
64
|
-
|
68
|
+
raise NotImplementedError
|
65
69
|
end
|
66
70
|
end
|
67
71
|
end
|
data/lib/celluloid/group/pool.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require "thread"
|
2
|
-
|
3
1
|
module Celluloid
|
4
2
|
class Group
|
5
3
|
class Spawner < Group
|
@@ -11,7 +9,7 @@ module Celluloid
|
|
11
9
|
|
12
10
|
def get(&block)
|
13
11
|
assert_active
|
14
|
-
|
12
|
+
raise ArgumentError, "No block sent to Spawner.get()" unless block_given?
|
15
13
|
instantiate block
|
16
14
|
end
|
17
15
|
|
@@ -52,9 +50,7 @@ module Celluloid
|
|
52
50
|
Internals::Logger.crash("thread crashed", ex)
|
53
51
|
Thread.current[:celluloid_thread_state] = :error
|
54
52
|
ensure
|
55
|
-
unless Thread.current[:celluloid_thread_state] == :error
|
56
|
-
Thread.current[:celluloid_thread_state] = :finished
|
57
|
-
end
|
53
|
+
Thread.current[:celluloid_thread_state] = :finished unless Thread.current[:celluloid_thread_state] == :error
|
58
54
|
@mutex.synchronize { @group.delete Thread.current }
|
59
55
|
Thread.exit
|
60
56
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Celluloid
|
2
|
+
module Internals
|
3
|
+
class CallChain
|
4
|
+
def self.current_id=(value)
|
5
|
+
Thread.current[:celluloid_chain_id] = value
|
6
|
+
task = Thread.current[:celluloid_task]
|
7
|
+
task.chain_id = value if task
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.current_id
|
11
|
+
Thread.current[:celluloid_chain_id]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Celluloid
|
2
|
+
module Internals
|
3
|
+
module CPUCounter
|
4
|
+
class << self
|
5
|
+
def cores
|
6
|
+
@cores ||= count_cores
|
7
|
+
end
|
8
|
+
|
9
|
+
def count_cores
|
10
|
+
from_result(from_env || from_sysdev || from_java || from_proc || from_win32ole || from_sysctl) || 1
|
11
|
+
end
|
12
|
+
|
13
|
+
def from_env
|
14
|
+
result = ENV["NUMBER_OF_PROCESSORS"]
|
15
|
+
result if result && !result.empty?
|
16
|
+
rescue
|
17
|
+
end
|
18
|
+
|
19
|
+
def from_sysdev
|
20
|
+
::IO.read("/sys/devices/system/cpu/present").split("-").last.to_i + 1
|
21
|
+
rescue Errno::ENOENT
|
22
|
+
begin
|
23
|
+
result = Dir["/sys/devices/system/cpu/cpu*"].count { |n| n =~ /cpu\d+/ }
|
24
|
+
result unless result.zero?
|
25
|
+
rescue
|
26
|
+
end
|
27
|
+
rescue
|
28
|
+
end
|
29
|
+
|
30
|
+
def from_java
|
31
|
+
Java::Java.lang.Runtime.getRuntime.availableProcessors if defined? Java::Java
|
32
|
+
rescue
|
33
|
+
end
|
34
|
+
|
35
|
+
def from_proc
|
36
|
+
File.read("/proc/cpuinfo").scan(/^processor\s*:/).size if File.exist?("/proc/cpuinfo")
|
37
|
+
rescue
|
38
|
+
end
|
39
|
+
|
40
|
+
def from_win32ole
|
41
|
+
require "win32ole"
|
42
|
+
WIN32OLE.connect("winmgmts://").ExecQuery("select * from Win32_ComputerSystem").NumberOfProcessors
|
43
|
+
rescue LoadError
|
44
|
+
rescue
|
45
|
+
end
|
46
|
+
|
47
|
+
def from_sysctl
|
48
|
+
Integer `sysctl -n hw.ncpu 2>/dev/null`
|
49
|
+
rescue
|
50
|
+
end
|
51
|
+
|
52
|
+
def from_result(result)
|
53
|
+
if result
|
54
|
+
i = Integer(result.to_s[/\d+/], 10)
|
55
|
+
return i if i > 0
|
56
|
+
end
|
57
|
+
rescue
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "set"
|
2
|
+
|
3
|
+
module Celluloid
|
4
|
+
module Internals
|
5
|
+
class Handlers
|
6
|
+
def initialize
|
7
|
+
@handlers = Set.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def handle(*patterns, &block)
|
11
|
+
patterns.each do |pattern|
|
12
|
+
handler = Handler.new pattern, block
|
13
|
+
@handlers << handler
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Handle incoming messages
|
18
|
+
def handle_message(message)
|
19
|
+
handler = @handlers.find { |h| h.match(message) }
|
20
|
+
handler.call(message) if handler
|
21
|
+
handler
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Methods blocking on a call to receive
|
26
|
+
class Handler
|
27
|
+
def initialize(pattern, block)
|
28
|
+
@pattern = pattern
|
29
|
+
@block = block
|
30
|
+
end
|
31
|
+
|
32
|
+
# Match a message with this receiver's block
|
33
|
+
def match(message)
|
34
|
+
@pattern === message
|
35
|
+
end
|
36
|
+
|
37
|
+
def call(message)
|
38
|
+
@block.call message
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Celluloid
|
2
|
+
module Internals
|
3
|
+
# Linked actors send each other system events
|
4
|
+
class Links
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@links = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
# Add an actor to the current links
|
12
|
+
def <<(actor)
|
13
|
+
@links[actor.mailbox.address] = actor
|
14
|
+
end
|
15
|
+
|
16
|
+
# Do links include the given actor?
|
17
|
+
def include?(actor)
|
18
|
+
@links.key? actor.mailbox.address
|
19
|
+
end
|
20
|
+
|
21
|
+
# Remove an actor from the links
|
22
|
+
def delete(actor)
|
23
|
+
@links.delete actor.mailbox.address
|
24
|
+
end
|
25
|
+
|
26
|
+
# Iterate through all links
|
27
|
+
def each
|
28
|
+
@links.each { |_, actor| yield(actor) }
|
29
|
+
end
|
30
|
+
|
31
|
+
# Generate a string representation
|
32
|
+
def inspect
|
33
|
+
links = map(&:inspect).join(",")
|
34
|
+
"#<#{self.class}[#{links}]>"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Celluloid
|
2
|
+
module Internals
|
3
|
+
module Logger
|
4
|
+
class WithBacktrace
|
5
|
+
def initialize(backtrace)
|
6
|
+
@backtrace = backtrace
|
7
|
+
end
|
8
|
+
|
9
|
+
def debug(string)
|
10
|
+
# !!! DO NOT INTRODUCE ADDITIONAL GLOBAL VARIABLES !!!
|
11
|
+
# rubocop:disable Style/GlobalVars
|
12
|
+
Celluloid.logger.debug(decorate(string)) if $CELLULOID_DEBUG
|
13
|
+
# rubocop:enable Style/GlobalVars
|
14
|
+
end
|
15
|
+
|
16
|
+
def info(string)
|
17
|
+
Celluloid.logger.info(decorate(string))
|
18
|
+
end
|
19
|
+
|
20
|
+
def warn(string)
|
21
|
+
Celluloid.logger.warn(decorate(string))
|
22
|
+
end
|
23
|
+
|
24
|
+
def error(string)
|
25
|
+
Celluloid.logger.error(decorate(string))
|
26
|
+
end
|
27
|
+
|
28
|
+
def decorate(string)
|
29
|
+
[string, @backtrace].join("\n\t")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
@exception_handlers = []
|
34
|
+
|
35
|
+
module_function
|
36
|
+
|
37
|
+
def with_backtrace(backtrace)
|
38
|
+
yield WithBacktrace.new(backtrace) if Celluloid.logger
|
39
|
+
end
|
40
|
+
|
41
|
+
# Send a debug message
|
42
|
+
def debug(string)
|
43
|
+
# !!! DO NOT INTRODUCE ADDITIONAL GLOBAL VARIABLES !!!
|
44
|
+
# rubocop:disable Style/GlobalVars
|
45
|
+
Celluloid.logger.debug(string) if Celluloid.logger && $CELLULOID_DEBUG
|
46
|
+
# rubocop:enable Style/GlobalVars
|
47
|
+
end
|
48
|
+
|
49
|
+
# Send a info message
|
50
|
+
def info(string)
|
51
|
+
Celluloid.logger.info(string) if Celluloid.logger
|
52
|
+
end
|
53
|
+
|
54
|
+
# Send a warning message
|
55
|
+
def warn(string)
|
56
|
+
Celluloid.logger.warn(string) if Celluloid.logger
|
57
|
+
end
|
58
|
+
|
59
|
+
# Send an error message
|
60
|
+
def error(string)
|
61
|
+
Celluloid.logger.error(string) if Celluloid.logger
|
62
|
+
end
|
63
|
+
|
64
|
+
# Handle a crash
|
65
|
+
def crash(string, exception)
|
66
|
+
if Celluloid.log_actor_crashes
|
67
|
+
string << "\n" << format_exception(exception)
|
68
|
+
error string
|
69
|
+
end
|
70
|
+
|
71
|
+
@exception_handlers.each do |handler|
|
72
|
+
begin
|
73
|
+
handler.call(exception)
|
74
|
+
rescue => ex
|
75
|
+
error "EXCEPTION HANDLER CRASHED:\n" << format_exception(ex)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Note a deprecation
|
81
|
+
def deprecate(message)
|
82
|
+
trace = caller.join("\n\t")
|
83
|
+
warn "DEPRECATION WARNING: #{message}\n\t#{trace}"
|
84
|
+
end
|
85
|
+
|
86
|
+
# Define an exception handler
|
87
|
+
# NOTE: These should be defined at application start time
|
88
|
+
def exception_handler(&block)
|
89
|
+
@exception_handlers << block
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
|
93
|
+
# Format an exception message
|
94
|
+
def format_exception(exception)
|
95
|
+
str = "#{exception.class}: #{exception}\n\t"
|
96
|
+
str << if exception.backtrace
|
97
|
+
exception.backtrace.join("\n\t")
|
98
|
+
else
|
99
|
+
"EMPTY BACKTRACE\n\t"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Celluloid
|
2
|
+
module Internals
|
3
|
+
# Method handles that route through an actor proxy
|
4
|
+
class Method
|
5
|
+
def initialize(proxy, name)
|
6
|
+
raise NoMethodError, "undefined method `#{name}'" unless proxy.respond_to? name
|
7
|
+
|
8
|
+
@proxy = proxy
|
9
|
+
@name = name
|
10
|
+
@klass = @proxy.class
|
11
|
+
end
|
12
|
+
|
13
|
+
def arity
|
14
|
+
@proxy.method_missing(:method, @name).arity
|
15
|
+
end
|
16
|
+
|
17
|
+
def name
|
18
|
+
@proxy.method_missing(:method, @name).name
|
19
|
+
end
|
20
|
+
|
21
|
+
def parameters
|
22
|
+
@proxy.method_missing(:method, @name).parameters
|
23
|
+
end
|
24
|
+
|
25
|
+
def call(*args, &block)
|
26
|
+
@proxy.__send__(@name, *args, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
def inspect
|
30
|
+
"#<Celluloid::Internals::Method #{@klass}##{@name}>"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Celluloid
|
2
|
+
module Internals
|
3
|
+
# Properties define inheritable attributes of classes, somewhat similar to
|
4
|
+
# Rails cattr_*/mattr_* or class_attribute
|
5
|
+
module Properties
|
6
|
+
def property(name, opts = {})
|
7
|
+
default = opts.fetch(:default, nil)
|
8
|
+
multi = opts.fetch(:multi, false)
|
9
|
+
ivar_name = "@#{name}".to_sym
|
10
|
+
|
11
|
+
singleton = class << ancestors.first; self; end
|
12
|
+
begin
|
13
|
+
singleton.send(:remove_method, name)
|
14
|
+
rescue
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
singleton.send(:define_method, name) do |value = nil, *extra|
|
18
|
+
if value
|
19
|
+
value = value ? [value, *send(name), *extra].uniq : [] if multi
|
20
|
+
instance_variable_set(ivar_name, value)
|
21
|
+
elsif instance_variables.include?(ivar_name)
|
22
|
+
instance_variable_get(ivar_name)
|
23
|
+
elsif superclass.respond_to? name
|
24
|
+
superclass.send(name)
|
25
|
+
else
|
26
|
+
default
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "set"
|
2
|
+
require "timers"
|
3
|
+
|
4
|
+
module Celluloid
|
5
|
+
module Internals
|
6
|
+
# Allow methods to directly interact with the actor protocol
|
7
|
+
class Receivers
|
8
|
+
def initialize(timers)
|
9
|
+
@receivers = Set.new
|
10
|
+
@timers = timers
|
11
|
+
end
|
12
|
+
|
13
|
+
# Receive an asynchronous message
|
14
|
+
def receive(timeout = nil, &block)
|
15
|
+
if Celluloid.exclusive?
|
16
|
+
Celluloid.mailbox.receive(timeout, &block)
|
17
|
+
else
|
18
|
+
receiver = Receiver.new block
|
19
|
+
|
20
|
+
if timeout
|
21
|
+
receiver.timer = @timers.after(timeout) do
|
22
|
+
@receivers.delete receiver
|
23
|
+
receiver.resume
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
@receivers << receiver
|
28
|
+
Task.suspend :receiving
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Handle incoming messages
|
33
|
+
def handle_message(message)
|
34
|
+
receiver = @receivers.find { |r| r.match(message) }
|
35
|
+
return unless receiver
|
36
|
+
|
37
|
+
@receivers.delete receiver
|
38
|
+
receiver.timer.cancel if receiver.timer
|
39
|
+
receiver.resume message
|
40
|
+
message
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Methods blocking on a call to receive
|
45
|
+
class Receiver
|
46
|
+
attr_accessor :timer
|
47
|
+
|
48
|
+
def initialize(block)
|
49
|
+
@block = block
|
50
|
+
@task = Task.current
|
51
|
+
@timer = nil
|
52
|
+
end
|
53
|
+
|
54
|
+
# Match a message with this receiver's block
|
55
|
+
def match(message)
|
56
|
+
@block ? @block.call(message) : true
|
57
|
+
end
|
58
|
+
|
59
|
+
def resume(message = nil)
|
60
|
+
@task.resume message
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|