我希望看到源的非确定性交错操作,类型签名如
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>
答案 0 :(得分:5)
stm-conduit包提供mergeSources,它执行与您正在寻找的内容类似的内容 - 尽管不完全相同。这可能是一个很好的起点。
答案 1 :(得分:3)
是的,这是可能的。
您可以通过分叉调查线程来轮询一堆Source
而不会阻塞,以便在每个线程中将Source
与Sink
配对,并将输出发送到某个并发通道:
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
。