mirror of
https://github.com/ocaml-multicore/eio.git
synced 2025-07-17 00:01:11 -04:00
Compare commits
4 Commits
387fb6d2b9
...
ad7149dc29
Author | SHA1 | Date | |
---|---|---|---|
|
ad7149dc29 | ||
|
9d5aadc3eb | ||
|
610b4c0653 | ||
|
51f33d4539 |
63
CHANGES.md
63
CHANGES.md
@ -1,3 +1,66 @@
|
||||
## v0.12
|
||||
|
||||
New features / API changes:
|
||||
|
||||
- Replace objects with variants (@talex5 @patricoferris #553 #605 #608, reviewed by @avsm).
|
||||
Some potential users found object types confusing, so we now use an alternative scheme for OS resources.
|
||||
For users of the resources, the only thing that changes is the types:
|
||||
|
||||
- Instead of taking an argument of type `#foo`, you should now take `_ foo`.
|
||||
- Instead of returning a value of type `foo`, you should now return `foo_ty Eio.Resource.t`.
|
||||
|
||||
To provide your own implementation of an interface, you now provide a module rather than an object.
|
||||
For example, to provide your own source flow, use `Eio.Flow.Pi.source (module My_source)`.
|
||||
|
||||
If you want to define your own interfaces, see the `Eio.Resource` module documentation.
|
||||
|
||||
- Add `Eio.Pool` (@talex5 @darrenldl #602, reviewed by @patricoferris).
|
||||
A lock-free pool of resources. This is similar to `Lwt_pool`.
|
||||
|
||||
- Add `Eio.Lazy` (@talex5 #609, reviewed by @SGrondin).
|
||||
If one fiber tries to force a lazy value while another is already doing it,
|
||||
this will wait for the first one to finish rather than raising an exception (as `Stdlib.Lazy` does).
|
||||
|
||||
- Add `Eio.Path.native` (@talex5 #603, reviewed by @patricoferris).
|
||||
This is useful when interacting with non-Eio libraries, for spawning sub-processes, and for displaying paths to users.
|
||||
|
||||
- Add `Flow.single_write` (@talex5 #598).
|
||||
|
||||
- Add `Eio.Flow.Pi.simple_copy` (@talex5 #611).
|
||||
Provides an easy way to implement the `copy` operation when making your own sink.
|
||||
|
||||
- Eio_unix: add FD passing (@talex5 #522).
|
||||
Allows opening a file and passing the handle over a Unix-domain socket.
|
||||
|
||||
- Add `Process.run ?is_success` to control definition of success (@SGrondin #586, reviewed by @talex5).
|
||||
|
||||
- Add `Eio_mock.Domain_manager` (@talex5 #610).
|
||||
This mock domain manager runs everything in a single domain, allowing tests to remain deterministic.
|
||||
|
||||
- Add `Eio.Debug.with_trace_prefix` (@talex5 #610).
|
||||
Allows prefixing all `traceln` output. The mock domain manager uses this to indicate which fake domain is running.
|
||||
|
||||
Bug fixes:
|
||||
|
||||
- Fork actions must not allocate (@talex5 #593).
|
||||
When using multiple domains, child processes could get stuck if they forked while another domain held the malloc lock.
|
||||
|
||||
- eio_posix: ignore some errors writing to the wake-up pipe (@talex5 #600).
|
||||
If the pipe is full or closed, the wake-up should simply be ignored.
|
||||
|
||||
Build/test fixes:
|
||||
|
||||
- Fix some MDX problems on Windows (@polytypic #597).
|
||||
|
||||
- The README depends on kcas (@talex5 #606).
|
||||
|
||||
- Clarify configuration for lib_eio_linux and enable tests on other arches (@dra27 #592).
|
||||
|
||||
- eio_linux tests: skip fixed buffer test if not available (@talex5 #604).
|
||||
|
||||
- eio_windows: update available line to win32 (@talex5 #588 #591).
|
||||
|
||||
|
||||
## v0.11
|
||||
|
||||
New features / API changes:
|
||||
|
@ -23,8 +23,8 @@ module Pi = struct
|
||||
|
||||
module type SINK = sig
|
||||
type t
|
||||
val copy : t -> src:_ source -> unit
|
||||
val single_write : t -> Cstruct.t list -> int
|
||||
val copy : t -> src:_ source -> unit
|
||||
end
|
||||
|
||||
module type SHUTDOWN = sig
|
||||
@ -37,7 +37,6 @@ module Pi = struct
|
||||
| Sink : ('t, (module SINK with type t = 't), [> sink_ty]) Resource.pi
|
||||
| Shutdown : ('t, (module SHUTDOWN with type t = 't), [> shutdown_ty]) Resource.pi
|
||||
|
||||
|
||||
let source (type t) (module X : SOURCE with type t = t) =
|
||||
Resource.handler [H (Source, (module X))]
|
||||
|
||||
@ -59,6 +58,22 @@ module Pi = struct
|
||||
H (Source, (module X));
|
||||
H (Sink, (module X));
|
||||
]
|
||||
|
||||
let simple_copy ~single_write t ~src:(Resource.T (src, src_ops)) =
|
||||
let rec write_all buf =
|
||||
if not (Cstruct.is_empty buf) then (
|
||||
let sent = single_write t [buf] in
|
||||
write_all (Cstruct.shift buf sent)
|
||||
)
|
||||
in
|
||||
let module Src = (val (Resource.get src_ops Source)) in
|
||||
try
|
||||
let buf = Cstruct.create 4096 in
|
||||
while true do
|
||||
let got = Src.single_read src buf in
|
||||
write_all (Cstruct.sub buf 0 got)
|
||||
done
|
||||
with End_of_file -> ()
|
||||
end
|
||||
|
||||
open Pi
|
||||
@ -153,20 +168,12 @@ let copy_string s = copy (string_source s)
|
||||
module Buffer_sink = struct
|
||||
type t = Buffer.t
|
||||
|
||||
let copy t ~src:(Resource.T (src, ops)) =
|
||||
let module Src = (val (Resource.get ops Source)) in
|
||||
let buf = Cstruct.create 4096 in
|
||||
try
|
||||
while true do
|
||||
let got = Src.single_read src buf in
|
||||
Buffer.add_string t (Cstruct.to_string ~len:got buf)
|
||||
done
|
||||
with End_of_file -> ()
|
||||
|
||||
let single_write t bufs =
|
||||
let old_length = Buffer.length t in
|
||||
List.iter (fun buf -> Buffer.add_bytes t (Cstruct.to_bytes buf)) bufs;
|
||||
Buffer.length t - old_length
|
||||
|
||||
let copy t ~src = Pi.simple_copy ~single_write t ~src
|
||||
end
|
||||
|
||||
let buffer_sink =
|
||||
|
@ -121,8 +121,13 @@ module Pi : sig
|
||||
|
||||
module type SINK = sig
|
||||
type t
|
||||
val copy : t -> src:_ source -> unit
|
||||
|
||||
val single_write : t -> Cstruct.t list -> int
|
||||
|
||||
val copy : t -> src:_ source -> unit
|
||||
(** [copy t ~src] allows for optimising copy operations.
|
||||
|
||||
If you have no optimisations, you can use {!simple_copy} to implement this using {!single_write}. *)
|
||||
end
|
||||
|
||||
module type SHUTDOWN = sig
|
||||
@ -146,5 +151,8 @@ module Pi : sig
|
||||
| Source : ('t, (module SOURCE with type t = 't), [> source_ty]) Resource.pi
|
||||
| Sink : ('t, (module SINK with type t = 't), [> sink_ty]) Resource.pi
|
||||
| Shutdown : ('t, (module SHUTDOWN with type t = 't), [> shutdown_ty]) Resource.pi
|
||||
|
||||
val simple_copy : single_write:('t -> Cstruct.t list -> int) -> 't -> src:_ source -> unit
|
||||
(** [simple_copy ~single_write] implements {!SINK}'s [copy] API using [single_write]. *)
|
||||
end
|
||||
|
||||
|
@ -42,25 +42,7 @@ module Impl = struct
|
||||
with Unix.Unix_error (code, name, arg) ->
|
||||
raise (Err.wrap code name arg)
|
||||
|
||||
let write_all t bufs =
|
||||
try
|
||||
let rec loop = function
|
||||
| [] -> ()
|
||||
| bufs ->
|
||||
let wrote = Low_level.writev t (Array.of_list bufs) in
|
||||
loop (Cstruct.shiftv bufs wrote)
|
||||
in
|
||||
loop bufs
|
||||
with Unix.Unix_error (code, name, arg) -> raise (Err.wrap code name arg)
|
||||
|
||||
let copy dst ~src =
|
||||
let buf = Cstruct.create 4096 in
|
||||
try
|
||||
while true do
|
||||
let got = Eio.Flow.single_read src buf in
|
||||
write_all dst [Cstruct.sub buf 0 got]
|
||||
done
|
||||
with End_of_file -> ()
|
||||
let copy t ~src = Eio.Flow.Pi.simple_copy ~single_write t ~src
|
||||
|
||||
let single_read t buf =
|
||||
match Low_level.readv t [| buf |] with
|
||||
|
@ -45,14 +45,7 @@ module Impl = struct
|
||||
write_all t bufs;
|
||||
Cstruct.lenv bufs
|
||||
|
||||
let copy dst ~src =
|
||||
let buf = Cstruct.create 4096 in
|
||||
try
|
||||
while true do
|
||||
let got = Eio.Flow.single_read src buf in
|
||||
write_all dst [Cstruct.sub buf 0 got]
|
||||
done
|
||||
with End_of_file -> ()
|
||||
let copy t ~src = Eio.Flow.Pi.simple_copy ~single_write t ~src
|
||||
|
||||
let single_read t buf =
|
||||
match Low_level.read_cstruct t buf with
|
||||
|
Loading…
x
Reference in New Issue
Block a user