I'm using Crystal bindings for X11 and typical usage looks something like this:
loop do
event = display.next_event # <- blocking!
# do stuff with event
end
This works fine but I can't do anything in parallel now because next_event
is native C code and thus never yields.
xlib's NextEvent is always blocking, also in C. There's a thread about it with possible alternatives, but polling is slower and more CPU demanding than next_event
, so I'd like to stick to that blocking call. Do I have to put this into its separate OS thread? -Dpreview_mt
actually solves this, but that's an experimental flag and makes all concurrency threaded which is unnecessary (edit: Just found out, this is not true, there is spawn same_thread: true do
syntax). What options do I have?
Edit: I just found this is discussed in more detail in this thread which is worth reading on the topic. There's also FileDescriptor
's wait_readable
which can resolve this if you can obtain a FD somehow.
When a lib function blocks, you can't do anything about it in Crystal. You will need to run it in a separate OS thread in order to be able to run other code in parallel. That's what such methods are designed to be used for.
In Crystal, you don't need preview_mt
to just run a separate OS thread. This flag enables multithreaded scheduling for the Crystal runtime. For your use case, you actually just need a dedicated thread to wait for a blocking call to finish.
The thread API is not publicly exposed, but you can use Thread.new { }
to create a new OS thread and run the proc in that thread.
I think we'll need to add a public API for such use cases to the language. But currently, it's not documented (so it might be subject to change, but that's unlikely).