Fix example fiber scheduler reg. writable events

There were two issues:

1. When an IO object is waiting for writablility only (as in test_tcp_accept) the selected hash is empty.
   Therefore selected[fiber] returns nil but needs to default to 0 in order to be or'ed with IO::WRITABLE.

2. When an IO object is waiting for read- or writability (as in test_tcp_connect), but only one of these
   two events arrive, the Fiber and IO object need to be removed from the other `@readable` or `@writable` list.
This commit is contained in:
Lars Kanis 2021-08-25 12:03:35 +02:00 коммит произвёл Samuel Williams
Родитель a2ad0cb7b4
Коммит 9c0582704f
2 изменённых файлов: 46 добавлений и 1 удалений

Просмотреть файл

@ -60,6 +60,7 @@ class Scheduler
readable&.each do |io|
if fiber = @readable.delete(io)
@writable.delete(io) if @writable[io] == fiber
selected[fiber] = IO::READABLE
elsif io == @urgent.first
@urgent.first.read_nonblock(1024)
@ -68,7 +69,8 @@ class Scheduler
writable&.each do |io|
if fiber = @writable.delete(io)
selected[fiber] |= IO::WRITABLE
@readable.delete(io) if @readable[io] == fiber
selected[fiber] = selected.fetch(fiber, 0) | IO::WRITABLE
end
end

Просмотреть файл

@ -97,4 +97,47 @@ class TestFiberIO < Test::Unit::TestCase
assert_kind_of Errno::EPIPE, error
end
def test_tcp_accept
server = TCPServer.new('localhost', 0)
th = Thread.new do
Fiber.set_scheduler(Scheduler.new)
Fiber.schedule do
sender = server.accept
sender.wait_writable
sender.write "hello"
sender.close
end
end
recver = TCPSocket.new('localhost', server.local_address.ip_port)
assert "hello", recver.read
recver.close
server.close
th.join
end
def test_tcp_connect
server = TCPServer.new('localhost', 0)
th = Thread.new do
Fiber.set_scheduler(Scheduler.new)
Fiber.schedule do
sender = TCPSocket.new('localhost', server.local_address.ip_port)
sender.write "hello"
sender.close
end
end
recver = server.accept
assert "hello", recver.read
recver.close
server.close
th.join
end
end