From 8a56b35071a876843b9e94c8517c78de50ab91ee Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Wed, 2 Oct 2024 21:13:32 +1300 Subject: [PATCH] Better window update synchronization. --- lib/async/http/protocol/http2/output.rb | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/async/http/protocol/http2/output.rb b/lib/async/http/protocol/http2/output.rb index 2f2efd4..32ec3d8 100644 --- a/lib/async/http/protocol/http2/output.rb +++ b/lib/async/http/protocol/http2/output.rb @@ -17,7 +17,8 @@ def initialize(stream, body, trailer = nil) @task = nil - @window_updated = Async::Condition.new + @guard = ::Mutex.new + @window_updated = ::ConditionVariable.new end attr :trailer @@ -33,17 +34,26 @@ def start(parent: Task.current) end def window_updated(size) - @window_updated.signal + @guard.synchronize do + @window_updated.signal + end end def write(chunk) until chunk.empty? maximum_size = @stream.available_frame_size - while maximum_size <= 0 - @window_updated.wait - - 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)