2012-07-14 36 views
5

我希望看到的來源具有不確定性的交織處理,具有類型簽名像不確定地交織管道的源

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

用例是,我已經有一個維護對很多節點開放連接P2P應用網絡,它主要是坐在等待來自其中的任何消息。當消息到達時,它不關心它來自哪裏,但需要儘快處理消息。理論上這種應用(至少在用於類似插座的源時)可以完全繞過GHC的IO管理器,並運行/ etc。直接打電話,但我並不特別在乎它是如何實施的,只要它有效。

是否可能與管道一樣?一個不那麼一般但可能更可行的方法可能是編寫一個[(k, Socket)] -> Source m (k, ByteString)函數來處理所有套接字上的接收。

我注意到管道中的ResumableSource操作,但他們似乎都想知道特定的Sink,這感覺像是一個抽象泄漏,至少對於此操作來說。

+0

你需要比使用forkIO和Source包裝Chan/TChan的簡單解決方案快多少? – 2012-07-14 07:09:16

+0

我不一定需要高性能(我預計最多可以連接到大約1000個這樣的對等體),但我也只是對這些迭代式抽象感興趣,並且想知道是否有可能提供這種類型的操作與管道。對於某些類型的網絡協議來說,這似乎是一個相當常見的用例。 – copumpkin 2012-07-14 07:11:28

+0

我相信事件管理器與您直接或通過某些包使用'select'或'epoll'無關。我不認爲有一個從事件管理器暴露的輪詢接口(如果它是事件管理器,它不會是太多的),所以最終會有大量的線程和chans與大多數設計無關。我要做的是從一個'Source'開始,包裝一個有界的'TChan',最初爲每個連接分配一個線程。如果需要提高性能,請移至活動經理。如果你仍然有問題,總是有FFI。 – 2012-07-14 07:24:54

回答

5

stm-conduit軟件包提供mergeSources,它執行與您正在查找的內容類似但不完全相同的內容。這可能是一個開始的好地方。

+1

接受Michael的回答。它做我所描述的。 – 2012-07-15 00:55:30

+0

任何人都可以詳細說明爲什麼'mergeSources'的類型限制它所處理的'Source'的monad參數的形式爲'ResourceT m'而不是任何'MonadResource'實例? – 2014-07-19 16:55:38

+1

我看不到一個理由,值得向維護人員提出問題。使用'hoist liftResourceT'調用'mergeSources'時,你可以自己修復這個問題。 – 2014-07-19 22:15:00

3

是的,這是可能的。

您可以查詢一堆Source•不用通過派生線程輪詢其中每個線程在配對Source了一個Sink發送輸出到一些併發通道阻滯劑:

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

...然後你定義一個Source該頻道上寫着:

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

注意,這不會比剛剛建立該線程輪詢插座本身不同,但它將會對conduit的其他用戶有用,這些用戶可能想要使用他們定義的套接字來調查除套接字之外的其他內容,因爲它更通用。

如果結合這些功能整合到一個功能,然後調用的API整體看起來是這樣的:

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

...但你仍然可以在那些k之遙,如果你想要的。