celluloid 0.16.0 → 0.17.0
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 +333 -0
- data/README.md +1 -1
- data/culture/CODE_OF_CONDUCT.md +28 -0
- data/culture/Gemfile +9 -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 +78 -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/rubocop.yml +4 -0
- data/culture/rubocop/style.yml +48 -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/timers.rb +72 -0
- data/lib/celluloid.rb +142 -127
- data/lib/celluloid/actor.rb +47 -41
- data/lib/celluloid/actor_system.rb +75 -22
- 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 +25 -114
- data/lib/celluloid/cell.rb +32 -20
- data/lib/celluloid/condition.rb +3 -3
- data/lib/celluloid/core_ext.rb +1 -1
- data/lib/celluloid/current.rb +2 -0
- data/lib/celluloid/deprecate.rb +18 -0
- data/lib/celluloid/exceptions.rb +1 -1
- data/lib/celluloid/fiber.rb +3 -3
- data/lib/celluloid/future.rb +7 -6
- data/lib/celluloid/group.rb +65 -0
- data/lib/celluloid/group/manager.rb +27 -0
- data/lib/celluloid/group/pool.rb +125 -0
- data/lib/celluloid/group/spawner.rb +71 -0
- data/lib/celluloid/logging.rb +5 -5
- data/lib/celluloid/mailbox.rb +14 -13
- data/lib/celluloid/mailbox/evented.rb +76 -0
- data/lib/celluloid/notices.rb +15 -0
- data/lib/celluloid/proxies.rb +12 -0
- data/lib/celluloid/proxy/abstract.rb +24 -0
- data/lib/celluloid/proxy/actor.rb +46 -0
- data/lib/celluloid/proxy/async.rb +36 -0
- data/lib/celluloid/proxy/block.rb +31 -0
- data/lib/celluloid/proxy/cell.rb +76 -0
- data/lib/celluloid/proxy/future.rb +40 -0
- data/lib/celluloid/proxy/sync.rb +44 -0
- data/lib/celluloid/rspec.rb +9 -10
- data/lib/celluloid/system_events.rb +16 -15
- data/lib/celluloid/{tasks.rb → task.rb} +21 -21
- data/lib/celluloid/task/fibered.rb +45 -0
- data/lib/celluloid/task/threaded.rb +59 -0
- data/lib/celluloid/test.rb +1 -1
- data/lib/celluloid/thread.rb +6 -1
- data/lib/celluloid/version.rb +3 -0
- data/spec/celluloid/actor_spec.rb +2 -2
- data/spec/celluloid/actor_system_spec.rb +35 -21
- data/spec/celluloid/block_spec.rb +3 -5
- data/spec/celluloid/calls_spec.rb +33 -11
- data/spec/celluloid/condition_spec.rb +16 -13
- data/spec/celluloid/evented_mailbox_spec.rb +1 -31
- data/spec/celluloid/future_spec.rb +13 -10
- data/spec/celluloid/group/elastic_spec.rb +0 -0
- data/spec/celluloid/group/manager_spec.rb +0 -0
- data/spec/celluloid/group/pool_spec.rb +8 -0
- data/spec/celluloid/group/spawner_spec.rb +8 -0
- data/spec/celluloid/mailbox/evented_spec.rb +27 -0
- data/spec/celluloid/mailbox_spec.rb +1 -3
- data/spec/celluloid/misc/leak_spec.rb +73 -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 +57 -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 +1237 -0
- data/spec/shared/group_examples.rb +121 -0
- data/{lib/celluloid/rspec → spec/shared}/mailbox_examples.rb +20 -17
- data/{lib/celluloid/rspec → spec/shared}/task_examples.rb +9 -8
- data/spec/spec_helper.rb +72 -16
- 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 +16 -0
- data/{lib/celluloid/rspec/example_actor_class.rb → spec/support/examples/actor_class.rb} +21 -2
- data/spec/support/examples/evented_mailbox_class.rb +27 -0
- data/spec/support/includer.rb +9 -0
- data/spec/support/logging.rb +63 -0
- data/spec/support/loose_threads.rb +65 -0
- data/spec/support/reset_class_variables.rb +27 -0
- data/spec/support/sleep_and_wait.rb +14 -0
- data/spec/support/split_logs.rb +1 -0
- data/spec/support/stubbing.rb +14 -0
- metadata +255 -95
- 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/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/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,65 @@
|
|
1
|
+
module Celluloid
|
2
|
+
class Group
|
3
|
+
class NotImplemented < StandardError; end
|
4
|
+
class StillActive < StandardError; end
|
5
|
+
class NotActive < StandardError; end
|
6
|
+
|
7
|
+
attr_accessor :group
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@mutex = Mutex.new
|
11
|
+
@group = []
|
12
|
+
@running = true
|
13
|
+
end
|
14
|
+
|
15
|
+
def assert_active
|
16
|
+
fail NotActive unless active?
|
17
|
+
end
|
18
|
+
|
19
|
+
def assert_inactive
|
20
|
+
return unless active?
|
21
|
+
if RUBY_PLATFORM == "java"
|
22
|
+
Celluloid.logger.warn "Group is still active"
|
23
|
+
else
|
24
|
+
fail StillActive
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def each
|
29
|
+
to_a.each { |thread| yield thread }
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_a
|
33
|
+
res = nil
|
34
|
+
@mutex.synchronize { res = @group.dup }
|
35
|
+
res
|
36
|
+
end
|
37
|
+
|
38
|
+
def purge(thread)
|
39
|
+
@mutex.synchronize do
|
40
|
+
@group.delete(thread)
|
41
|
+
thread.kill rescue nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def each_actor(&block)
|
46
|
+
to_a.lazy.select { |t| t[:celluloid_role] == :actor }.each(&block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def active?
|
50
|
+
@running
|
51
|
+
end
|
52
|
+
|
53
|
+
def get
|
54
|
+
fail NotImplemented
|
55
|
+
end
|
56
|
+
|
57
|
+
def create
|
58
|
+
fail NotImplemented
|
59
|
+
end
|
60
|
+
|
61
|
+
def shutdown
|
62
|
+
fail NotImplemented
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Celluloid
|
2
|
+
class Group
|
3
|
+
class Manager
|
4
|
+
include Celluloid
|
5
|
+
|
6
|
+
def manage!(group)
|
7
|
+
@group = group
|
8
|
+
every(1.26) { garbage_collector }
|
9
|
+
end
|
10
|
+
|
11
|
+
def garbage_collector
|
12
|
+
@group.each do |t|
|
13
|
+
puts "running Group::Manager garbage_collector"
|
14
|
+
# case t[:celluloid_meta][:state]
|
15
|
+
# when :finished
|
16
|
+
# # puts "thread finished: #{t.inspect}"
|
17
|
+
# else
|
18
|
+
# # puts "thread state: #{t[:celluloid_meta]}"
|
19
|
+
# end
|
20
|
+
# # puts "thread: #{t[:celluloid_actor].name}"
|
21
|
+
end
|
22
|
+
rescue => ex
|
23
|
+
puts "#{ex.backtrace.first}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require "thread"
|
2
|
+
|
3
|
+
module Celluloid
|
4
|
+
class Group
|
5
|
+
class Pool < Group
|
6
|
+
# You do not want to use this. Truly, you do not. There is no scenario when you will.
|
7
|
+
# But. If you somehow do.. `Celluloid.group_class = Celluloid::Group::Pool` and weep.
|
8
|
+
|
9
|
+
attr_accessor :max_idle
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
super
|
13
|
+
@mutex = Mutex.new
|
14
|
+
@idle_threads = []
|
15
|
+
@group = []
|
16
|
+
@busy_size = 0
|
17
|
+
@idle_size = 0
|
18
|
+
|
19
|
+
# TODO: should really adjust this based on usage
|
20
|
+
@max_idle = 16
|
21
|
+
end
|
22
|
+
|
23
|
+
def idle?
|
24
|
+
busy_size.count == 0
|
25
|
+
end
|
26
|
+
|
27
|
+
def busy?
|
28
|
+
busy_size.count > 0
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :busy_size
|
32
|
+
|
33
|
+
attr_reader :idle_size
|
34
|
+
|
35
|
+
# Get a thread from the pool, running the given block
|
36
|
+
def get(&block)
|
37
|
+
@mutex.synchronize do
|
38
|
+
assert_active
|
39
|
+
|
40
|
+
begin
|
41
|
+
if @idle_threads.empty?
|
42
|
+
thread = create
|
43
|
+
else
|
44
|
+
thread = @idle_threads.pop
|
45
|
+
@idle_size = @idle_threads.length
|
46
|
+
end
|
47
|
+
end until thread.status # handle crashed threads
|
48
|
+
|
49
|
+
thread.busy = true
|
50
|
+
@busy_size += 1
|
51
|
+
thread[:celluloid_queue] << block
|
52
|
+
thread
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Return a thread to the pool
|
57
|
+
def put(thread)
|
58
|
+
@mutex.synchronize do
|
59
|
+
thread.busy = false
|
60
|
+
if idle_size + 1 >= @max_idle
|
61
|
+
thread[:celluloid_queue] << nil
|
62
|
+
@busy_size -= 1
|
63
|
+
@group.delete(thread)
|
64
|
+
else
|
65
|
+
@idle_threads.push thread
|
66
|
+
@busy_size -= 1
|
67
|
+
@idle_size = @idle_threads.length
|
68
|
+
clean_thread_locals(thread)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def shutdown
|
74
|
+
@running = false
|
75
|
+
@mutex.synchronize do
|
76
|
+
finalize
|
77
|
+
@group.each do |thread|
|
78
|
+
thread[:celluloid_queue] << nil
|
79
|
+
end
|
80
|
+
@group.shift.kill until @group.empty?
|
81
|
+
@idle_threads.clear
|
82
|
+
@busy_size = 0
|
83
|
+
@idle_size = 0
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
# Create a new thread with an associated queue of procs to run
|
90
|
+
def create
|
91
|
+
queue = Queue.new
|
92
|
+
thread = Thread.new do
|
93
|
+
while proc = queue.pop
|
94
|
+
begin
|
95
|
+
proc.call
|
96
|
+
rescue Exception => ex
|
97
|
+
Internals::Logger.crash("thread crashed", ex)
|
98
|
+
ensure
|
99
|
+
put thread
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
thread[:celluloid_queue] = queue
|
105
|
+
# @idle_threads << thread
|
106
|
+
@group << thread
|
107
|
+
thread
|
108
|
+
end
|
109
|
+
|
110
|
+
# Clean the thread locals of an incoming thread
|
111
|
+
def clean_thread_locals(thread)
|
112
|
+
thread.keys.each do |key|
|
113
|
+
next if key == :celluloid_queue
|
114
|
+
|
115
|
+
# Ruby seems to lack an API for deleting thread locals. WTF, Ruby?
|
116
|
+
thread[key] = nil
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def finalize
|
121
|
+
@max_idle = 0
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,71 @@
|
|
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
|
+
@mutex.synchronize do
|
21
|
+
queue = Queue.new
|
22
|
+
loop do
|
23
|
+
break if @group.empty?
|
24
|
+
th = @group.shift
|
25
|
+
th.kill
|
26
|
+
queue << th
|
27
|
+
end
|
28
|
+
|
29
|
+
loop do
|
30
|
+
break if queue.empty?
|
31
|
+
queue.pop.join
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def idle?
|
37
|
+
to_a.select { |t| t[:celluloid_meta] && t[:celluloid_meta][:state] == :running }.empty?
|
38
|
+
end
|
39
|
+
|
40
|
+
def busy?
|
41
|
+
to_a.select { |t| t[:celluloid_meta] && t[:celluloid_meta][:state] == :running }.any?
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def instantiate(proc)
|
47
|
+
thread = Thread.new do
|
48
|
+
Thread.current[:celluloid_meta] = {
|
49
|
+
started: Time.now,
|
50
|
+
state: :running,
|
51
|
+
}
|
52
|
+
|
53
|
+
begin
|
54
|
+
proc.call
|
55
|
+
rescue Exception => ex
|
56
|
+
Internals::Logger.crash("thread crashed", ex)
|
57
|
+
Thread.current[:celluloid_meta][:state] = :error
|
58
|
+
ensure
|
59
|
+
unless Thread.current[:celluloid_meta][:state] == :error
|
60
|
+
Thread.current[:celluloid_meta][:state] = :finished
|
61
|
+
end
|
62
|
+
Thread.current[:celluloid_meta][:finished] = Time.now
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
@mutex.synchronize { @group << thread }
|
67
|
+
thread
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
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"
|
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
73
|
# timeout is exceeded, raise a TimeoutError.
|
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 TimeoutError.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,76 @@
|
|
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 IOError
|
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
|
+
rescue IOError
|
55
|
+
raise MailboxShutdown, "mailbox shutdown called during receive"
|
56
|
+
end
|
57
|
+
|
58
|
+
# Obtain the next message from the mailbox that matches the given block
|
59
|
+
def next_message(block)
|
60
|
+
@mutex.lock
|
61
|
+
begin
|
62
|
+
super(&block)
|
63
|
+
ensure
|
64
|
+
@mutex.unlock rescue nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Cleanup any IO objects this Mailbox may be using
|
69
|
+
def shutdown
|
70
|
+
super do
|
71
|
+
@reactor.shutdown
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|