Class: Hyperion::Http2Handler::WriterContext
- Inherits:
-
Object
- Object
- Hyperion::Http2Handler::WriterContext
- Defined in:
- lib/hyperion/http2_handler.rb
Overview
Holds the per-connection outbound coordination state (queue, notifications, byte counters, shutdown flag) plus the encode mutex that protects HPACK state and per-stream frame ordering.
Single instance per connection, lives for the lifetime of ‘serve`.
Instance Attribute Summary collapse
-
#encode_mutex ⇒ Object
readonly
Returns the value of attribute encode_mutex.
-
#t0_serve_entry ⇒ Object
2.10-G — connection-lifecycle timing slots used by the optional h2 latency-instrumentation path (gated by ‘HYPERION_H2_TIMING=1`).
-
#t1_preface_done ⇒ Object
2.10-G — connection-lifecycle timing slots used by the optional h2 latency-instrumentation path (gated by ‘HYPERION_H2_TIMING=1`).
-
#t2_first_encode ⇒ Object
2.10-G — connection-lifecycle timing slots used by the optional h2 latency-instrumentation path (gated by ‘HYPERION_H2_TIMING=1`).
-
#t2_first_wire ⇒ Object
2.10-G — connection-lifecycle timing slots used by the optional h2 latency-instrumentation path (gated by ‘HYPERION_H2_TIMING=1`).
Instance Method Summary collapse
-
#enqueue(bytes) ⇒ Object
Called by SendQueueIO#write on the calling (encoder) fiber.
-
#initialize(max_pending_bytes: MAX_PER_CONN_PENDING_BYTES) ⇒ WriterContext
constructor
A new instance of WriterContext.
-
#note_drained(bytesize) ⇒ Object
Called by the writer fiber after each successful drain to release any encoders blocked on the cap.
- #pending_bytes ⇒ Object
- #queue_empty? ⇒ Boolean
- #shutdown! ⇒ Object
-
#try_pop ⇒ Object
Pops a single chunk; returns nil if the queue is empty (non-blocking).
- #wait_for_signal ⇒ Object
- #writer_done? ⇒ Boolean
Constructor Details
#initialize(max_pending_bytes: MAX_PER_CONN_PENDING_BYTES) ⇒ WriterContext
Returns a new instance of WriterContext.
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/hyperion/http2_handler.rb', line 143 def initialize(max_pending_bytes: MAX_PER_CONN_PENDING_BYTES) @queue = ::Thread::Queue.new @send_notify = ::Async::Notification.new @drained_notify = ::Async::Notification.new @encode_mutex = ::Mutex.new @pending_bytes = 0 @pending_bytes_lock = ::Mutex.new @max_pending_bytes = max_pending_bytes @writer_done = false # 2.10-G timing slots, all initially nil so capture is a single # `||=` write under the encode mutex / writer fiber. @t0_serve_entry = nil @t1_preface_done = nil @t2_first_encode = nil @t2_first_wire = nil end |
Instance Attribute Details
#encode_mutex ⇒ Object (readonly)
Returns the value of attribute encode_mutex.
136 137 138 |
# File 'lib/hyperion/http2_handler.rb', line 136 def encode_mutex @encode_mutex end |
#t0_serve_entry ⇒ Object
2.10-G — connection-lifecycle timing slots used by the optional h2 latency-instrumentation path (gated by ‘HYPERION_H2_TIMING=1`). Each slot is a single CLOCK_MONOTONIC timestamp captured at most once per connection. nil = unset, set on first observation.
141 142 143 |
# File 'lib/hyperion/http2_handler.rb', line 141 def t0_serve_entry @t0_serve_entry end |
#t1_preface_done ⇒ Object
2.10-G — connection-lifecycle timing slots used by the optional h2 latency-instrumentation path (gated by ‘HYPERION_H2_TIMING=1`). Each slot is a single CLOCK_MONOTONIC timestamp captured at most once per connection. nil = unset, set on first observation.
141 142 143 |
# File 'lib/hyperion/http2_handler.rb', line 141 def t1_preface_done @t1_preface_done end |
#t2_first_encode ⇒ Object
2.10-G — connection-lifecycle timing slots used by the optional h2 latency-instrumentation path (gated by ‘HYPERION_H2_TIMING=1`). Each slot is a single CLOCK_MONOTONIC timestamp captured at most once per connection. nil = unset, set on first observation.
141 142 143 |
# File 'lib/hyperion/http2_handler.rb', line 141 def t2_first_encode @t2_first_encode end |
#t2_first_wire ⇒ Object
2.10-G — connection-lifecycle timing slots used by the optional h2 latency-instrumentation path (gated by ‘HYPERION_H2_TIMING=1`). Each slot is a single CLOCK_MONOTONIC timestamp captured at most once per connection. nil = unset, set on first observation.
141 142 143 |
# File 'lib/hyperion/http2_handler.rb', line 141 def t2_first_wire @t2_first_wire end |
Instance Method Details
#enqueue(bytes) ⇒ Object
Called by SendQueueIO#write on the calling (encoder) fiber. Enforces the per-connection backpressure cap before enqueuing.
162 163 164 165 166 167 |
# File 'lib/hyperion/http2_handler.rb', line 162 def enqueue(bytes) wait_for_drain_if_full(bytes.bytesize) @pending_bytes_lock.synchronize { @pending_bytes += bytes.bytesize } @queue << bytes @send_notify.signal end |
#note_drained(bytesize) ⇒ Object
Called by the writer fiber after each successful drain to release any encoders blocked on the cap.
178 179 180 181 182 183 184 |
# File 'lib/hyperion/http2_handler.rb', line 178 def note_drained(bytesize) @pending_bytes_lock.synchronize do @pending_bytes -= bytesize @pending_bytes = 0 if @pending_bytes.negative? # paranoia end @drained_notify.signal end |
#pending_bytes ⇒ Object
205 206 207 |
# File 'lib/hyperion/http2_handler.rb', line 205 def pending_bytes @pending_bytes_lock.synchronize { @pending_bytes } end |
#queue_empty? ⇒ Boolean
201 202 203 |
# File 'lib/hyperion/http2_handler.rb', line 201 def queue_empty? @queue.empty? end |
#shutdown! ⇒ Object
190 191 192 193 194 195 |
# File 'lib/hyperion/http2_handler.rb', line 190 def shutdown! @writer_done = true # Wake the writer if it's parked, and any encoder waiting on drain. @send_notify.signal @drained_notify.signal end |
#try_pop ⇒ Object
Pops a single chunk; returns nil if the queue is empty (non-blocking).
170 171 172 173 174 |
# File 'lib/hyperion/http2_handler.rb', line 170 def try_pop @queue.pop(true) rescue ::ThreadError nil end |
#wait_for_signal ⇒ Object
186 187 188 |
# File 'lib/hyperion/http2_handler.rb', line 186 def wait_for_signal @send_notify.wait end |
#writer_done? ⇒ Boolean
197 198 199 |
# File 'lib/hyperion/http2_handler.rb', line 197 def writer_done? @writer_done end |