celluloid 0.14.1 → 0.15.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -2
  3. data/lib/celluloid.rb +92 -108
  4. data/lib/celluloid/actor.rb +42 -64
  5. data/lib/celluloid/autostart.rb +1 -1
  6. data/lib/celluloid/call_chain.rb +13 -0
  7. data/lib/celluloid/calls.rb +5 -8
  8. data/lib/celluloid/condition.rb +8 -10
  9. data/lib/celluloid/cpu_counter.rb +1 -1
  10. data/lib/celluloid/evented_mailbox.rb +7 -10
  11. data/lib/celluloid/fsm.rb +1 -1
  12. data/lib/celluloid/future.rb +1 -2
  13. data/lib/celluloid/internal_pool.rb +77 -20
  14. data/lib/celluloid/legacy.rb +0 -38
  15. data/lib/celluloid/mailbox.rb +17 -10
  16. data/lib/celluloid/pool_manager.rb +1 -1
  17. data/lib/celluloid/properties.rb +24 -0
  18. data/lib/celluloid/proxies/abstract_proxy.rb +3 -0
  19. data/lib/celluloid/proxies/actor_proxy.rb +3 -32
  20. data/lib/celluloid/proxies/async_proxy.rb +4 -8
  21. data/lib/celluloid/proxies/future_proxy.rb +8 -6
  22. data/lib/celluloid/proxies/sync_proxy.rb +12 -7
  23. data/lib/celluloid/rspec.rb +3 -1
  24. data/lib/celluloid/signals.rb +7 -35
  25. data/lib/celluloid/stack_dump.rb +50 -37
  26. data/lib/celluloid/supervision_group.rb +5 -5
  27. data/lib/celluloid/task_set.rb +49 -0
  28. data/lib/celluloid/tasks.rb +67 -42
  29. data/lib/celluloid/tasks/task_fiber.rb +3 -1
  30. data/lib/celluloid/tasks/task_thread.rb +2 -3
  31. data/lib/celluloid/thread.rb +2 -0
  32. data/spec/celluloid/actor_spec.rb +5 -0
  33. data/spec/celluloid/block_spec.rb +54 -0
  34. data/spec/celluloid/calls_spec.rb +42 -0
  35. data/spec/celluloid/condition_spec.rb +65 -0
  36. data/spec/celluloid/evented_mailbox_spec.rb +34 -0
  37. data/spec/celluloid/fsm_spec.rb +107 -0
  38. data/spec/celluloid/future_spec.rb +32 -0
  39. data/spec/celluloid/internal_pool_spec.rb +52 -0
  40. data/spec/celluloid/links_spec.rb +45 -0
  41. data/spec/celluloid/logging/ring_buffer_spec.rb +38 -0
  42. data/spec/celluloid/mailbox_spec.rb +5 -0
  43. data/spec/celluloid/notifications_spec.rb +120 -0
  44. data/spec/celluloid/pool_spec.rb +52 -0
  45. data/spec/celluloid/properties_spec.rb +42 -0
  46. data/spec/celluloid/registry_spec.rb +64 -0
  47. data/spec/celluloid/stack_dump_spec.rb +35 -0
  48. data/spec/celluloid/supervision_group_spec.rb +53 -0
  49. data/spec/celluloid/supervisor_spec.rb +92 -0
  50. data/spec/celluloid/tasks/task_fiber_spec.rb +5 -0
  51. data/spec/celluloid/tasks/task_thread_spec.rb +5 -0
  52. data/spec/celluloid/thread_handle_spec.rb +22 -0
  53. data/spec/celluloid/uuid_spec.rb +11 -0
  54. data/spec/spec_helper.rb +31 -0
  55. data/spec/support/actor_examples.rb +161 -10
  56. data/spec/support/example_actor_class.rb +8 -0
  57. data/spec/support/mailbox_examples.rb +15 -3
  58. data/spec/support/task_examples.rb +2 -2
  59. metadata +28 -3
  60. data/lib/celluloid/version.rb +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 83a01356fe7e144f11c0ac9db25951850f53c9b4
4
- data.tar.gz: 243e2915cef408cf97229f8ec0a512bfb2524fb8
3
+ metadata.gz: 802e81b987e2d65c9d7055c2160805612db65b50
4
+ data.tar.gz: 2a2c5eaf4c8afa92a8ee3c782ffb3e6556454061
5
5
  SHA512:
