Sync/choice-evt 在多个通道上(数量在运行时确定)

Sync/choice-evt over multiple channels (number determined at runtime)

我正在尝试创建一个非常简单的程序,旨在测量 select 和跨多个通道同步所需的时间。本质上,这个概念很简单,我有一个发送者和一个接收者。在多次迭代中,发件人随机 select 选择已提供的两个频道之一,并在该频道上发送消息。作为其中的一部分,我需要能够控制所涉及的频道数量作为程序的命令行参数,因此我不能将预定数量的频道硬编码到程序中。问题是,我无法弄清楚如何从 Synchronisation 模块获取 syncchoice-evt 以使用多个通道。

整个程序(我目前拥有的)如下:

#lang racket

(provide main)
(require racket/random)

(define (sender iterations channels)
  (match iterations
    [0 (displayln "sender completed")]
    [iter 
           (let ([choice-chan (random-ref channels)])
             (channel-put choice-chan iter)
             (sender (- iter 1) channels))]))

(define (receiver iterations channels notification-semaphore)
  (match iterations
    [0 (begin
         (displayln "receiver completed")
         (semaphore-post notification-semaphore))]
    [iter
     (let ([ignored-choice (sync (choice-evt (vector->values channels)))])
        (begin (displayln ignored-choice)
        (receiver (- iter 1) channels notification-semaphore)))]))

(define (experiment iterations num-channels)
  (let ([channels
         (vector->immutable-vector
          (build-vector num-channels (λ (i) (make-channel))))]
        [notification-semaphore (make-semaphore)])
    (thread (λ () (receiver iterations channels notification-semaphore)))
    (thread (λ () (sender iterations channels)))
    (semaphore-wait notification-semaphore)))

(define (main iterations num-channels)
  (experiment (string->number iterations) (string->number num-channels))
  (displayln "SelectTime completed successfully"))

displayln 表达式并不是绝对必要的,它们只是为了让我可以看到确实有一些东西从发送者传递到接收者。

我遇到的问题是,当我只使用一个通道时,似乎一切正常。但是,对于两个或多个通道,我收到一个运行时错误,抱怨元数不匹配 - 预期为 1 个值,但提供了 2 个(如果我在命令行上指定了更多,则提供了更多)。据我所知,在处理内部表达式后,此错误发生在 receiver 函数内部对 (choice-evt (vector->values channels)) 求值时。我已经尝试了所有我能想到的变体,例如直接使用 channels 而没有 vector->values;将向量更改为列表;删除 choice-evt (特别是因为,如果我正确阅读文档,那实际上对我的测试来说并不是必需的);在 let.

中的变量声明之外移动 sync 发生的位置

当通道数量在运行时未知时,如何同步多个通道?看起来使用向量或列表不是解决此问题的正确方法,但我对 的正确方法有点困惑。

P.S。如果您认为这可能有帮助,请在回答时随时以其他方式批评该程序:)

您可以使用 apply 从可变长度的 列表 频道中制作 choice-evt。例如,在上面的代码中,将 sync 调用更改为以下内容:

(sync (apply choice-evt (vector->list channels)))