Affect.PortSynchronous one-to-one rendezvous.
A port provides a handle on which functions can exchange values with a one-to-one synchronous rendezvous:
Port.offer blocks until there is matching Port.take call.Port.take blocks until there is matching Port.offer call.See examples.
val make : unit -> 'a tmake () is a new port.
val offer : 'a t -> 'a -> unitval take : 'a t -> 'aThis shows how two functions can be made to synchronize via a port.
let f () =
let p = Port.make () in
let v = Fun.Async.call @@ fun () -> Port.take p in
let _call = Fun.Async.call @@ fun () -> Port.offer p "hey!" in
assert (Fun.Async.get v = "hey!")The following example is from the action basics section, it defines an action derived from port actions that allows two functions to agree on a value both may propose. It also shows that Affect.Action.choose is really a choice: only one action returns, so in propose'the offer and take on the same port in the same choice cannot match together.
let propose' p v =
let ours = Port.offer' p v v in
let theirs = Port.take' p in
Action.choose [ours; theirs]
let propose p v = Action.invoke (propose' p v)
let f () =
let p = Port.make () in
let v0 = Fun.Async.call @@ fun () -> propose p "hey!" in
let v1 = Fun.Async.call @@ fun () -> propose p "ho!" in
let v0, v1 = Fun.Async.get v0, Fun.Async.get v1 in
assert (v0 = v1 && (v0 = "hey!" || v0 = "ho!"))In this example we show actions are first-class values, they can be transferred over ports.
let f () =
let c = Fun.Async.call @@ fun () -> 3.14 in
let p = Port.make () in
let _c = Fun.Async.call @@ fun () -> Port.offer p (Fun.Async.get' c) in
let v = Fun.Async.call @@ fun () -> Action.invoke (Port.take p) in
assert (Fun.Async.get v = 3.14)