6
- metadata.gz: 60e75d013b08ff7101ea6280b31bd5976ba097e821880e3d6d9b935580c8515d05d8619bc6a3df7be1d2733366d97b482a3668443e59c3c9e397bc6a14e46c75
7
- data.tar.gz: 3e9fe0851276289183c6ca52e72bc545dc174831d325d78a9682f63087c4f54ff3b6f454babf4b091641a163235f953e02bbf656cfbdce4e093ec35df831e167
6
+ metadata.gz: 3bee45fcc9e099fcd5b61d605fa06293d9454402f65601ff789aac7c679e9f0d206a7f696a53d37fa3febeda10163dd5c2e4da1bc8dece2101bf1a3f949ca60e
7
+ data.tar.gz: c897040ce47e50088ee2c53ea8291733d2214cb127d3014558e366f8a1e58239ea232a9d7381671d99c64fcf6dca6e65b6f1d8b335a986a8779b97f875a163da
data/README.md CHANGED
@@ -99,7 +99,9 @@ Installation
99
99
 
100
100
  Add this line to your application's Gemfile:
101
101
 
102
- gem 'celluloid'
102
+ ```ruby
103
+ gem 'celluloid'
104
+ ```
103
105
 
104
106
  And then execute:
105
107
 
@@ -111,7 +113,9 @@ Or install it yourself as:
111
113
 
112
114
  Inside of your Ruby program, require Celluloid with:
113
115
 
114
- require 'celluloid/autostart'
116
+ ```ruby
117
+ require 'celluloid/autostart'
118
+ ```
115
119
 
116
120
  Supported Platforms
117
121
  -------------------
@@ -3,7 +3,14 @@ require 'thread'
3
3
  require 'timeout'
4
4
  require 'set'
5
5
 
6
+ if defined?(JRUBY_VERSION) && JRUBY_VERSION == "1.7.3"
7
+ raise "Celluloid is broken on JRuby 1.7.3. Please upgrade to 1.7.4+"
8
+ end
9
+
6
10
  module Celluloid
11
+ VERSION = '0.15.0.pre'
12
+ Error = Class.new StandardError
13
+
7
14
  extend self # expose all instance methods as singleton methods
8
15
 
9
16
  # Warning message added to Celluloid objects accessed outside their actors
@@ -18,6 +25,24 @@ module Celluloid
18
25
  def included(klass)
19
26
  klass.send :extend, ClassMethods
20
27
  klass.send :include, InstanceMethods
28
+
29
+ klass.send :extend, Properties
30
+
31
+ klass.property :mailbox_class, :default => Celluloid::Mailbox
32
+ klass.property :proxy_class, :default => Celluloid::ActorProxy
33
+ klass.property :task_class, :default => Celluloid.task_class
34
+ klass.property :mailbox_size
35
+
36
+ klass.property :execute_block_on_receiver,
37
+ :default => [:after, :every, :receive],
38
+ :multi => true
39
+
40
+ klass.property :finalizer
41
+ klass.property :exit_handler
42
+
43
+ klass.send(:define_singleton_method, :trap_exit) do |*args|
44
+ exit_handler(*args)
45
+ end
21
46
  end
22
47
 
23
48
  # Are we currently inside of an actor?
@@ -48,6 +73,18 @@ module Celluloid
48
73
  end
49
74
  alias_method :dump, :stack_dump
50
75
 
76
+ # Detect if a particular call is recursing through multiple actors
77
+ def detect_recursion
78
+ actor = Thread.current[:celluloid_actor]
79
+ return unless actor
80
+
81
+ task = Thread.current[:celluloid_task]
82
+ return unless task
83
+
84
+ chain_id = CallChain.current_id
85
+ actor.tasks.to_a.any? { |t| t != task && t.chain_id == chain_id }
86
+ end
87
+
51
88
  # Define an exception handler for actor crashes
52
89
  def exception_handler(&block)
53
90
  Logger.exception_handler(&block)
@@ -63,10 +100,18 @@ module Celluloid
63
100
  end
64
101
  end
65
102
 
103
+ def boot
104
+ init
105
+ start
106
+ end
107
+
108
+ def init
109
+ self.internal_pool = InternalPool.new
110
+ end
111
+
66
112
  # Launch default services
67
113
  # FIXME: We should set up the supervision hierarchy here
68
- def boot
69
- internal_pool.reset
114
+ def start
70
115
  Celluloid::Notifications::Fanout.supervise_as :notifications_fanout
