管道和非管道代码之间的并发考虑

时间:2014-09-03 16:21:25

标签: haskell api-design haskell-pipes

我正在为管道界面中的某些编码包装C库,但我已经做了一些需要做出的设计决策。

在设置C库之后,我们继续编码器上下文。有了这个,我们可以编码或更改一些参数(让我们将Haskell接口调用到最后一个函数tune :: Context -> Int -> IO ())。我的问题分为两部分:

  1. 编码部分很容易包含在Pipe Foo Bar IO ()中,但我还希望公开tune。由于编码上下文的同时使用必须受到锁定保护,因此我需要在管道中的每次迭代时锁定,并使用相同的锁保护tune。但现在我觉得我正在强迫用户隐藏锁定。我在这里吠叫错了吗?这种情况通常如何在管道生态系统中得到解决?在 my 的情况下,我希望我的特定代码所属的管道始终在自己的线程中运行,同时进行调优,但我不想强迫任何用户使用这种观点。管道生态系统中的其他软件包似乎也不会强迫用户使用。
  2. 需要正确地取消初始化不再使用的编码上下文。在管道生态系统中,如何确保在管道被销毁时处理这些事情(在这种情况下执行索姆IO操作)?
  3. 一个具体的例子是包装压缩库,在这种情况下,上面可以是:

    1. 压缩强度可调。我们设置了管道并快速运行。假设必须序列化对压缩编解码器上下文的并发访问,那么最好如何在管道保持运行时更改压缩强度设置?
    2. 压缩库在设置时从Haskell堆中分配了一堆内存,当管道被拆除时,我们需要调用一些库函数来清理它。
    3. 谢谢......这可能都很明显,但我对管道生态系统还很陌生。

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

1 个答案:

答案 0 :(得分:4)

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

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

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

那么让我们假设您有两个对应于输入和调优请求的并发Producer

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

通过阅读this tutorial,您可以了解有关pipes-concurrency库的更多信息。

通过强制所有调优请求通过相同的单线程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了解更多信息。