Affect.PortSourceSynchronous 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.
The type for ports with values of type 'a.
This 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)