71
116
  Celluloid::IncidentReporter.supervise_as :default_incident_reporter, STDERR
72
117
  end
@@ -90,11 +135,12 @@ module Celluloid
90
135
 
91
136
  # Shut down all running actors
92
137
  def shutdown
138
+ actors = Actor.all
139
+
93
140
  Timeout.timeout(shutdown_timeout) do
94
141
  internal_pool.shutdown
95
142
 
96
- actors = Actor.all
97
- Logger.debug "Terminating #{actors.size} actors..." if actors.size > 0
143
+ Logger.debug "Terminating #{actors.size} #{(actors.size > 1) ? 'actors' : 'actor'}..." if actors.size > 0
98
144
 
99
145
  # Attempt to shut down the supervision tree, if available
100
146
  Supervisor.root.terminate if Supervisor.root
@@ -103,21 +149,31 @@ module Celluloid
103
149
  actors.each do |actor|
104
150
  begin
105
151
  actor.terminate!
106
- rescue DeadActorError, MailboxError
152
+ rescue DeadActorError
107
153
  end
108
154
  end
109
155
 
110
156
  actors.each do |actor|
111
157
  begin
112
158
  Actor.join(actor)
113
- rescue DeadActorError, MailboxError
159
+ rescue DeadActorError
114
160
  end
115
161
  end
116
-
117
- Logger.debug "Shutdown completed cleanly"
118
162
  end
119
163
  rescue Timeout::Error
120
164
  Logger.error("Couldn't cleanly terminate all actors in #{shutdown_timeout} seconds!")
165
+ actors.each do |actor|
166
+ begin
167
+ Actor.kill(actor)
168
+ rescue DeadActorError, MailboxDead
169
+ end
170
+ end
171
+ ensure
172
+ internal_pool.kill
173
+ end
174
+
175
+ def version
176
+ VERSION
121
177
  end
122
178
  end
123
179
 
@@ -173,63 +229,6 @@ module Celluloid
173
229
  Actor.join(new(*args, &block))
174
230
  end
175
231
 
176
- # Trap errors from actors we're linked to when they exit
177
- def exit_handler(callback = nil)
178
- if callback
179
- @exit_handler = callback.to_sym
180
- elsif defined?(@exit_handler)
181
- @exit_handler
182
- elsif superclass.respond_to? :exit_handler
183
- superclass.exit_handler
184
- end
185
- end
186
- alias_method :trap_exit, :exit_handler
187
-
188
- # Define a callback to run when the actor is finalized.
189
- def finalizer(callback = nil)
190
- if callback
191
- @finalizer = callback.to_sym
192
- elsif defined?(@finalizer)
193
- @finalizer
194
- elsif superclass.respond_to? :finalizer
195
- superclass.finalizer
196
- end
197
- end
198
-
199
- # Define the mailbox class for this class
200
- def mailbox_class(klass = nil)
201
- if klass
202
- mailbox.class = klass
203
- else
204
- mailbox.class
205
- end
206
- end
207
-
208
- def proxy_class(klass = nil)
209
- if klass
210
- @proxy_class = klass
211
- elsif defined?(@proxy_class)
212
- @proxy_class
213
- elsif superclass.respond_to? :proxy_class
214
- superclass.proxy_class
215
- else
216
- Celluloid::ActorProxy
217
- end
218
- end
219
-
220
- # Define the default task type for this class
221
- def task_class(klass = nil)
222
- if klass
223
- @task_class = klass
224
- elsif defined?(@task_class)
225
- @task_class
226
- elsif superclass.respond_to? :task_class
227
- superclass.task_class
228
- else
229
- Celluloid.task_class
230
- end
231
- end
232
-
233
232
  # Mark methods as running exclusively
234
233
  def exclusive(*methods)
235
234
  if methods.empty?
@@ -240,55 +239,22 @@ module Celluloid
240
239
  end
241
240
  end
242
241
 
243
- # Mark methods as running blocks on the receiver
244
- def execute_block_on_receiver(*methods)
245
- receiver_block_executions.merge methods.map(&:to_sym)
246
- end
247
-
248
- def receiver_block_executions
249
- @receiver_block_executions ||= Set.new([:after, :every, :receive])
250
- end
251
-
252
242
  # Configuration options for Actor#new
253
243
  def actor_options
