diff --git a/README.md b/README.md index 2ff3da14..b7abf523 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ is distributed under the [ISC license](LICENSE.md). - [A transactional lock-free queue](#a-transactional-lock-free-queue) - [Composing transactions](#composing-transactions) - [Blocking transactions](#blocking-transactions) + - [Timeouts](#timeouts) - [A transactional lock-free leftist heap](#a-transactional-lock-free-leftist-heap) - [Programming with transactional data structures](#programming-with-transactional-data-structures) - [The dining philosophers problem](#the-dining-philosophers-problem) @@ -552,6 +553,61 @@ The retry mechanism essentially allows a transaction to wait for an arbitrary condition and can function as a fairly expressive communication and synchronization mechanism. +#### Timeouts + +```ocaml +# #require "domain-local-timeout" +``` + +```ocaml +# #thread +``` + +```ocaml +# Domain_local_timeout.set_system (module Thread) (module Unix) +- : unit = () +``` + +```ocaml +type timeout = { + passed : 'x.xt:'x Xt.t -> bool; + cancel : unit -> unit; +} +``` + +```ocaml +# let timeoutf seconds = + let passed = Loc.make false in + let cancel = + Domain_local_timeout.set_timeoutf seconds @@ fun () -> + Loc.set passed true + in + { passed = Xt.get passed; + cancel = (cancel :> unit -> unit) } +val timeoutf : float -> timeout = +``` + +```ocaml +# let exit_if ~xt { passed; cancel } = + if passed ~xt then + raise Exit; + Xt.post_commit ~xt cancel; + Retry.later () +val exit_if : xt:'a Xt.t -> timeout -> 'b = +``` + +```ocaml +# let an_empty_stack = stack () in + let timeout = timeoutf 0.1 in + Xt.commit { tx = + Xt.first [ + pop an_empty_stack; + exit_if timeout; + ] + } +Exception: Stdlib.Exit. +``` + #### A transactional lock-free leftist heap Let's implement something a bit more complicated, diff --git a/dune-project b/dune-project index b148ade4..064346d3 100644 --- a/dune-project +++ b/dune-project @@ -11,6 +11,7 @@ (depends (ocaml (>= 5.0)) (domain-local-await (>= 0.1.0)) + domain-local-timeout (mdx (and (>= 1.10.0) :with-test)))) (package (name kcas_data) (synopsis "Compositional lock-free data structures and primitives for communication and synchronization") diff --git a/kcas.opam b/kcas.opam index 4cd451d0..4e883311 100644 --- a/kcas.opam +++ b/kcas.opam @@ -11,6 +11,7 @@ depends: [ "dune" {>= "3.3"} "ocaml" {>= "5.0"} "domain-local-await" {>= "0.1.0"} + "domain-local-timeout" "mdx" {>= "1.10.0" & with-test} "odoc" {with-doc} ] @@ -29,3 +30,6 @@ build: [ ] ] dev-repo: "git+https://github.com/ocaml-multicore/kcas.git" +pin-depends: [ + [ "domain-local-timeout.dev" "git+https://github.com/ocaml-multicore/domain-local-timeout#3c90d77a6b6f7ca77c21ec7be9f803ca2cadb138" ] +] diff --git a/kcas.opam.template b/kcas.opam.template new file mode 100644 index 00000000..b5050e09 --- /dev/null +++ b/kcas.opam.template @@ -0,0 +1,3 @@ +pin-depends: [ + [ "domain-local-timeout.dev" "git+https://github.com/ocaml-multicore/domain-local-timeout#3c90d77a6b6f7ca77c21ec7be9f803ca2cadb138" ] +]