Class: Goru::Routines::IO

Inherits:
Goru::Routine show all
Defined in:
lib/goru/routines/io.rb

Overview

public

Constant Summary collapse

READY_STATUSES =
[:io_ready, :ready].freeze
READY_BRIDGE_STATUSES =
[nil, :ready].freeze
INTENTS =
%i[r w].freeze

Instance Attribute Summary collapse

Attributes inherited from Goru::Routine

#debug, #error, #state, #status

Instance Method Summary collapse

Methods inherited from Goru::Routine

#finished, #reactor=, #result, #sleep, #update

Constructor Details

#initialize(state = nil, io:, intent:, event_loop:, &block) ⇒ IO

Returns a new instance of IO.



12
13
14
15
16
17
18
19
20
# File 'lib/goru/routines/io.rb', line 12

def initialize(state = nil, io:, intent:, event_loop:, &block)
  super(state, &block)

  @io = io
  @intent = normalize_intent(intent)
  @event_loop = event_loop
  @status = :orphaned
  @monitor = nil
end

Instance Attribute Details

#intentObject

public


24
25
26
# File 'lib/goru/routines/io.rb', line 24

def intent
  @intent
end

#ioObject (readonly)

public


24
25
26
# File 'lib/goru/routines/io.rb', line 24

def io
  @io
end

#monitorObject

Returns the value of attribute monitor.



26
27
28
# File 'lib/goru/routines/io.rb', line 26

def monitor
  @monitor
end

Instance Method Details

#acceptObject

public


62
63
64
65
66
67
68
69
# File 'lib/goru/routines/io.rb', line 62

def accept
  @io.accept_nonblock
rescue Errno::EAGAIN
  wait
rescue Errno::ECONNRESET, Errno::EPIPE, EOFError
  finished
  nil
end

#adoptedObject

public


30
31
32
# File 'lib/goru/routines/io.rb', line 30

def adopted
  set_status(:ready)
end

#bridge(state = nil, intent:, channel:, &block) ⇒ Object

public


112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/goru/routines/io.rb', line 112

def bridge(state = nil, intent:, channel:, &block)
  raise "routine is already bridged" if @bridge

  intent = normalize_intent(intent)
  validate_intent!(intent)
  self.intent = intent

  @bridge = case intent
  when :r
    Bridges::Readable.new(routine: self, channel: channel)
  when :w
    Bridges::Writable.new(routine: self, channel: channel)
  end

  routine = case intent
  when :r
    Routines::Channels::Readable.new(state, channel: channel, &block)
  when :w
    Routines::Channels::Writable.new(state, channel: channel, &block)
  end

  @reactor.adopt_routine(routine)
  @reactor.wakeup

  routine
end

#bridgedObject

public


141
142
143
# File 'lib/goru/routines/io.rb', line 141

def bridged
  @reactor.wakeup
end

#callObject



54
55
56
57
58
# File 'lib/goru/routines/io.rb', line 54

def call
  super

  @monitor&.interests = @intent
end

#read(bytes) ⇒ Object

public


80
81
82
83
84
85
86
87
# File 'lib/goru/routines/io.rb', line 80

def read(bytes)
  @io.read_nonblock(bytes)
rescue Errno::EAGAIN
  wait
rescue Errno::ECONNRESET, Errno::EPIPE, EOFError
  finished
  nil
end

#ready?Boolean

public

Returns:

  • (Boolean)


50
51
52
# File 'lib/goru/routines/io.rb', line 50

def ready?
  READY_STATUSES.include?(@status) && READY_BRIDGE_STATUSES.include?(@bridge&.status)
end

#unbridgeObject

public


147
148
149
150
# File 'lib/goru/routines/io.rb', line 147

def unbridge
  @bridge = nil
  @reactor.wakeup
end

#waitObject



71
72
73
74
75
76
# File 'lib/goru/routines/io.rb', line 71

def wait
  set_status(:selecting)
  @reactor.register(self) unless @monitor

  throw :continue
end

#wakeupObject

public


36
37
38
39
40
41
42
43
# File 'lib/goru/routines/io.rb', line 36

def wakeup
  # Keep this io from being selected again until the underlying routine is called.
  # Interests are reset in `#call`.
  #
  @monitor&.interests = nil

  set_status(:io_ready)
end

#write(data) ⇒ Object

public


91
92
93
94
95
96
97
98
# File 'lib/goru/routines/io.rb', line 91

def write(data)
  @io.write_nonblock(data)
rescue Errno::EAGAIN
  wait
rescue Errno::ECONNRESET, Errno::EPIPE, EOFError
  finished
  nil
end