Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove IO.select #4392

Merged
merged 1 commit into from May 9, 2017
Merged

Remove IO.select #4392

merged 1 commit into from May 9, 2017

Conversation

RX14
Copy link
Contributor

@RX14 RX14 commented May 8, 2017

IO.select frequently confuses users by blocking all fibers, and can easily be replaced by blocking CSP programs.

IO.select frequently confuses users by blocking all fibers, and can easily be
replaced by blocking CSP programs.
@sdogruyol
Copy link
Member

I've bitten a few time by this too. It's confusing and hard to explain to newcomers 😭

@bararchy
Copy link
Contributor

bararchy commented May 9, 2017

And above all unneeded with how Crystal works (non blocking, event loop, etc..)

@ysbaddaden
Copy link
Contributor

Granted. This is long held legacy from before IO got evented. We now use better techniques (eg: epoll, kpoll) to automatically switch contexts as required.

Anybody coming here and lacking support for IO.select, you should spawn fibers to read/write to each IO, and let Crystal switch fibers as available/required. The following example will start a TCP and a UNIX servers, accepting requests concurrently (not blocking each other), then handle each request concurrently, too (not blocking servers from accepting other requests, nor blocking other requests):

def server_loop(server)
  loop do
    spawn handle_client(server.accept)
  end
end

spawn do
  TCPServer.open(9292) { |server| server_loop(server) }
end

spawn do
  UNIXServer.open("/tmp/app.sock") { |server| server_loop(server) }
end

sleep

@ysbaddaden ysbaddaden merged commit be16968 into crystal-lang:master May 9, 2017
@bcardiff bcardiff added this to the Next milestone May 9, 2017
@Singond
Copy link

Singond commented Jan 7, 2023

Does the above apply to one object shared between fibers? For example, say I have a TCPSocket open, and want to use one fiber for writing and another fiber for reading. Is it safe to simply pass the socket to both fibers? I guess this is all right when both fibers run on the same thread, but how about multithreading?

require "socket"

sock = TCPSocket.new "example.org", 80

spawn do
  sock << "request\n"
end

spawn do
  while true
    puts sock.gets
  end
end

sleep

@straight-shoota
Copy link
Member

Yes, that should be perfectly fine as long as reading and writing are clearly separated.
If you read/write concurrently on the same socket though, you might experience interference, even in a single thread. So this should be avoided.

@Singond
Copy link

Singond commented Jan 7, 2023

All right, thanks for the clarification. Crystal really makes this kind of things easy.

By the way, it took me some time to find this thread when searching for the answer. Would it be possible to add this information into the official documentation? It might be helpful to some.

@zw963
Copy link
Contributor

zw963 commented Feb 12, 2023

I create a new thread in form for discuss more deeper real-life use cases for convert IO.select into fiber

https://forum.crystal-lang.org/t/need-document-for-how-porting-io-select-in-ruby-crystal/5374

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants