不确定交错管道的来源

时间:2012-07-14 06:58:02

标签: haskell conduit

我希望看到源的非确定性交错操作,类型签名如

interleave :: WhateverIOMonadClassItWouldWant m => [(k, Source m a)] -> Source m (k, a)

用例是我有一个p2p应用程序,它保持与网络上许多节点的开放连接,而且它主要是坐在等待来自其中任何节点的消息。当消息到达时,它不关心它来自何处,但需要尽快处理消息。理论上,这种应用程序(至少用于类似套接字的源)可以完全绕过GHC的IO管理器并运行select / epoll /等。直接打电话,但我并不特别在意它是如何实现的,只要它有效。

管道可以这样吗?一种不太通用但可能更可行的方法可能是编写一个[(k, Socket)] -> Source m (k, ByteString)函数来处理所有套接字的接收。

我注意到管道中的ResumableSource操作,但它们似乎都想知道特定的Sink,这感觉有点抽象泄漏,至少对于此操作而言。 / p>

2 个答案:

答案 0 :(得分:5)

stm-conduit包提供mergeSources,它执行与您正在寻找的内容类似的内容 - 尽管不完全相同。这可能是一个很好的起点。

答案 1 :(得分:3)

是的,这是可能的。

您可以通过分叉调查线程来轮询一堆Source而不会阻塞,以便在每个线程中将SourceSink配对,并将输出发送到某个并发通道:

concur :: (WhateverIOMonadClassItWouldWant m) => TChan a -> Sink a m r

...然后定义从该频道读取的Source

synchronize :: (WhateverIOMonadClassItWouldWant m) => TChan a -> Source a m r

请注意,这与仅分支线程轮询套接字本身没有什么不同,但对conduit的其他用户可能希望使用Source轮询除套接字以外的其他内容他们定义的是因为它更通用。

如果将这些功能组合到一个功能中,那么调用的整体API将类似于:

poll :: (WhateverIOMonadClassItWouldWant m) => [Source a m r] -> m (Source a m r)

...但如果你愿意,你仍然可以投入k