rainbows.git  about / heads / tags
Unicorn for sleepy apps and slow clients
blob dcd8c14abf501832f244ece92a9a0b8e73d70135 2643 bytes (raw)
$ git show HEAD:lib/rainbows/fiber/io.rb	# shows this blob on the CLI

  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
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
 
# -*- encoding: binary -*-
# :enddoc:
# A \Fiber-aware IO class, gives users the illusion of a synchronous
# interface that yields away from the current \Fiber whenever
# the underlying descriptor is blocked on reads or write
#
# It's not recommended to use any of this in your applications
# unless you're willing to accept breakage.  Most of this is very
# difficult-to-use, fragile and we don't have much time to devote to
# supporting these in the future.
#
# This is a stable, legacy interface and should be preserved for all
# future versions of Rainbows!  However, new apps should use
# Rainbows::Fiber::IO::Socket or Rainbows::Fiber::IO::Pipe instead
# (or better yet, avoid any of the Rainbows::Fiber* stuff).
class Rainbows::Fiber::IO
  attr_accessor :to_io

  # :stopdoc:
  # see Rainbows::Fiber::IO::Compat for initialize implementation
  class << self
    alias :[] :new
  end
  # :startdoc:

  # no longer used internally within Rainbows!, only for compatibility
  def write_nonblock(buf)
    @to_io.write_nonblock(buf)
  end

  def kgio_addr
    @to_io.kgio_addr
  end

  # for wrapping output response bodies
  def each
    buf = readpartial(16384)
    yield buf
    yield buf while readpartial(16384, buf)
  rescue EOFError
    self
  end

  def closed?
    @to_io.closed?
  end

  def fileno
    @to_io.fileno
  end

  def write(buf)
    case rv = Kgio.trywrite(@to_io, buf)
    when String
      buf = rv
    when :wait_writable
      kgio_wait_writable
    end until nil == rv
  end

  # used for reading headers (respecting keepalive_timeout)
  def timed_read(buf)
    expire = nil
    case rv = Kgio.tryread(@to_io, 16384, buf)
    when :wait_readable
      return if expire && expire < Rainbows.now
      expire ||= read_expire
      kgio_wait_readable
    else
      return rv
    end while true
  end

  def readpartial(length, buf = "")
    case rv = Kgio.tryread(@to_io, length, buf)
    when nil
      raise EOFError, "end of file reached", []
    when :wait_readable
      kgio_wait_readable
    else
      return rv
    end while true
  end

  def kgio_read(*args)
    @to_io.kgio_read(*args)
  end

  def kgio_read!(*args)
    @to_io.kgio_read!(*args)
  end

  def kgio_trywrite(*args)
    @to_io.kgio_trywrite(*args)
  end

  autoload :Socket, 'rainbows/fiber/io/socket'
  autoload :Pipe, 'rainbows/fiber/io/pipe'
end

# :stopdoc:
require 'rainbows/fiber/io/methods'
require 'rainbows/fiber/io/compat'
class Rainbows::Fiber::IO
  include Rainbows::Fiber::IO::Compat
  include Rainbows::Fiber::IO::Methods
  alias_method :wait_readable, :kgio_wait_readable
  alias_method :wait_writable, :kgio_wait_writable
end

git clone https://yhbt.net/rainbows.git