254
244
  {
255
- :mailbox => mailbox.build,
245
+ :mailbox_class => mailbox_class,
246
+ :mailbox_size => mailbox_size,
256
247
  :proxy_class => proxy_class,
257
248
  :task_class => task_class,
258
249
  :exit_handler => exit_handler,
259
250
  :exclusive_methods => defined?(@exclusive_methods) ? @exclusive_methods : nil,
260
- :receiver_block_executions => receiver_block_executions
251
+ :receiver_block_executions => execute_block_on_receiver
261
252
  }
262
253
  end
263
254
 
264
255
  def ===(other)
265
256
  other.kind_of? self
266
257
  end
267
-
268
- def mailbox
269
- @mailbox_factory ||= MailboxFactory.new(self)
270
- end
271
-
272
- class MailboxFactory
273
- attr_accessor :class, :max_size
274
-
275
- def initialize(actor)
276
- @actor = actor
277
- @class = nil
278
- @max_size = nil
279
- end
280
-
281
- def build
282
- mailbox = mailbox_class.new
283
- mailbox.max_size = @max_size
284
- mailbox
285
- end
286
-
287
- private
288
- def mailbox_class
289
- @class || (@actor.superclass.respond_to?(:mailbox_class) && @actor.superclass.mailbox_class) || Celluloid::Mailbox
290
- end
291
- end
292
258
  end
293
259
 
294
260
  # These are methods we don't want added to the Celluloid singleton but to be
@@ -326,6 +292,8 @@ module Celluloid
326
292
  end
327
293
 
328
294
  def inspect
295
+ return "..." if Celluloid.detect_recursion
296
+
329
297
  str = "#<"
330
298
 
331
299
  if leaked?
@@ -363,7 +331,7 @@ module Celluloid
363
331
 
364
332
  # Terminate this actor
365
333
  def terminate
366
- Thread.current[:celluloid_actor].terminate
334
+ Thread.current[:celluloid_actor].proxy.terminate!
367
335
  end
368
336
 
369
337
  # Send a signal with the given name to all waiting methods
@@ -383,7 +351,7 @@ module Celluloid
383
351
 
384
352
  # Obtain the UUID of the current call chain
385
353
  def call_chain_id
386
- Thread.current[:celluloid_chain_id]
354
+ CallChain.current_id
387
355
  end
388
356
 
389
357
  # Obtain the running tasks for this actor
@@ -446,16 +414,30 @@ module Celluloid
446
414
  end
447
415
  end
448
416
 
417
+ # Timeout on task suspension (eg Sync calls to other actors)
418
+ def timeout(duration)
419
+ bt = caller
420
+ task = Task.current
421
+ timer = after(duration) do
422
+ exception = Task::TimeoutError.new
423
+ exception.set_backtrace bt
424
+ task.resume exception
425
+ end
426
+ yield
427
+ ensure
428
+ timer.cancel if timer
429
+ end
430
+
449
431
  # Run given block in an exclusive mode: all synchronous calls block the whole
450
432
  # actor, not only current message processing.
451
433
  def exclusive(&block)
452
- Thread.current[:celluloid_actor].exclusive(&block)
434
+ Thread.current[:celluloid_task].exclusive(&block)
453
435
  end
454
436
 
455
437
  # Are we currently exclusive
456
438
  def exclusive?
457
- actor = Thread.current[:celluloid_actor]
458
- actor && actor.exclusive?
439
+ task = Thread.current[:celluloid_task]
440
+ task && task.exclusive?
459
441
  end
460
442
 
461
443
  # Call a block after a given interval, returning a Celluloid::Timer object
@@ -488,9 +470,8 @@ module Celluloid
488
470
  end
489
471
  end
490
472
 
491
- require 'celluloid/version'
492
-
493
473
  require 'celluloid/calls'
474
+ require 'celluloid/call_chain'
494
475
  require 'celluloid/condition'
495
476
  require 'celluloid/thread'
496
477
  require 'celluloid/core_ext'
@@ -503,6 +484,7 @@ require 'celluloid/logger'
503
484
  require 'celluloid/mailbox'
504
485
  require 'celluloid/evented_mailbox'
505
486
  require 'celluloid/method'
487
+ require 'celluloid/properties'
506
488
  require 'celluloid/receivers'
507
489
  require 'celluloid/registry'
508
490
  require 'celluloid/responses'
@@ -510,6 +492,7 @@ require 'celluloid/signals'
510
492
  require 'celluloid/stack_dump'
