gpt4 book ai didi

haskell - 管道和非管道代码之间的并发注意事项

转载 作者:行者123 更新时间:2023-12-04 20:06:24 27 4
gpt4 key购买 nike

我正在为管道接口(interface)中的某些编码包装一个 C 库,但我遇到了一些需要做出的设计决策。

建立 C 库后,我们保留一个编码器上下文。有了这个,我们可以编码,或者改变一些参数(让我们调用 Haskell 接口(interface)到最后一个函数 tune :: Context -> Int -> IO () )。我的问题有两个部分:

  • 编码部分很容易包含在 Pipe Foo Bar IO () 中。 ,但我也想曝光tune .由于同时使用编码上下文必须受到锁保护,因此我需要在管道中的每次迭代时都锁定,并保护 tune使用相同的锁。但现在我觉得我在强制用户隐藏锁。我在这里吠错树了吗?这种情况在管道生态系统中通常是如何解决的?就我而言,我希望我的特定代码所属的管道始终在其自己的线程中运行,同时进行调整,但我不想将这种观点强加给任何用户。管道生态系统中的其他软件包似乎也没有强制他们的用户喜欢。
  • 不再使用的编码上下文需要正确地取消初始化。在管道生态系统中,如何确保在管道被破坏时处理这些事情(在这种情况下执行 som IO 操作)?

  • 一个具体的例子是包装一个压缩库,在这种情况下,上面可以是:
  • 压缩强度是可调的。我们设置了管道,它愉快地运行。假设必须序列化对压缩编解码器上下文的并发访问,最好如何在管道继续运行时更改压缩强度设置?
  • 压缩库在设置时从 Haskell 堆中分配了一堆内存,当管道被拆除时,我们需要调用一些库函数来清理这些内存。

  • 谢谢......这可能都很明显,但我对管道生态系统很陌生。

    编辑:发布后阅读此内容,我很确定这是我在这里问过的最模糊的问题。啊!对不起 ;-)

    最佳答案

    关于(1),一般的解决方案是改变你的Pipe的类型为:

    Pipe (Either (Context, Int) Foo) Bar IO ()

    换句话说,它同时接受 Foo输入和 tune请求,它在内部处理。

    那么让我们假设你有两个并发的 Producer s 对应于输入和调整请求:
    producer1 :: Producer Foo IO ()

    producer2 :: Producer (Context, Int) IO ()

    您可以使用 pipes-concurrency创建一个它们都输入的缓冲区,如下所示:
    example = do
    (output, input) <- spawn Unbounded
    -- input :: Input (Either (Context, Int) Foo)
    -- output :: Output (Either (Context, Int) Foo)

    let io1 = runEffect $ producer1 >-> Pipes.Prelude.map Right >-> toOutput output
    io2 = runEffect $ producer2 >-> Pipes.Prelude.map Left >-> toOutput output
    as <- mapM async [io1, io2]
    runEffect (fromInput >-> yourPipe >-> someConsumer)
    mapM_ wait as

    您可以了解更多关于 pipes-concurrency图书馆阅读 this tutorial .

    通过强制所有调整请求通过相同的单线程 Pipe您可以确保不会意外同时调用 tune功能。

    关于 (2) 有两种方法可以使用 pipes 获取资源.更复杂的方法是使用 pipes-safe库,它提供了 bracket可以在 Pipe 中使用的函数,但这对于您的目的来说可能是多余的,并且只存在于在管道的生命周期内获取和释放多个资源。更简单的解决方案是使用以下 with获取管道的成语:
    withEncoder :: (Pipe Foo Bar IO () -> IO r) -> IO r
    withEncoder k = bracket acquire release $ \resource -> do
    k (createPipeFromResource resource)

    然后用户会写:
    withEncoder $ \yourPipe -> do
    runEffect (someProducer >-> yourPipe >-> someConsumer)

    您可以选择使用 managed包,它稍微简化了类型,并且更容易获取多个资源。您可以通过阅读 this blog post of mine 了解更多信息.

    关于haskell - 管道和非管道代码之间的并发注意事项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25649213/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com