Class: Async::HTTP::Protocol::HTTP2::Output

Inherits:
Object
  • Object
show all
Defined in:
lib/async/http/protocol/http2/output.rb

Overview

Writes body data to an HTTP/2 stream, respecting flow control windows.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(stream, body, trailer = nil) ⇒ Output

Initialize the output handler.



18
19
20
21
22
23
24
25
26
27
# File 'lib/async/http/protocol/http2/output.rb', line 18

def initialize(stream, body, trailer = nil)
	@stream = stream
	@body = body
	@trailer = trailer
	
	@task = nil
	
	@guard = ::Mutex.new
	@window_updated = ::ConditionVariable.new
end

Instance Attribute Details

#trailerObject (readonly)

Returns the value of attribute trailer.



29
30
31
# File 'lib/async/http/protocol/http2/output.rb', line 29

def trailer
  @trailer
end

Instance Method Details

#close(error = nil) ⇒ Object

This method should only be called from within the context of the output task.



86
87
88
89
# File 'lib/async/http/protocol/http2/output.rb', line 86

def close(error = nil)
	close_write(error)
	stop(error)
end

#close_write(error = nil) ⇒ Object

Finish writing to the stream.



78
79
80
81
82
83
# File 'lib/async/http/protocol/http2/output.rb', line 78

def close_write(error = nil)
	if stream = @stream
		@stream = nil
		stream.finish_output(error)
	end
end

#start(parent: Task.current) ⇒ Object

Start an asynchronous task to write the body to the stream.



32
33
34
35
36
37
38
39
40
# File 'lib/async/http/protocol/http2/output.rb', line 32

def start(parent: Task.current)
	raise "Task already started!" if @task
	
	if @body.stream?
		@task = parent.async(&self.method(:stream))
	else
		@task = parent.async(&self.method(:passthrough))
	end
end

#stop(error) ⇒ Object

This method should only be called from within the context of the HTTP/2 stream.



92
93
94
95
96
97
# File 'lib/async/http/protocol/http2/output.rb', line 92

def stop(error)
	if task = @task
		@task = nil
		task.stop(error)
	end
end

#window_updated(size) ⇒ Object

Signal that the flow control window has been updated.



45
46
47
48
49
50
51
# File 'lib/async/http/protocol/http2/output.rb', line 45

def window_updated(size)
	@guard.synchronize do
		@window_updated.signal
	end
	
	return true
end

#write(chunk) ⇒ Object

Write a chunk of data to the HTTP/2 stream, respecting flow control.



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/async/http/protocol/http2/output.rb', line 55

def write(chunk)
	until chunk.empty?
		maximum_size = @stream.available_frame_size
		
		# We try to avoid synchronization if possible:
		if maximum_size <= 0
			@guard.synchronize do
				maximum_size = @stream.available_frame_size
				
				while maximum_size <= 0
					@window_updated.wait(@guard)
					
					maximum_size = @stream.available_frame_size
				end
			end
		end
		
		break unless chunk = send_data(chunk, maximum_size)
	end
end