如何在Haskell中轮询文件,套接字或句柄以使其可读/可写?

时间:2012-07-31 16:13:03

标签: haskell

我如何从Haskell观看几个文件/套接字并等待它们变得可读/可写?

在Haskell中有类似select / epoll / ...的内容吗?或者我被迫为每个文件/套接字生成一个线程并始终使用该线程中的阻塞资源?

2 个答案:

答案 0 :(得分:14)

问题是错误的:你不是强制为每个文件/套接字生成一个线程并使用阻塞调用,你获取每个文件/套接字产生一个线程并使用阻止调用。这是最干净的解决方案(任何语言);在其他语言中避免它的唯一原因是那里的效率有点低。然而,GHC的线程足够便宜,它在Haskell中效率不高。 (此外,在幕后,GHC的IO管理器使用类似epoll的方式来唤醒线程。)

答案 1 :(得分:2)

select(2)有一个包装:https://hackage.haskell.org/package/select
此处使用示例:https://github.com/pxqr/udev/blob/master/examples/monitor.hs#L36

poll(2)有一个包装器: https://hackage.haskell.org/package/poll

GHC base附带了在GHC.Event模块中包装epoll on Linux(以及其他平台上的等效内容)的功能。
用法示例:

import GHC.Event
import Data.Maybe (fromMaybe)
import Control.Concurrent (threadDelay)

main = do
  fd <- getSomeFileDescriptorOfInterest
  mgr <- fromMaybe (error "Must be compiled with -threaded") <$> getSystemEventManager
  registerFd mgr (\fdkey event -> print event) fd evtRead OneShot
  threadDelay 100000000

http://hackage.haskell.org/package/base-4.11.1.0/docs/GHC-Event.html

的更多文档

https://wiki.haskell.org/Simple_Servers#Epoll-based_event_callbacks使用旧版lib的示例 但是,该示例中的loop已被移至隐藏模块GHC.Event.Manager,并且据我所知,并未公开导出。 GHC.Event本身说“这个模块应该被视为GHC内部。”

Control.Concurrent threadWaitReadthreadWaitWrite。 所以,要翻译上面的epoll例子:

import Control.Concurrent (threadWaitRead)

main = do
  fd <- getSomeFileDescriptorOfInterest
  threadWaitRead fd
  putStrLn "Got a read ready event"

您可以将threadWaitRead及后续IO操作包装在Control.Monad.forever中以重复运行它们。您还可以将事物包装在forkIO中,以便在程序执行其他操作时在后台运行它。