511
493
  require 'celluloid/system_events'
512
494
  require 'celluloid/tasks'
495
+ require 'celluloid/task_set'
513
496
  require 'celluloid/thread_handle'
514
497
  require 'celluloid/uuid'
515
498
 
@@ -535,3 +518,4 @@ Celluloid.task_class = Celluloid::TaskFiber
535
518
  Celluloid.logger = Logger.new(STDERR)
536
519
  Celluloid.shutdown_timeout = 10
537
520
  Celluloid.register_shutdown
521
+ Celluloid.init
@@ -2,16 +2,16 @@ require 'timers'
2
2
 
3
3
  module Celluloid
4
4
  # Don't do Actor-like things outside Actor scope
5
- class NotActorError < StandardError; end
5
+ class NotActorError < Celluloid::Error; end
6
6
 
7
7
  # Trying to do something to a dead actor
8
- class DeadActorError < StandardError; end
8
+ class DeadActorError < Celluloid::Error; end
9
9
 
10
10
  # A timeout occured before the given request could complete
11
- class TimeoutError < StandardError; end
11
+ class TimeoutError < Celluloid::Error; end
12
12
 
13
13
  # The sender made an error, not the current actor
14
- class AbortError < StandardError
14
+ class AbortError < Celluloid::Error
15
15
  attr_reader :cause
16
16
 
17
17
  def initialize(cause)
@@ -77,8 +77,8 @@ module Celluloid
77
77
  # Obtain all running actors in the system
78
78
  def all
79
79
  actors = []
80
- Thread.list.each do |t|
81
- next unless t.celluloid? && t.role == :actor
80
+ Celluloid.internal_pool.each do |t|
81
+ next unless t.role == :actor
82
82
  actors << t.actor.proxy if t.actor && t.actor.respond_to?(:proxy)
83
83
  end
84
84
  actors
@@ -121,10 +121,7 @@ module Celluloid
121
121
  # Forcibly kill a given actor
122
122
  def kill(actor)
123
123
  actor.thread.kill
124
- begin
125
- actor.mailbox.shutdown
126
- rescue DeadActorError
127
- end
124
+ actor.mailbox.shutdown if actor.mailbox.alive?
128
125
  end
129
126
 
130
127
  # Wait for an actor to terminate
@@ -136,12 +133,15 @@ module Celluloid
136
133
 
137
134
  # Wrap the given subject with an Actor
138
135
  def initialize(subject, options = {})
139
- @subject = subject
140
- @mailbox = options[:mailbox] || Mailbox.new
136
+ @subject = subject
137
+
138
+ @mailbox = options.fetch(:mailbox_class, Mailbox).new
139
+ @mailbox.max_size = options.fetch(:mailbox_size, nil)
140
+
141
+ @task_class = options[:task_class] || Celluloid.task_class
141
142
  @exit_handler = options[:exit_handler]
142
143
  @exclusives = options[:exclusive_methods]
143
144
  @receiver_block_executions = options[:receiver_block_executions]
144
- @task_class = options[:task_class] || Celluloid.task_class
145
145
 
146
146
  @tasks = TaskSet.new
147
147
  @links = Links.new
@@ -193,28 +193,9 @@ module Celluloid
193
193
  @running = false
194
194
  end
195
195
 
196
- # Is this actor running in exclusive mode?
197
- def exclusive?
198
- @exclusive
199
- end
200
-
201
- # Execute a code block in exclusive mode.
202
- def exclusive
203
- if @exclusive
204
- yield
205
- else
206
- begin
207
- @exclusive = true
208
- yield
209
- ensure
210
- @exclusive = false
211
- end
212
- end
213
- end
214
-
215
196
  # Perform a linking request with another actor
216
197
  def linking_request(receiver, type)
217
- exclusive do
198
+ Celluloid.exclusive do
218
199
  start_time = Time.now
219
200
  receiver.mailbox << LinkingRequest.new(Actor.current, type)
220
201
  system_events = []
@@ -245,7 +226,7 @@ module Celluloid
245
226
 
246
227
  # Send a signal with the given name to all waiting methods
247
228
  def signal(name, value = nil)
248
- @signals.send name, value
229
+ @signals.broadcast name, value
249
230
  end
250
231
 
251
232
  # Wait for the given signal
@@ -314,15 +295,17 @@ module Celluloid
314
295
  when SystemEvent
