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.
Files changed (177) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +394 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +28 -15
  5. data/culture/CONDUCT.md +28 -0
  6. data/culture/Gemfile +9 -0
  7. data/culture/LICENSE.txt +22 -0
  8. data/culture/README.md +22 -0
  9. data/culture/Rakefile +5 -0
  10. data/culture/SYNC.md +70 -0
  11. data/culture/celluloid-culture.gemspec +18 -0
  12. data/culture/gems/README.md +39 -0
  13. data/culture/gems/dependencies.yml +85 -0
  14. data/culture/gems/loader.rb +101 -0
  15. data/culture/rubocop/README.md +38 -0
  16. data/culture/rubocop/lint.yml +8 -0
  17. data/culture/rubocop/metrics.yml +15 -0
  18. data/culture/rubocop/perf.yml +0 -0
  19. data/culture/rubocop/rubocop.yml +5 -0
  20. data/culture/rubocop/style.yml +57 -0
  21. data/culture/spec/gems_spec.rb +2 -0
  22. data/culture/spec/spec_helper.rb +0 -0
  23. data/culture/spec/sync_spec.rb +2 -0
  24. data/culture/sync.rb +56 -0
  25. data/culture/tasks/rspec.rake +5 -0
  26. data/culture/tasks/rubocop.rake +2 -0
  27. data/examples/basic_usage.rb +49 -0
  28. data/examples/futures.rb +38 -0
  29. data/examples/ring.rb +61 -0
  30. data/examples/simple_pmap.rb +14 -0
  31. data/examples/stack.rb +47 -0
  32. data/examples/timers.rb +72 -0
  33. data/lib/celluloid/actor/manager.rb +7 -0
  34. data/lib/celluloid/actor/system.rb +163 -0
  35. data/lib/celluloid/actor.rb +53 -71
  36. data/lib/celluloid/autostart.rb +1 -1
  37. data/lib/celluloid/backported.rb +2 -0
  38. data/lib/celluloid/call/async.rb +16 -0
  39. data/lib/celluloid/call/block.rb +22 -0
  40. data/lib/celluloid/call/sync.rb +70 -0
  41. data/lib/celluloid/calls.rb +24 -114
  42. data/lib/celluloid/cell.rb +32 -20
  43. data/lib/celluloid/condition.rb +5 -6
  44. data/lib/celluloid/core_ext.rb +1 -1
  45. data/lib/celluloid/current.rb +2 -0
  46. data/lib/celluloid/debug.rb +1 -0
  47. data/lib/celluloid/deprecate.rb +21 -0
  48. data/lib/celluloid/exceptions.rb +22 -16
  49. data/lib/celluloid/fiber.rb +3 -3
  50. data/lib/celluloid/future.rb +46 -8
  51. data/lib/celluloid/group/pool.rb +125 -0
  52. data/lib/celluloid/group/spawner.rb +68 -0
  53. data/lib/celluloid/group.rb +61 -0
  54. data/lib/celluloid/logging.rb +5 -5
  55. data/lib/celluloid/mailbox/evented.rb +74 -0
  56. data/lib/celluloid/mailbox.rb +15 -14
  57. data/lib/celluloid/managed.rb +3 -0
  58. data/lib/celluloid/notices.rb +15 -0
  59. data/lib/celluloid/proxies.rb +11 -0
  60. data/lib/celluloid/proxy/abstract.rb +50 -0
  61. data/lib/celluloid/proxy/actor.rb +37 -0
  62. data/lib/celluloid/proxy/async.rb +15 -0
  63. data/lib/celluloid/proxy/block.rb +28 -0
  64. data/lib/celluloid/proxy/cell.rb +66 -0
  65. data/lib/celluloid/proxy/future.rb +20 -0
  66. data/lib/celluloid/proxy/sync.rb +24 -0
  67. data/lib/celluloid/rspec.rb +67 -9
  68. data/lib/celluloid/system_events.rb +69 -14
  69. data/lib/celluloid/task/fibered.rb +45 -0
  70. data/lib/celluloid/task/threaded.rb +59 -0
  71. data/lib/celluloid/{tasks.rb → task.rb} +30 -38
  72. data/lib/celluloid/test.rb +1 -1
  73. data/lib/celluloid/thread.rb +6 -1
  74. data/lib/celluloid/version.rb +3 -0
  75. data/lib/celluloid.rb +151 -130
  76. data/spec/celluloid/actor/system_spec.rb +83 -0
  77. data/spec/celluloid/actor_spec.rb +2 -2
  78. data/spec/celluloid/block_spec.rb +67 -8
  79. data/spec/celluloid/calls_spec.rb +28 -23
  80. data/spec/celluloid/condition_spec.rb +23 -14
  81. data/spec/celluloid/evented_mailbox_spec.rb +1 -31
  82. data/spec/celluloid/future_spec.rb +15 -12
  83. data/spec/celluloid/group/elastic_spec.rb +0 -0
  84. data/spec/celluloid/group/pool_spec.rb +8 -0
  85. data/spec/celluloid/group/spawner_spec.rb +17 -0
  86. data/spec/celluloid/mailbox/evented_spec.rb +40 -0
  87. data/spec/celluloid/mailbox_spec.rb +1 -3
  88. data/spec/celluloid/misc/leak_spec.rb +73 -0
  89. data/spec/celluloid/proxy_spec.rb +33 -0
  90. data/spec/celluloid/task/fibered_spec.rb +5 -0
  91. data/spec/celluloid/task/threaded_spec.rb +5 -0
  92. data/spec/celluloid/timer_spec.rb +14 -16
  93. data/spec/deprecate/actor_system_spec.rb +72 -0
  94. data/spec/deprecate/block_spec.rb +52 -0
  95. data/spec/deprecate/calls_spec.rb +39 -0
  96. data/spec/deprecate/evented_mailbox_spec.rb +34 -0
  97. data/spec/deprecate/future_spec.rb +32 -0
  98. data/spec/deprecate/internal_pool_spec.rb +4 -0
  99. data/spec/shared/actor_examples.rb +1259 -0
  100. data/spec/shared/group_examples.rb +121 -0
  101. data/spec/shared/mailbox_examples.rb +87 -0
  102. data/{lib/celluloid/rspec → spec/shared}/task_examples.rb +9 -8
  103. data/spec/spec_helper.rb +5 -42
  104. data/spec/support/configure_rspec.rb +77 -0
  105. data/spec/support/coverage.rb +4 -0
  106. data/spec/support/crash_checking.rb +68 -0
  107. data/spec/support/debugging.rb +31 -0
  108. data/spec/support/env.rb +21 -0
  109. data/{lib/celluloid/rspec/example_actor_class.rb → spec/support/examples/actor_class.rb} +21 -2
  110. data/spec/support/examples/call_class.rb +37 -0
  111. data/spec/support/examples/evented_mailbox_class.rb +27 -0
  112. data/spec/support/includer.rb +6 -0
  113. data/spec/support/logging.rb +55 -0
  114. data/spec/support/loose_threads.rb +68 -0
  115. data/spec/support/reset_class_variables.rb +27 -0
  116. data/spec/support/sleep_and_wait.rb +14 -0
  117. data/spec/support/stubbing.rb +14 -0
  118. metadata +276 -78
  119. data/lib/celluloid/actor_system.rb +0 -107
  120. data/lib/celluloid/call_chain.rb +0 -13
  121. data/lib/celluloid/cpu_counter.rb +0 -34
  122. data/lib/celluloid/evented_mailbox.rb +0 -73
  123. data/lib/celluloid/fsm.rb +0 -186
  124. data/lib/celluloid/handlers.rb +0 -41
  125. data/lib/celluloid/internal_pool.rb +0 -159
  126. data/lib/celluloid/legacy.rb +0 -9
  127. data/lib/celluloid/links.rb +0 -36
  128. data/lib/celluloid/logger.rb +0 -93
  129. data/lib/celluloid/logging/incident.rb +0 -21
  130. data/lib/celluloid/logging/incident_logger.rb +0 -129
  131. data/lib/celluloid/logging/incident_reporter.rb +0 -48
  132. data/lib/celluloid/logging/log_event.rb +0 -20
  133. data/lib/celluloid/logging/ring_buffer.rb +0 -65
  134. data/lib/celluloid/method.rb +0 -32
  135. data/lib/celluloid/notifications.rb +0 -83
  136. data/lib/celluloid/pool_manager.rb +0 -146
  137. data/lib/celluloid/probe.rb +0 -73
  138. data/lib/celluloid/properties.rb +0 -24
  139. data/lib/celluloid/proxies/abstract_proxy.rb +0 -20
  140. data/lib/celluloid/proxies/actor_proxy.rb +0 -38
  141. data/lib/celluloid/proxies/async_proxy.rb +0 -31
  142. data/lib/celluloid/proxies/block_proxy.rb +0 -29
  143. data/lib/celluloid/proxies/cell_proxy.rb +0 -68
  144. data/lib/celluloid/proxies/future_proxy.rb +0 -35
  145. data/lib/celluloid/proxies/sync_proxy.rb +0 -36
  146. data/lib/celluloid/receivers.rb +0 -63
  147. data/lib/celluloid/registry.rb +0 -57
  148. data/lib/celluloid/responses.rb +0 -44
  149. data/lib/celluloid/rspec/actor_examples.rb +0 -1054
  150. data/lib/celluloid/rspec/mailbox_examples.rb +0 -84
  151. data/lib/celluloid/signals.rb +0 -23
  152. data/lib/celluloid/stack_dump.rb +0 -133
  153. data/lib/celluloid/supervision_group.rb +0 -169
  154. data/lib/celluloid/supervisor.rb +0 -22
  155. data/lib/celluloid/task_set.rb +0 -49
  156. data/lib/celluloid/tasks/task_fiber.rb +0 -43
  157. data/lib/celluloid/tasks/task_thread.rb +0 -53
  158. data/lib/celluloid/thread_handle.rb +0 -50
  159. data/lib/celluloid/uuid.rb +0 -38
  160. data/spec/celluloid/actor_system_spec.rb +0 -69
  161. data/spec/celluloid/cpu_counter_spec.rb +0 -82
  162. data/spec/celluloid/fsm_spec.rb +0 -107
  163. data/spec/celluloid/internal_pool_spec.rb +0 -52
  164. data/spec/celluloid/links_spec.rb +0 -45
  165. data/spec/celluloid/logging/ring_buffer_spec.rb +0 -38
  166. data/spec/celluloid/notifications_spec.rb +0 -120
  167. data/spec/celluloid/pool_spec.rb +0 -92
  168. data/spec/celluloid/probe_spec.rb +0 -121
  169. data/spec/celluloid/properties_spec.rb +0 -42
  170. data/spec/celluloid/registry_spec.rb +0 -64
  171. data/spec/celluloid/stack_dump_spec.rb +0 -64
  172. data/spec/celluloid/supervision_group_spec.rb +0 -65
  173. data/spec/celluloid/supervisor_spec.rb +0 -103
  174. data/spec/celluloid/tasks/task_fiber_spec.rb +0 -5
  175. data/spec/celluloid/tasks/task_thread_spec.rb +0 -5
  176. data/spec/celluloid/thread_handle_spec.rb +0 -26
  177. 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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