为什么需要两个双向通道来实现单元的服务器协议?


需要

两个双向通道来实现协议似乎很奇怪。我们不能只使用一个通道并更改服务器循环以提供和接受该单个通道吗?请注意,这在 Hopac 中是允许的,不会造成任何问题。作业不能在单个同步操作中使用通道向自身发送消息。解释如果只有一个通道而不是单独的 getCh 和 putCh 通道会出错。提示:考虑具有多个客户端的情况。

以上来自霍帕克文档。

新用户是否真的期望在旅程的这个阶段了解库实施的细节?我更喜欢文档给出答案而不是提出问题。为什么对takeget使用单一通道是一个坏主意?

module HopacExample
open System
open Hopac
open Hopac.Infixes
type Cell<'a> = {
takeCh : Ch<'a>
putCh : Ch<'a>
}
let get c = Ch.take c.takeCh
let put c (x: 'a) = Ch.give c.putCh x
let cell x = Job.delay <| fun () ->
let c = {takeCh = Ch (); putCh = Ch ()}
let server x = 
Alt.choose [
Ch.take c.putCh
Ch.give c.takeCh x ^->. x]
Job.iterateServer x server >>-. c
run <| job {
let! c = cell 1
let print () = Job.start (get c >>- fun i -> printf "%in" i)
let put i = Job.start (put c i)
do! print()
do! put 2
do! print()
do! put 3
do! print()
do! put 4
do! print()
do! put 5
do! print()
do! put 6
do! print()
}
Console.ReadKey()
2
3
4
4
5
6
module HopacExample2
open System
open Hopac
open Hopac.Infixes
let get c = Ch.take c
let put c (x: 'a) = Ch.give c x
let cell x = Job.delay <| fun () ->
let c = Ch ()
let server x = 
Alt.choose [
Ch.take c
Ch.give c x ^->. x]
Job.iterateServer x server >>-. c
run <| job {
let! c = cell 1
let print () = Job.start (get c >>- fun i -> printf "%in" i)
let put i = Job.start (put c i)
do! print()
do! put 2
do! print()
do! put 3
do! print()
do! put 4
do! print()
do! put 5
do! print()
do! put 6
do! print()
}
Console.ReadKey()
5
5
5
5
5
6

有一些差异,但我不会归因于并发的变幻莫测。

您需要两个通道的原因是强制用户通过服务器。如果您完全删除了服务器,您将能够知道仅使用单个通道的问题是什么。仅使用单个通道,客户端可能会绕过服务器并直接相互通信。

module HopacExample2
open System
open Hopac
open Hopac.Infixes
let get c = Ch.take c
let put c (x: 'a) = Ch.give c x
let cell x = 
let c = Ch ()
Job.start (put c x) >>-. c
run <| job {
let! c = cell 1
let print () = Job.start (get c >>- fun i -> printf "%in" i)
let put i = Job.start (put c i)
for i=2 to 6 do
do! print()
do! put i
}
Console.ReadKey()

最新更新