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



我如何监视Haskell中的几个文件/套接字并等待它们变得可读写?

有类似select/epoll/…的东西吗。。。在哈斯克尔?或者我被迫为每个文件/套接字生成一个线程,并始终使用该线程中的阻塞资源?

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

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基础提供了在GHC.Event模块中封装Linux上的epoll(以及其他平台上的等效功能)的功能
示例用法:

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

在中使用旧版本的lib的示例https://wiki.haskell.org/Simple_Servers#Epoll-based_event_callbacks尽管如此,该示例中的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中包装该内容,以便在程序执行其他操作时在后台运行它。

最新更新