IOU is a Ruby gem for working with the io_uring API. IOU provides a simple and idiomatic API for working with io_uring. IOU does not make any assumptions about the concurrency model in your application. It can be used in multi-threaded, multi-fibered, or callback-based apps. It largely follows the liburing API, but provides certain Ruby-esque amenities to make it easier to use io_uring in Ruby apps.
- Prepare and submit operations: accept, read, write, timeout, nop.
- Cancel operations.
- Multishot timeout, accept, read.
- Setup buffer ring for multishot read (provides a nice boost for read performance).
- Associate arbitrary data with operations.
- Run callback on completion of operations.
- Emit arbitrary values for in-app signalling.
Operations are performed by preparing them (using the different #prep_xxx
methods), submitting them, then waiting or polling for completion of those
operations. Here's a simple example of how IOU is used:
ring = IOU::Ring.new
# prepare a 3 second timeout operation
ring.prep_timeout(interval: 3)
# submit all unsubmitted operations to io_uring
ring.submit
# wait for completion, this will block for 3 seconds!
ring.wait_for_completion
#=> { id: 1, op: :timeout, interval: 3}
Any operation can be cancelled by calling #prep_cancel
:
id = ring.prep_timeout(interval: 3)
...
ring.prep_cancel(id)
Callback-style handling of completions can be done using #process_completions
:
timeout_id = ring.prep_timeout(interval: 3)
ring.submit
# passing true to process_completions means wait for at least one completion
# to be available
ring.process_completions(true) do |completion|
# the completion is a hash containing the operation spec
if completion[:id] == timeout_id
puts "timeout elapsed!"
end
end
# another way to do callbacks is to provide a block to prep_timeout:
timeout_id = ring.prep_timeout(interval: 3) do
puts "timeout elapsed"
end
# wait for completion and trigger the callback
ring.process_completions(true)
I/O operations, such as read
, write
, recv
, send
, accept
etc are done
using raw fd's.
# write to STDOUT using IOU
ring.prep_write(fd: STDOUT.fileno, buffer: 'Hello world!')
ring.submit
ring.wait_for_completion
Examples for using IOU can be found in the examples directory:
- Echo server
- HTTP server
- Event loop (in the style of EventMachine)
- Fiber-based concurrency