10

我怎么能从 Haskell 中观察几个文件/套接字并等待它们变得可读/可写?

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

4

2 回答 2

15

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

于 2012-07-31T16:27:09.190 回答
4

有一个包装器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 带有将 Linux 上的 epoll (以及其他平台上的等价物)包装在GHC.Event模块中的功能。
示例用法:

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上使用旧版本库的示例 虽然,该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以便在您的程序执行其他操作时在后台运行它。

于 2018-05-17T05:15:39.010 回答