class Celluloid::Task

Tasks are interruptable/resumable execution contexts used to run methods

Attributes

chain_id[RW]
guard_warnings[RW]
meta[R]
status[R]
type[R]

Public Class Methods

current() click to toggle source

Obtain the current task

# File lib/celluloid/task.rb, line 5
def self.current
  Thread.current[:celluloid_task] || raise(NotTaskError, "not within a task context")
end
new(type, meta) { || ... } click to toggle source

Create a new task

# File lib/celluloid/task.rb, line 18
def initialize(type, meta)
  @type     = type
  @meta     = meta
  @status   = :new

  @exclusive         = false
  @dangerous_suspend = @meta ? @meta.dup.delete(:dangerous_suspend) : false
  @guard_warnings    = false

  actor     = Thread.current[:celluloid_actor]
  @chain_id = Internals::CallChain.current_id

  raise NotActorError, "can't create tasks outside of actors" unless actor
  guard "can't create tasks inside of tasks" if Thread.current[:celluloid_task]

  create do
    begin
      @status = :running
      actor.setup_thread

      name_current_thread thread_metadata

      Thread.current[:celluloid_task] = self
      Internals::CallChain.current_id = @chain_id

      actor.tasks << self
      yield
    rescue TaskTerminated
      # Task was explicitly terminated
    ensure
      name_current_thread nil
      @status = :dead
      actor.tasks.delete self
    end
  end
end
suspend(status) click to toggle source

Suspend the running task, deferring to the scheduler

# File lib/celluloid/task.rb, line 10
def self.suspend(status)
  Task.current.suspend(status)
end

Public Instance Methods

backtrace() click to toggle source
# File lib/celluloid/task.rb, line 137
def backtrace; end
create(&_block) click to toggle source
# File lib/celluloid/task.rb, line 55
def create(&_block)
  raise "Implement #{self.class}#create"
end
exclusive() { || ... } click to toggle source

Execute a code block in exclusive mode.

# File lib/celluloid/task.rb, line 96
def exclusive
  if @exclusive
    yield
  else
    begin
      @exclusive = true
      yield
    ensure
      @exclusive = false
    end
  end
end
exclusive?() click to toggle source

Is this task running in exclusive mode?

# File lib/celluloid/task.rb, line 133
def exclusive?
  @exclusive
end
guard(message) click to toggle source
# File lib/celluloid/task.rb, line 149
def guard(message)
  # !!! DO NOT INTRODUCE ADDITIONAL GLOBAL VARIABLES !!!
  # rubocop:disable Style/GlobalVars
  if @guard_warnings
    Internals::Logger.warn message if $CELLULOID_DEBUG
  else
    raise message if $CELLULOID_DEBUG
  end
  # rubocop:enable Style/GlobalVars
end
inspect() click to toggle source

Nicer string inspect for tasks

# File lib/celluloid/task.rb, line 145
def inspect
  "#<#{self.class}:0x#{object_id.to_s(16)} @type=#{@type.inspect}, @meta=#{@meta.inspect}, @status=#{@status.inspect}>"
end
resume(value = nil) click to toggle source

Resume a suspended task, giving it a value to return if needed

# File lib/celluloid/task.rb, line 83
def resume(value = nil)
  guard "Cannot resume a task from inside of a task" if Thread.current[:celluloid_task]
  if running?
    deliver(value)
  else
    # rubocop:disable Metrics/LineLength
    Internals::Logger.warn "Attempted to resume a dead task: type=#{@type.inspect}, meta=#{@meta.inspect}, status=#{@status.inspect}"
    # rubocop:enable Metrics/LineLength
  end
  nil
end
running?() click to toggle source

Is the current task still running?

# File lib/celluloid/task.rb, line 140
def running?
  @status != :dead
end
suspend(status) click to toggle source

Suspend the current task, changing the status to the given argument

# File lib/celluloid/task.rb, line 60
def suspend(status)
  raise "Cannot suspend while in exclusive mode" if exclusive?
  raise "Cannot suspend a task from outside of itself" unless Task.current == self

  @status = status

  # !!! DO NOT INTRODUCE ADDITIONAL GLOBAL VARIABLES !!!
  # rubocop:disable Style/GlobalVars
  if $CELLULOID_DEBUG && @dangerous_suspend
    Internals::Logger.with_backtrace(caller[2...8]) do |logger|
      logger.warn "Dangerously suspending task: type=#{@type.inspect}, meta=#{@meta.inspect}, status=#{@status.inspect}"
    end
  end
  # rubocop:enable Style/GlobalVars

  value = signal

  @status = :running
  raise value if value.is_a?(Celluloid::Interruption)
  value
end
terminate() click to toggle source

Terminate this task

# File lib/celluloid/task.rb, line 110
def terminate
  raise "Cannot terminate an exclusive task" if exclusive?

  if running?
    # !!! DO NOT INTRODUCE ADDITIONAL GLOBAL VARIABLES !!!
    # rubocop:disable Style/GlobalVars
    if $CELLULOID_DEBUG
      Internals::Logger.with_backtrace(backtrace) do |logger|
        type = @dangerous_suspend ? :warn : :debug
        logger.send(type, "Terminating task: type=#{@type.inspect}, meta=#{@meta.inspect}, status=#{@status.inspect}")
      end
    end
    # rubocop:enable Style/GlobalVars

    exception = TaskTerminated.new("task was terminated")
    exception.set_backtrace(caller)
    resume exception
  else
    raise DeadTaskError, "task is already dead"
  end
end

Private Instance Methods

name_current_thread(new_name) click to toggle source
# File lib/celluloid/task.rb, line 162
def name_current_thread(new_name)
  return unless RUBY_PLATFORM == "java"
  if new_name.nil?
    new_name = Thread.current[:celluloid_original_thread_name]
    Thread.current[:celluloid_original_thread_name] = nil
  else
    Thread.current[:celluloid_original_thread_name] = Thread.current.to_java.getNativeThread.get_name
  end
  Thread.current.to_java.getNativeThread.set_name(new_name)
end
thread_metadata() click to toggle source
# File lib/celluloid/task.rb, line 173
def thread_metadata
  method = @meta && @meta[:method_name] || "<no method>"
  klass = Thread.current[:celluloid_actor] &&
          Thread.current[:celluloid_actor].behavior.subject.bare_object.class ||
          "<no actor>"
  format("[Celluloid] %s#%s", klass, method)
end