Skip to content

Instantly share code, notes, and snippets.

@elct9620
Created June 15, 2018 04:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elct9620/a1c61816b506ad4e1d264f0e9357364d to your computer and use it in GitHub Desktop.
Save elct9620/a1c61816b506ad4e1d264f0e9357364d to your computer and use it in GitHub Desktop.
require 'socket'
require 'fiber'
class Selector
def initialize
@readable = {}
@writeable = {}
end
def wait_readable(io)
@readable[io] = Fiber.current
Fiber.yield
@readable.delete(io)
true
end
def run
while @readable.any? || @writeable.any?
readable, writable = IO.select(@readable.keys, @writeable.keys)
readable.each do |io|
@readable[io].resume
end
writable.each do |io|
@writeable[io].resume
end
end
end
end
class Client
def initialize(io, selector)
@io = io
@selector = selector
end
def read(*args)
while result = @io.read_nonblock(*args, exception: false)
case result
when :wait_readable
@selector.wait_readable(@io)
else
return result
end
end
end
end
class FiberChat < TCPServer
def initialize(*args)
super
@selector = Selector.new
end
def handle(conn)
client = Client.new(conn, @selector)
Fiber.new do
msg = ''
loop do
msg += client.read(1).to_s until msg.end_with?("\n")
Kernel.puts msg
msg = ''
end
end.resume
end
def run(&block)
Fiber.new do
while conn = accept_nonblock(exception: false)
case conn
when :wait_readable
@selector.wait_readable(self)
else
handle(conn)
end
end
end.resume
@selector.run
end
end
srv = FiberChat.new 8080
srv.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment