File: task.rb

package info (click to toggle)
ruby-stud 0.0.23-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 132 kB
  • sloc: ruby: 435; makefile: 2
file content (64 lines) | stat: -rw-r--r-- 2,134 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
require "thread"
require "stud/interval"

module Stud

  # A Task spawns a thread to execute the given block. execution completion and result retrieval is
  # done using the Task#wait method. A Task is run once and the thread exists upon block completion.
  # A task and its underlying thread are not reusable.
  #
  # Task does not provide a mean to force-interrupt a running task, it only provides the #stop!
  # method to signal the task for a stop request. The task or code block can use the #stop? method
  # to check for a stop request. Note that the #stop! and #stop? methods are thread safe.
  class Task
    # provide access to the underlying thread if ever needed.
    attr_reader :thread

    def initialize(*args, &block)
      # A queue to receive the result of the block
      # TODO(sissel): Don't use a queue, just store it in an instance variable.
      @queue = Queue.new

      @thread = Thread.new(@queue, *args) do |queue, *args|
        begin
          result = block.call(*args)
          queue << [:return, result]
        rescue => e
          queue << [:exception, e]
        end
      end # thread
    end # def initialize

    # wait waits for the task thread to complete and return the block return value
    # if the block raises an exception, this exception is propagated in this
    # wait method.
    # @return [Object, Exception] block return value
    def wait
      @thread.join
      reason, result = @queue.pop

      if reason == :exception
        #raise StandardError.new(result)
        raise result
      else
        return result
      end
    end # def wait

    # stop! requests the task to stop. the Thread#wakeup method is also
    # called so that a sleeping task is waked up and has a chance to verify
    # the stop request using the #stop? method. also see Stud.stop!
    def stop!
      Stud.stop!(@thread)
    end

    # stop? returns true if this task stop! has been called
    # See Stud.stop?
    # @return [Boolean] true if the stop! has been called
    def stop?
      Stud.stop?(@thread)
    end
    alias_method :interrupted?, :stop?

  end # class Task
end # module Stud