during
Simple idiomatic dlang wrapper around linux io_uring(news) asynchronous API.
It's just a low level wrapper, doesn't try to do fancy higher level stuff, but attempts to provide building blocks for it.
Main features:
- doesn't use liburing (doesn't do anything we can't do directly with kernel syscalls in a more D idiomatic way)
@nogc
,nothrow
,betterC
are supported- simple usage with provided API D interface
- range interface to submit and receive operations
- helper functions to prepare operations
- chainable function calls
- up to date with Linux 5.14
Note:
- not all operations are properly tested yet (from Kernel 5.4, 5.5, 5.6, 5.7, 5.8)
- PR's are always welcome
Docs
during
uses adrdox to generate it's documentation. To build your own
copy, run the following command from the root of the during
repository:
path/to/adrdox/doc2 --genSearchIndex --genSource -o generated-docs source
Usage example
import during;
import std.range : drop, iota;
import std.algorithm : copy, equal, map;
Uring io;
auto res = io.setup();
assert(res >= 0, "Error initializing IO");
SubmissionEntry entry;
entry.opcode = Operation.NOP;
entry.user_data = 1;
// custom operation to allow usage customization
struct MyOp { Operation opcode = Operation.NOP; ulong user_data; }
// chain operations
res = io
.put(entry) // whole entry as defined by io_uring
.put(MyOp(Operation.NOP, 2)) // custom op that would be filled over submission queue entry
.putWith!((ref SubmissionEntry e) // own function to directly fill entry in a queue
{
e.prepNop();
e.user_data = 42;
})
.submit(1); // submit operations and wait for at least 1 completed
assert(res == 3); // 3 operations were submitted to the submission queue
assert(!io.empty); // at least one operation has been completed
assert(io.front.user_data == 1);
io.popFront(); // drop it from the completion queue
// wait for and drop rest of the operations
io.wait(2);
io.drop(2);
// use range API to post some operations
iota(0, 16).map!(a => MyOp(Operation.NOP, a)).copy(io);
// submit them and wait for their completion
res = io.submit(16);
assert(res == 16);
assert(io.length == 16); // all operations has completed
assert(io.map!(c => c.user_data).equal(iota(0, 16)));
For more examples, see tests
and examples
subfolders or the documentation.
How to use the library
Just add
dependency "during" version="~>0.1.0"
to your dub.sdl
project file, or
"dependencies": {
"during: "~>0.1.0"
}
to your dub.json
project file.
Running tests
For a normal tests, just run:
dub test
See also Makefile
for other targets.
Note: As we're using silly as a unittest runner, it runs tests in multiple threads by default.
This can be a problem as each io_uring
consumes some pages from memlock
limit (see ulimit -l
).
To avoid that, add -- -t 1
to the command to run it single threaded.
Benchmark
See echo_server sample implementation.