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
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
shared_context "a Celluloid Mailbox" do
|
|
2
|
-
after do
|
|
3
|
-
Celluloid.logger.stub(:debug)
|
|
4
|
-
subject.shutdown if subject.alive?
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
it "receives messages" do
|
|
8
|
-
message = :ohai
|
|
9
|
-
|
|
10
|
-
subject << message
|
|
11
|
-
subject.receive.should == message
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
it "prioritizes system events over other messages" do
|
|
15
|
-
subject << :dummy1
|
|
16
|
-
subject << :dummy2
|
|
17
|
-
|
|
18
|
-
subject << Celluloid::SystemEvent.new
|
|
19
|
-
subject.receive.should be_a(Celluloid::SystemEvent)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
it "selectively receives messages with a block" do
|
|
23
|
-
class Foo; end
|
|
24
|
-
class Bar; end
|
|
25
|
-
class Baz; end
|
|
26
|
-
|
|
27
|
-
foo, bar, baz = Foo.new, Bar.new, Baz.new
|
|
28
|
-
|
|
29
|
-
subject << baz
|
|
30
|
-
subject << foo
|
|
31
|
-
subject << bar
|
|
32
|
-
|
|
33
|
-
subject.receive { |msg| msg.is_a? Foo }.should eq(foo)
|
|
34
|
-
subject.receive { |msg| msg.is_a? Bar }.should eq(bar)
|
|
35
|
-
subject.receive.should eq(baz)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
it "waits for a given timeout interval" do
|
|
39
|
-
interval = 0.1
|
|
40
|
-
started_at = Time.now
|
|
41
|
-
|
|
42
|
-
expect do
|
|
43
|
-
subject.receive(interval) { false }
|
|
44
|
-
end.to raise_exception(Celluloid::TimeoutError)
|
|
45
|
-
|
|
46
|
-
(Time.now - started_at).should be_within(Celluloid::TIMER_QUANTUM).of interval
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
it "has a size" do
|
|
50
|
-
subject.should respond_to(:size)
|
|
51
|
-
subject.size.should be_zero
|
|
52
|
-
subject << :foo
|
|
53
|
-
subject << :foo
|
|
54
|
-
subject.should have(2).entries
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
it "discards messages received when when full" do
|
|
58
|
-
subject.max_size = 2
|
|
59
|
-
subject << :first
|
|
60
|
-
subject << :second
|
|
61
|
-
subject << :third
|
|
62
|
-
subject.to_a.should =~ [:first, :second]
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
it "logs discarded messages" do
|
|
66
|
-
Celluloid.logger.should_receive(:debug).with("Discarded message (mailbox is dead): third")
|
|
67
|
-
|
|
68
|
-
subject.max_size = 2
|
|
69
|
-
subject << :first
|
|
70
|
-
subject << :second
|
|
71
|
-
subject << :third
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
it "discard messages when dead" do
|
|
75
|
-
Celluloid.logger.should_receive(:debug).with("Discarded message (mailbox is dead): first")
|
|
76
|
-
Celluloid.logger.should_receive(:debug).with("Discarded message (mailbox is dead): second")
|
|
77
|
-
Celluloid.logger.should_receive(:debug).with("Discarded message (mailbox is dead): third")
|
|
78
|
-
|
|
79
|
-
subject << :first
|
|
80
|
-
subject << :second
|
|
81
|
-
subject.shutdown
|
|
82
|
-
subject << :third
|
|
83
|
-
end
|
|
84
|
-
end
|
data/lib/celluloid/signals.rb
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
module Celluloid
|
|
2
|
-
# Event signaling between methods of the same object
|
|
3
|
-
class Signals
|
|
4
|
-
def initialize
|
|
5
|
-
@conditions = {}
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
# Wait for the given signal and return the associated value
|
|
9
|
-
def wait(name)
|
|
10
|
-
raise "cannot wait for signals while exclusive" if Celluloid.exclusive?
|
|
11
|
-
|
|
12
|
-
@conditions[name] ||= Condition.new
|
|
13
|
-
@conditions[name].wait
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# Send a signal to all method calls waiting for the given name
|
|
17
|
-
def broadcast(name, value = nil)
|
|
18
|
-
if condition = @conditions.delete(name)
|
|
19
|
-
condition.broadcast(value)
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
data/lib/celluloid/stack_dump.rb
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
module Celluloid
|
|
2
|
-
class StackDump
|
|
3
|
-
module DisplayBacktrace
|
|
4
|
-
def display_backtrace(backtrace, output, indent = nil)
|
|
5
|
-
backtrace ||= ["EMPTY BACKTRACE"]
|
|
6
|
-
backtrace.each do |line|
|
|
7
|
-
output << indent if indent
|
|
8
|
-
output << "\t" << line << "\n"
|
|
9
|
-
end
|
|
10
|
-
output << "\n\n"
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
class TaskState < Struct.new(:task_class, :type, :meta, :status, :backtrace)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
class ActorState
|
|
18
|
-
include DisplayBacktrace
|
|
19
|
-
attr_accessor :name, :id, :cell
|
|
20
|
-
attr_accessor :status, :tasks
|
|
21
|
-
attr_accessor :backtrace
|
|
22
|
-
|
|
23
|
-
def dump
|
|
24
|
-
string = ""
|
|
25
|
-
string << "Celluloid::Actor 0x#{id.to_s(16)}"
|
|
26
|
-
string << " [#{name}]" if name
|
|
27
|
-
string << "\n"
|
|
28
|
-
|
|
29
|
-
if cell
|
|
30
|
-
string << cell.dump
|
|
31
|
-
string << "\n"
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
if status == :idle
|
|
35
|
-
string << "State: Idle (waiting for messages)\n"
|
|
36
|
-
display_backtrace backtrace, string
|
|
37
|
-
else
|
|
38
|
-
string << "State: Running (executing tasks)\n"
|
|
39
|
-
display_backtrace backtrace, string
|
|
40
|
-
string << "\tTasks:\n"
|
|
41
|
-
|
|
42
|
-
tasks.each_with_index do |task, i|
|
|
43
|
-
string << "\t #{i+1}) #{task.task_class}[#{task.type}]: #{task.status}\n"
|
|
44
|
-
string << "\t #{task.meta.inspect}\n"
|
|
45
|
-
display_backtrace task.backtrace, string, "\t"
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
string
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
class CellState < Struct.new(:subject_id, :subject_class)
|
|
54
|
-
def dump
|
|
55
|
-
"Celluloid::Cell 0x#{subject_id.to_s(16)}: #{subject_class}"
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
class ThreadState < Struct.new(:thread_id, :backtrace, :role)
|
|
60
|
-
include DisplayBacktrace
|
|
61
|
-
|
|
62
|
-
def dump
|
|
63
|
-
string = ""
|
|
64
|
-
string << "Thread 0x#{thread_id.to_s(16)} (#{role}):\n"
|
|
65
|
-
display_backtrace backtrace, string
|
|
66
|
-
string
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
attr_accessor :actors, :threads
|
|
71
|
-
|
|
72
|
-
def initialize(internal_pool)
|
|
73
|
-
@internal_pool = internal_pool
|
|
74
|
-
|
|
75
|
-
@actors = []
|
|
76
|
-
@threads = []
|
|
77
|
-
|
|
78
|
-
snapshot
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def snapshot
|
|
82
|
-
@internal_pool.each do |thread|
|
|
83
|
-
if thread.role == :actor
|
|
84
|
-
@actors << snapshot_actor(thread.actor) if thread.actor
|
|
85
|
-
else
|
|
86
|
-
@threads << snapshot_thread(thread)
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def snapshot_actor(actor)
|
|
92
|
-
state = ActorState.new
|
|
93
|
-
state.id = actor.object_id
|
|
94
|
-
|
|
95
|
-
# TODO: delegate to the behavior
|
|
96
|
-
if actor.behavior.is_a?(Cell)
|
|
97
|
-
state.cell = snapshot_cell(actor.behavior)
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
tasks = actor.tasks
|
|
101
|
-
if tasks.empty?
|
|
102
|
-
state.status = :idle
|
|
103
|
-
else
|
|
104
|
-
state.status = :running
|
|
105
|
-
state.tasks = tasks.to_a.map { |t| TaskState.new(t.class, t.type, t.meta, t.status, t.backtrace) }
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
state.backtrace = actor.thread.backtrace if actor.thread
|
|
109
|
-
state
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def snapshot_cell(behavior)
|
|
113
|
-
state = CellState.new
|
|
114
|
-
state.subject_id = behavior.subject.object_id
|
|
115
|
-
state.subject_class = behavior.subject.class
|
|
116
|
-
state
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
def snapshot_thread(thread)
|
|
120
|
-
ThreadState.new(thread.object_id, thread.backtrace, thread.role)
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
def print(output = STDERR)
|
|
124
|
-
@actors.each do |actor|
|
|
125
|
-
output.print actor.dump
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
@threads.each do |thread|
|
|
129
|
-
output.print thread.dump
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
end
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
module Celluloid
|
|
2
|
-
# Supervise collections of actors as a group
|
|
3
|
-
class SupervisionGroup
|
|
4
|
-
include Celluloid
|
|
5
|
-
trap_exit :restart_actor
|
|
6
|
-
|
|
7
|
-
class << self
|
|
8
|
-
|
|
9
|
-
# Actors or sub-applications to be supervised
|
|
10
|
-
def blocks
|
|
11
|
-
@blocks ||= []
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Start this application (and watch it with a supervisor)
|
|
15
|
-
def run!(registry = nil)
|
|
16
|
-
group = new(registry) do |_group|
|
|
17
|
-
blocks.each do |block|
|
|
18
|
-
block.call(_group)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
group
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Run the application in the foreground with a simple watchdog
|
|
25
|
-
def run(registry = nil)
|
|
26
|
-
loop do
|
|
27
|
-
supervisor = run!(registry)
|
|
28
|
-
|
|
29
|
-
# Take five, toplevel supervisor
|
|
30
|
-
sleep 5 while supervisor.alive?
|
|
31
|
-
|
|
32
|
-
Logger.error "!!! Celluloid::SupervisionGroup #{self} crashed. Restarting..."
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Register an actor class or a sub-group to be launched and supervised
|
|
37
|
-
# Available options are:
|
|
38
|
-
#
|
|
39
|
-
# * as: register this application in the Celluloid::Actor[] directory
|
|
40
|
-
# * args: start the actor with the given arguments
|
|
41
|
-
def supervise(klass, options = {})
|
|
42
|
-
blocks << lambda do |group|
|
|
43
|
-
group.add klass, options
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# Register a pool of actors to be launched on group startup
|
|
48
|
-
# Available options are:
|
|
49
|
-
#
|
|
50
|
-
# * as: register this application in the Celluloid::Actor[] directory
|
|
51
|
-
# * args: start the actor pool with the given arguments
|
|
52
|
-
def pool(klass, options = {})
|
|
53
|
-
blocks << lambda do |group|
|
|
54
|
-
group.pool klass, options
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
finalizer :finalize
|
|
60
|
-
|
|
61
|
-
# Start the group
|
|
62
|
-
def initialize(registry = nil)
|
|
63
|
-
@members = []
|
|
64
|
-
@registry = registry || Celluloid.actor_system.registry
|
|
65
|
-
|
|
66
|
-
yield current_actor if block_given?
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
execute_block_on_receiver :initialize, :supervise, :supervise_as
|
|
70
|
-
|
|
71
|
-
def supervise(klass, *args, &block)
|
|
72
|
-
add(klass, :args => args, :block => block)
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def supervise_as(name, klass, *args, &block)
|
|
76
|
-
add(klass, :args => args, :block => block, :as => name)
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def pool(klass, options = {})
|
|
80
|
-
options[:method] = 'pool_link'
|
|
81
|
-
add(klass, options)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def add(klass, options)
|
|
85
|
-
member = Member.new(@registry, klass, options)
|
|
86
|
-
@members << member
|
|
87
|
-
member.actor
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def actors
|
|
91
|
-
@members.map(&:actor)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def [](actor_name)
|
|
95
|
-
@registry[actor_name]
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
# Restart a crashed actor
|
|
99
|
-
def restart_actor(actor, reason)
|
|
100
|
-
member = @members.find do |_member|
|
|
101
|
-
_member.actor == actor
|
|
102
|
-
end
|
|
103
|
-
raise "a group member went missing. This shouldn't be!" unless member
|
|
104
|
-
|
|
105
|
-
if reason
|
|
106
|
-
member.restart
|
|
107
|
-
else
|
|
108
|
-
member.cleanup
|
|
109
|
-
@members.delete(member)
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
# A member of the group
|
|
114
|
-
class Member
|
|
115
|
-
def initialize(registry, klass, options = {})
|
|
116
|
-
@registry = registry
|
|
117
|
-
@klass = klass
|
|
118
|
-
|
|
119
|
-
# Stringify keys :/
|
|
120
|
-
options = options.inject({}) { |h,(k,v)| h[k.to_s] = v; h }
|
|
121
|
-
|
|
122
|
-
@name = options['as']
|
|
123
|
-
@block = options['block']
|
|
124
|
-
@args = options['args'] ? Array(options['args']) : []
|
|
125
|
-
@method = options['method'] || 'new_link'
|
|
126
|
-
@pool = @method == 'pool_link'
|
|
127
|
-
@pool_size = options['size'] if @pool
|
|
128
|
-
|
|
129
|
-
start
|
|
130
|
-
end
|
|
131
|
-
attr_reader :name, :actor
|
|
132
|
-
|
|
133
|
-
def start
|
|
134
|
-
# when it is a pool, then we don't splat the args
|
|
135
|
-
# and we need to extract the pool size if set
|
|
136
|
-
if @pool
|
|
137
|
-
options = {:args => @args}
|
|
138
|
-
options[:size] = @pool_size if @pool_size
|
|
139
|
-
@args = [options]
|
|
140
|
-
end
|
|
141
|
-
@actor = @klass.send(@method, *@args, &@block)
|
|
142
|
-
@registry[@name] = @actor if @name
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
def restart
|
|
146
|
-
@actor = nil
|
|
147
|
-
cleanup
|
|
148
|
-
|
|
149
|
-
start
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
def terminate
|
|
153
|
-
cleanup
|
|
154
|
-
@actor.terminate if @actor
|
|
155
|
-
rescue DeadActorError
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
def cleanup
|
|
159
|
-
@registry.delete(@name) if @name
|
|
160
|
-
end
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
private
|
|
164
|
-
|
|
165
|
-
def finalize
|
|
166
|
-
@members.reverse_each(&:terminate) if @members
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
end
|
data/lib/celluloid/supervisor.rb
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
module Celluloid
|
|
2
|
-
# Supervisors are actors that watch over other actors and restart them if
|
|
3
|
-
# they crash
|
|
4
|
-
class Supervisor
|
|
5
|
-
class << self
|
|
6
|
-
# Define the root of the supervision tree
|
|
7
|
-
attr_accessor :root
|
|
8
|
-
|
|
9
|
-
def supervise(klass, *args, &block)
|
|
10
|
-
SupervisionGroup.new do |group|
|
|
11
|
-
group.supervise klass, *args, &block
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def supervise_as(name, klass, *args, &block)
|
|
16
|
-
SupervisionGroup.new do |group|
|
|
17
|
-
group.supervise_as name, klass, *args, &block
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
data/lib/celluloid/task_set.rb
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
require 'set'
|
|
2
|
-
require 'forwardable'
|
|
3
|
-
|
|
4
|
-
module Celluloid
|
|
5
|
-
if defined? JRUBY_VERSION
|
|
6
|
-
require 'jruby/synchronized'
|
|
7
|
-
|
|
8
|
-
class TaskSet
|
|
9
|
-
extend Forwardable
|
|
10
|
-
include JRuby::Synchronized
|
|
11
|
-
|
|
12
|
-
def_delegators :@tasks, :<<, :delete, :first, :empty?, :to_a
|
|
13
|
-
|
|
14
|
-
def initialize
|
|
15
|
-
@tasks = Set.new
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
elsif defined? Rubinius
|
|
19
|
-
class TaskSet
|
|
20
|
-
def initialize
|
|
21
|
-
@tasks = Set.new
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def <<(task)
|
|
25
|
-
Rubinius.synchronize(self) { @tasks << task }
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def delete(task)
|
|
29
|
-
Rubinius.synchronize(self) { @tasks.delete task }
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def first
|
|
33
|
-
Rubinius.synchronize(self) { @tasks.first }
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def empty?
|
|
37
|
-
Rubinius.synchronize(self) { @tasks.empty? }
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def to_a
|
|
41
|
-
Rubinius.synchronize(self) { @tasks.to_a }
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
else
|
|
45
|
-
# Assume we're on MRI, where we have the GIL. But what about IronRuby?
|
|
46
|
-
# Or MacRuby. Do people care? This will break Celluloid::StackDumps
|
|
47
|
-
TaskSet = Set
|
|
48
|
-
end
|
|
49
|
-
end
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
module Celluloid
|
|
2
|
-
class FiberStackError < Celluloid::Error; end
|
|
3
|
-
|
|
4
|
-
# Tasks with a Fiber backend
|
|
5
|
-
class TaskFiber < Task
|
|
6
|
-
|
|
7
|
-
def create
|
|
8
|
-
queue = Thread.current[:celluloid_queue]
|
|
9
|
-
actor_system = Thread.current[:celluloid_actor_system]
|
|
10
|
-
@fiber = Fiber.new do
|
|
11
|
-
# FIXME: cannot use the writer as specs run inside normal Threads
|
|
12
|
-
Thread.current[:celluloid_role] = :actor
|
|
13
|
-
Thread.current[:celluloid_queue] = queue
|
|
14
|
-
Thread.current[:celluloid_actor_system] = actor_system
|
|
15
|
-
yield
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def signal
|
|
20
|
-
Fiber.yield
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# Resume a suspended task, giving it a value to return if needed
|
|
24
|
-
def deliver(value)
|
|
25
|
-
@fiber.resume value
|
|
26
|
-
rescue SystemStackError => ex
|
|
27
|
-
raise FiberStackError, "#{ex} (please see https://github.com/celluloid/celluloid/wiki/Fiber-stack-errors)"
|
|
28
|
-
rescue FiberError => ex
|
|
29
|
-
raise DeadTaskError, "cannot resume a dead task (#{ex})"
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# Terminate this task
|
|
33
|
-
def terminate
|
|
34
|
-
super
|
|
35
|
-
rescue FiberError
|
|
36
|
-
# If we're getting this the task should already be dead
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def backtrace
|
|
40
|
-
["#{self.class} backtrace unavailable. Please try `Celluloid.task_class = Celluloid::TaskThread` if you need backtraces here."]
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
module Celluloid
|
|
2
|
-
# Tasks with a Thread backend
|
|
3
|
-
class TaskThread < Task
|
|
4
|
-
# Run the given block within a task
|
|
5
|
-
def initialize(type, meta)
|
|
6
|
-
@resume_queue = Queue.new
|
|
7
|
-
@exception_queue = Queue.new
|
|
8
|
-
@yield_mutex = Mutex.new
|
|
9
|
-
@yield_cond = ConditionVariable.new
|
|
10
|
-
|
|
11
|
-
super
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def create
|
|
15
|
-
# TODO: move this to ActorSystem#get_thread (ThreadHandle inside InternalPool)
|
|
16
|
-
@thread = ThreadHandle.new(Thread.current[:celluloid_actor_system], :task) do
|
|
17
|
-
begin
|
|
18
|
-
ex = @resume_queue.pop
|
|
19
|
-
raise ex if ex.is_a?(Task::TerminatedError)
|
|
20
|
-
|
|
21
|
-
yield
|
|
22
|
-
rescue Exception => ex
|
|
23
|
-
@exception_queue << ex
|
|
24
|
-
ensure
|
|
25
|
-
@yield_cond.signal
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def signal
|
|
31
|
-
@yield_cond.signal
|
|
32
|
-
@resume_queue.pop
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def deliver(value)
|
|
36
|
-
raise DeadTaskError, "cannot resume a dead task" unless @thread.alive?
|
|
37
|
-
|
|
38
|
-
@yield_mutex.synchronize do
|
|
39
|
-
@resume_queue.push(value)
|
|
40
|
-
@yield_cond.wait(@yield_mutex)
|
|
41
|
-
while @exception_queue.size > 0
|
|
42
|
-
raise @exception_queue.pop
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
rescue ThreadError
|
|
46
|
-
raise DeadTaskError, "cannot resume a dead task"
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def backtrace
|
|
50
|
-
@thread.backtrace
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
module Celluloid
|
|
2
|
-
# An abstraction around threads from the InternalPool which ensures we don't
|
|
3
|
-
# accidentally do things to threads which have been returned to the pool,
|
|
4
|
-
# such as, say, killing them
|
|
5
|
-
class ThreadHandle
|
|
6
|
-
def initialize(actor_system, role = nil)
|
|
7
|
-
@mutex = Mutex.new
|
|
8
|
-
@join = ConditionVariable.new
|
|
9
|
-
|
|
10
|
-
@thread = actor_system.get_thread do
|
|
11
|
-
Thread.current.role = role
|
|
12
|
-
begin
|
|
13
|
-
yield
|
|
14
|
-
ensure
|
|
15
|
-
@mutex.synchronize do
|
|
16
|
-
@thread = nil
|
|
17
|
-
@join.broadcast
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# Is the thread running?
|
|
24
|
-
def alive?
|
|
25
|
-
@mutex.synchronize { @thread.alive? if @thread }
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# Forcibly kill the thread
|
|
29
|
-
def kill
|
|
30
|
-
!!@mutex.synchronize { @thread.kill if @thread }
|
|
31
|
-
self
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Join to a running thread, blocking until it terminates
|
|
35
|
-
def join(limit = nil)
|
|
36
|
-
raise ThreadError, "Target thread must not be current thread" if @thread == Thread.current
|
|
37
|
-
@mutex.synchronize { @join.wait(@mutex, limit) if @thread }
|
|
38
|
-
self
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# Obtain the backtrace for this thread
|
|
42
|
-
def backtrace
|
|
43
|
-
@thread.backtrace
|
|
44
|
-
rescue NoMethodError
|
|
45
|
-
# undefined method `backtrace' for nil:NilClass
|
|
46
|
-
# Swallow this in case this ThreadHandle was terminated and @thread was
|
|
47
|
-
# set to nil
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
data/lib/celluloid/uuid.rb
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
require 'securerandom'
|
|
2
|
-
|
|
3
|
-
module Celluloid
|
|
4
|
-
# Clearly Ruby doesn't have enough UUID libraries
|
|
5
|
-
# This one aims to be fast and simple with good support for multiple threads
|
|
6
|
-
# If there's a better UUID library I can use with similar multithreaded
|
|
7
|
-
# performance, I certainly wouldn't mind using a gem for this!
|
|
8
|
-
module UUID
|
|
9
|
-
values = SecureRandom.hex(9).match(/(.{8})(.{4})(.{3})(.{3})/)
|
|
10
|
-
PREFIX = "#{values[1]}-#{values[2]}-4#{values[3]}-8#{values[4]}".freeze
|
|
11
|
-
BLOCK_SIZE = 0x10000
|
|
12
|
-
|
|
13
|
-
@counter = 0
|
|
14
|
-
@counter_mutex = Mutex.new
|
|
15
|
-
|
|
16
|
-
def self.generate
|
|
17
|
-
thread = Thread.current
|
|
18
|
-
|
|
19
|
-
unless thread.uuid_limit
|
|
20
|
-
@counter_mutex.synchronize do
|
|
21
|
-
block_base = @counter
|
|
22
|
-
@counter += BLOCK_SIZE
|
|
23
|
-
thread.uuid_counter = block_base
|
|
24
|
-
thread.uuid_limit = @counter - 1
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
counter = thread.uuid_counter
|
|
29
|
-
if thread.uuid_counter >= thread.uuid_limit
|
|
30
|
-
thread.uuid_counter = thread.uuid_limit = nil
|
|
31
|
-
else
|
|
32
|
-
thread.uuid_counter += 1
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
"#{PREFIX}-#{sprintf("%012x", counter)}".freeze
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|