315
296
  handle_system_event message
316
297
  when Call
317
- task(:call, message.method) {
318
- if @receiver_block_executions && meth = message.method
319
- if meth == :__send__
320
- meth = message.arguments.first
321
- end
322
- if @receiver_block_executions.include?(meth.to_sym)
323
- message.execute_block_on_receiver
324
- end
298
+ meth = message.method
299
+ if meth == :__send__
300
+ meth = message.arguments.first
301
+ end
302
+ if @receiver_block_executions && meth
303
+ if @receiver_block_executions.include?(meth.to_sym)
304
+ message.execute_block_on_receiver
325
305
  end
306
+ end
307
+
308
+ task(:call, :method_name => meth, :dangerous_suspend => meth == :initialize) {
326
309
  message.dispatch(@subject)
327
310
  }
328
311
  when BlockCall
@@ -330,7 +313,9 @@ module Celluloid
330
313
  when BlockResponse, Response
331
314
  message.dispatch
332
315
  else
333
- @receivers.handle_message(message)
316
+ unless @receivers.handle_message(message)
317
+ Logger.debug "Discarded message (unhandled): #{message}"
318
+ end
334
319
  end
335
320
  message
336
321
  end
@@ -339,13 +324,13 @@ module Celluloid
339
324
  def handle_system_event(event)
340
325
  case event
341
326
  when ExitEvent
342
- task(:exit_handler, @exit_handler) { handle_exit_event event }
327
+ task(:exit_handler, :method_name => @exit_handler) { handle_exit_event event }
343
328
  when LinkingRequest
344
329
  event.process(links)
345
330
  when NamingRequest
346
331
  @name = event.name
347
332
  when TerminationRequest
348
- @running = false
333
+ terminate
349
334
  when SignalConditionRequest
350
335
  event.call
351
336
  end
@@ -382,17 +367,9 @@ module Celluloid
382
367
 
383
368
  # Run the user-defined finalizer, if one is set
384
369
  def run_finalizer
385
- # FIXME: remove before Celluloid 1.0
386
- if @subject.respond_to?(:finalize) && @subject.class.finalizer != :finalize
387
- Logger.warn("DEPRECATION WARNING: #{@subject.class}#finalize is deprecated and will be removed in Celluloid 1.0. " +
388
- "Define finalizers with '#{@subject.class}.finalizer :callback.'")
389
-
390
- task(:finalizer, :finalize) { @subject.finalize }
391
- end
392
-
393
370
  finalizer = @subject.class.finalizer
394
371
  if finalizer && @subject.respond_to?(finalizer, true)
395
- task(:finalizer, :finalize) { @subject.__send__(finalizer) }
372
+ task(:finalizer, :method_name => finalizer, :dangerous_suspend => true) { @subject.__send__(finalizer) }
396
373
  end
397
374
  rescue => ex
398
375
  Logger.crash("#{@subject.class}#finalize crashed!", ex)
@@ -402,25 +379,26 @@ module Celluloid
402
379
  def cleanup(exit_event)
403
380
  @mailbox.shutdown
404
381
  @links.each do |actor|
405
- begin
382
+ if actor.mailbox.alive?
406
383
  actor.mailbox << exit_event
407
- rescue MailboxError
408
- # We're exiting/crashing, they're dead. Give up :(
409
384
  end
410
385
  end
411
386
 
412
- tasks.each { |task| task.terminate }
387
+ tasks.to_a.each { |task| task.terminate }
413
388
  rescue => ex
414
389
  Logger.crash("#{@subject.class}: CLEANUP CRASHED!", ex)
415
390
  end
416
391
 
417
392
  # Run a method inside a task unless it's exclusive
418
- def task(task_type, method_name = nil, &block)
419
- if @exclusives && (@exclusives == :all || (method_name && @exclusives.include?(method_name.to_sym)))
420
- exclusive { block.call }
421
- else
422
- @task_class.new(task_type, &block).resume
423
- end
393
+ def task(task_type, meta = nil)
394
+ method_name = meta && meta.fetch(:method_name, nil)
395
+ @task_class.new(task_type, meta) {
396
+ if @exclusives && (@exclusives == :all || (method_name && @exclusives.include?(method_name.to_sym)))
397
+ Celluloid.exclusive { yield }
398
+ else
399
+ yield
400
+ end
401
+ }.resume
424
402
  end
425
403
  end
426
404
  end