doushao6874 2019-06-12 10:12
浏览 21

如何计算尽可能晚在通道上发送的消息?

My scenario:

  • I have a producer and a consumer. Both are goroutines, and they communicate through one channel.
  • The producer is capable of (theoretically) generating a message at any time.
  • Generating a message requires some computation.
  • The message is somewhat time-sensitive (i.e. the older it is, the less relevant it is).
  • The consumer reads from the channel occasionally. For the sake of this example, let's say the consumer uses a time.Ticker to read a message once every couple of seconds.
  • The consumer would prefer "fresh" messages (i.e. messages that were generated as recently as possible).

So, the question is: How can the producer generate a message as late as possible?


Sample code that shows the general idea:

func producer() {
    for {
        select {
        ...
        case pipe <- generateMsg():
            // I'd like to call generateMsg as late as possible,
            // i.e. calculate the timestamp when I know
            // that writing to the channel will not block.
        }
    }
}

func consumer() {
    for {
        select {
        ...
        case <-timeTicker.C:
            // Reading from the consumer.
            msg <- pipe
            ...
        }
    }
}

Full code (slightly different from above) is available at the Go Playground: https://play.golang.org/p/y0oCf39AV6P


One idea I had was to check if writing to a channel would block. If it wouldn't block, then I can generate a message and then send it. However…

  • I couldn't find any way to test if writing to a channel would block or not.
  • In the general case, this is a bad idea because it introduces a racing condition if we have multiple producers. In this specific case, I only have one producer.

Another (bad) idea:

func producer() {
    var msg Message
    for {
        // This is BAD. DON'T DO THIS!
        select {
        case pipe <- msg:
            // It may send the same message multiple times.
        default:
            msg = generateMsg()
            // It causes a busy-wait loop, high CPU usage
            // because it re-generates the message all the time.
        }
    }
}
  • 写回答

1条回答 默认 最新

  • dounai1986 2019-06-12 10:12
    关注

    This answer (for Go non-blocking channel send, test-for-failure before attempting to send?) suggests using a second channel to send a signal from the consumer to the producer:

    1. Consumer wants to get a message (e.g. after receiving a tick from timer.Ticker).
    2. Consumer sends a signal through a side channel to the producer goroutine. (So, for this side channel, the producer/consumer roles are reversed).
    3. Producer receives the signal from the side channel.
    4. Producer starts computing the real message.
    5. Producer sends the message through the main channel.
    6. Consumer receives the message.
    评论

报告相同问题?

悬赏问题

  • ¥15 在获取boss直聘的聊天的时候只能获取到前40条聊天数据
  • ¥20 关于URL获取的参数,无法执行二选一查询
  • ¥15 液位控制,当液位超过高限时常开触点59闭合,直到液位低于低限时,断开
  • ¥15 marlin编译错误,如何解决?
  • ¥15 有偿四位数,节约算法和扫描算法
  • ¥15 VUE项目怎么运行,系统打不开
  • ¥50 pointpillars等目标检测算法怎么融合注意力机制
  • ¥20 Vs code Mac系统 PHP Debug调试环境配置
  • ¥60 大一项目课,微信小程序
  • ¥15 求视频摘要youtube和ovp数据集