Add eio_main library to select backend

This allows writing portable applications without depending on a
specific backend such as Eunix.
This commit is contained in:
Thomas Leonard 2021-05-25 11:20:53 +01:00
parent 72440f5df5
commit 879d94e55b
6 changed files with 54 additions and 9 deletions

View File

@ -60,6 +60,7 @@ It is able to run a web-server with good performance, but most features are stil
- `eio` provides a high-level, cross-platform OS API.
- `eunix` provides a Linux io-uring backend for these APIs,
plus a low-level API that can be used directly (in non-portable code).
- `eio_main` selects an appropriate backend (e.g. `eunix`), depending on your platform.
- `ctf` provides tracing support.
## Getting started
@ -78,14 +79,14 @@ git clone --recursive https://github.com/ocaml-multicore/eio.git
cd eio
opam pin -yn ./ocaml-uring
opam pin -yn .
opam depext -i eunix utop
opam depext -i eio_main utop
```
To try out the examples interactively, run `utop` and `require` the `eunix` library.
To try out the examples interactively, run `utop` and `require` the `eio_main` library.
It is also convenient to open the `Fibreslib` module:
```ocaml
# #require "eunix";;
# #require "eio_main";;
# open Fibreslib;;
```
@ -97,10 +98,10 @@ let main ~stdout =
Eio.Sink.write stdout ~src
```
To run it, we use `Eunix.run` to run the event loop and call it from there:
To run it, we use `Eio_main.run` to run the event loop and call it from there:
```ocaml
# Eunix.run @@ fun env ->
# Eio_main.run @@ fun env ->
main ~stdout:(Eio.Stdenv.stdout env);;
Hello, world!
- : unit = ()
@ -113,13 +114,16 @@ Note that:
- The type of the `main` function here tells us that this program only interacts via `stdout`.
- `Eio_main.run` automatically calls the appropriate run function for your platform.
For example, on Linux this will call `Eunix.run`. For non-portable code you can use the platform-specific library directly.
## Testing with mocks
Because external resources are provided to `main` as arguments, we can easily replace them with mocks for testing.
e.g.
```ocaml
# Eunix.run @@ fun _env ->
# Eio_main.run @@ fun _env ->
let buffer = Buffer.create 20 in
main ~stdout:(Eio.Sink.of_buffer buffer);
traceln "Main would print %S" (Buffer.contents buffer);;
@ -135,7 +139,7 @@ so let's make a little wrapper to simplify future examples:
```ocaml
let run fn =
Eunix.run @@ fun _ ->
Eio_main.run @@ fun _ ->
try fn ()
with Failure msg -> traceln "Error: %s" msg
```
@ -286,7 +290,7 @@ And here is the equivalent using Eio:
```ocaml
# let () =
Eunix.run @@ fun env ->
Eio_main.run @@ fun env ->
let src = Eio.Stdenv.stdin env in
let dst = Eio.Stdenv.stdout env in
Eio.Sink.write dst ~src

2
dune
View File

@ -1,3 +1,3 @@
(mdx
(packages eunix)
(packages eio_main)
(files README.md))

View File

@ -48,4 +48,11 @@
(ocplib-endian (>= 1.1))
(mtime (>= 1.2.0))
(cstruct (>= 6.0.0))))
(package
(name eio_main)
(synopsis "Effect-based direct-style IO mainloop for OCaml")
(description
"Selects an appropriate Eio backend for the current platform.")
(depends
(eunix (= :version))))
(using mdx 0.1)

29
eio_main.opam Normal file
View File

@ -0,0 +1,29 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
synopsis: "Effect-based direct-style IO mainloop for OCaml"
description: "Selects an appropriate Eio backend for the current platform."
maintainer: ["anil@recoil.org"]
authors: ["Anil Madhavapeddy" "Thomas Leonard"]
license: "ISC"
homepage: "https://github.com/ocaml-multicore/eio"
bug-reports: "https://github.com/ocaml-multicore/eio/issues"
depends: [
"dune" {>= "2.8"}
"eunix" {= version}
"odoc" {with-doc}
]
build: [
["dune" "subst"] {dev}
[
"dune"
"build"
"-p"
name
"-j"
jobs
"@install"
"@runtest" {with-test}
"@doc" {with-doc}
]
]
dev-repo: "git+https://github.com/ocaml-multicore/eio.git"

4
lib_main/dune Normal file
View File

@ -0,0 +1,4 @@
(library
(name eio_main)
(public_name eio_main)
(libraries eunix))

1
lib_main/eio_main.ml Normal file
View File

@ -0,0 +1 @@
let run fn = Eunix.run (fun env -> fn (env :> Eio.Stdenv.t))