Sha256: 79ce48fcf9e7702e8e8fcedc943737a441886e9043d3fa2fe610ff87310eb4be

Contents?: true

Size: 1.35 KB

Versions: 2

Compression:

Stored size: 1.35 KB

Contents

class Asynchronous::Thread
  def initialize(&callable)
    @value = nil
    @value_received = false
    @read, @write = ::IO.pipe
    read_buffer

    @pid = fork(&callable)
  end

  def join
    wait
    receive_value! unless @value_received
    raise(@value.wrapped_error) if @value.is_a?(::Asynchronous::Error)
    self
  end

  def kill
    ::Process.kill('KILL', @pid)

    wait
  rescue Errno::ESRCH
    nil
  end

  def status
    alive? ? 'run' : false
  end

  def value
    join; @value
  end

  protected

  def alive?
    ::Asynchronous::Utils.alive?(@pid)
  end

  def receive_value!
    @write.close
    read_buffer.join
    @read.close
    @value_received = true
  end

  def wait(flag = 0)
    ::Process.wait(@pid, flag)
  rescue Errno::ECHILD
    nil
  end

  def fork(&callable)
    ::Kernel.fork { main(&callable) }
  end

  def read_buffer
    @read_buffer ||= ::Thread.new do
      @value = Marshal.load(@read)
    end
  end

  def main
    ::Asynchronous::ZombiKiller.antidote

    @read.close

    result = begin
      yield
    rescue ::Exception => ex
      ::Asynchronous::Error.new(ex)
    end

    write_result!(result)
  end

  def write_result!(result)
    return unless Asynchronous::ZombiKiller.how_is_mom?
    ::Marshal.dump(result, @write)
    @write.flush
    @write.close
  rescue Errno::EPIPE
    nil
  end
end

# Marshal.load(File.binread(FNAME))

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
asynchronous-4.0.1 lib/asynchronous/thread.rb
asynchronous-4.0.0 lib/asynchronous/thread.rb