Class: Celluloid::Task

Inherits:
Object
  • Object
show all
Defined in:
lib/celluloid/tasks.rb

Overview

Tasks are interruptable/resumable execution contexts used to run methods

Direct Known Subclasses

TaskFiber, TaskThread

Defined Under Namespace

Classes: TerminatedError, TimeoutError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type, meta) ⇒ Task

Create a new task

Raises:


31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/celluloid/tasks.rb', line 31

def initialize(type, meta)
  @type     = type
  @meta     = meta
  @status   = :new

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

  actor     = Thread.current[:celluloid_actor]
  @chain_id = 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.current[:celluloid_task] = self
      CallChain.current_id = @chain_id

      actor.tasks << self
      yield
    rescue Task::TerminatedError      # Task was explicitly terminated

    ensure
      name_current_thread nil
      @status = :dead
      actor.tasks.delete self
    end
  end
end

Instance Attribute Details

#chain_idObject

Returns the value of attribute chain_id


28
29
30
# File 'lib/celluloid/tasks.rb', line 28

def chain_id
  @chain_id
end

#guard_warningsObject

Returns the value of attribute guard_warnings


28
29
30
# File 'lib/celluloid/tasks.rb', line 28

def guard_warnings
  @guard_warnings
end

#metaObject (readonly)

Returns the value of attribute meta


27
28
29
# File 'lib/celluloid/tasks.rb', line 27

def meta
  @meta
end

#statusObject (readonly)

Returns the value of attribute status


27
28
29
# File 'lib/celluloid/tasks.rb', line 27

def status
  @status
end

#typeObject (readonly)

Returns the value of attribute type


27
28
29
# File 'lib/celluloid/tasks.rb', line 27

def type
  @type
end

Class Method Details

.currentObject

Obtain the current task


18
19
20
# File 'lib/celluloid/tasks.rb', line 18

def self.current
  Thread.current[:celluloid_task] or raise NotTaskError, "not within a task context"
end

.suspend(status) ⇒ Object

Suspend the running task, deferring to the scheduler


23
24
25
# File 'lib/celluloid/tasks.rb', line 23

def self.suspend(status)
  Task.current.suspend(status)
end

Instance Method Details

#backtraceObject


135
136
# File 'lib/celluloid/tasks.rb', line 135

def backtrace
end

#create(&block) ⇒ Object


68
69
70
# File 'lib/celluloid/tasks.rb', line 68

def create(&block)
  raise "Implement #{self.class}#create"
end

#exclusiveObject

Execute a code block in exclusive mode.


101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/celluloid/tasks.rb', line 101

def exclusive
  if @exclusive
    yield
  else
    begin
      @exclusive = true
      yield
    ensure
      @exclusive = false
    end
  end
end

#exclusive?Boolean

Is this task running in exclusive mode?

Returns:

  • (Boolean)

131
132
133
# File 'lib/celluloid/tasks.rb', line 131

def exclusive?
  @exclusive
end

#guard(message) ⇒ Object


146
147
148
149
150
151
152
# File 'lib/celluloid/tasks.rb', line 146

def guard(message)
  if @guard_warnings
    Logger.warn message if $CELLULOID_DEBUG
  else
    raise message if $CELLULOID_DEBUG
  end
end

#inspectObject

Nicer string inspect for tasks


142
143
144
# File 'lib/celluloid/tasks.rb', line 142

def inspect
  "#<#{self.class}:0x#{object_id.to_s(16)} @type=#{@type.inspect}, @meta=#{@meta.inspect}, @status=#{@status.inspect}>"
end

#resume(value = nil) ⇒ Object

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


94
95
96
97
98
# File 'lib/celluloid/tasks.rb', line 94

def resume(value = nil)
  guard "Cannot resume a task from inside of a task" if Thread.current[:celluloid_task]
  deliver(value)
  nil
end

#running?Boolean

Is the current task still running?

Returns:

  • (Boolean)

139
# File 'lib/celluloid/tasks.rb', line 139

def running?; @status != :dead; end

#suspend(status) ⇒ Object

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


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/celluloid/tasks.rb', line 73

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

  if $CELLULOID_DEBUG && @dangerous_suspend
    Logger.with_backtrace(caller[2...8]) do |logger|
      logger.warn "Dangerously suspending task: type=#{@type.inspect}, meta=#{@meta.inspect}, status=#{@status.inspect}"
    end
  end

  value = signal

  @status = :running
  raise value if value.is_a?(Celluloid::ResumableError)

  value
end

#terminateObject

Terminate this task


115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/celluloid/tasks.rb', line 115

def terminate
  raise "Cannot terminate an exclusive task" if exclusive?

  if running?
    Logger.with_backtrace(backtrace) do |logger|
      logger.debug "Terminating task: type=#{@type.inspect}, meta=#{@meta.inspect}, status=#{@status.inspect}"
    end
    exception = Task::TerminatedError.new("task was terminated")
    exception.set_backtrace(caller)
    resume exception
  else
    raise DeadTaskError, "task is already dead"
  end
end