我怎么能从 Haskell 中观察几个文件/套接字并等待它们变得可读/可写?
Haskell 中是否有类似 select/epoll/... 的东西?或者我被迫为每个文件/套接字生成一个线程并始终使用该线程内的阻塞资源?
我怎么能从 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 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
里面有threadWaitRead
和threadWaitWrite
。所以,翻译上面的 epoll 例子:
import Control.Concurrent (threadWaitRead)
main = do
fd <- getSomeFileDescriptorOfInterest
threadWaitRead fd
putStrLn "Got a read ready event"
您可以将threadWaitRead
后续的 IO 操作包装起来Control.Monad.forever
以重复运行它们。您还可以将这个东西包装起来,forkIO
以便在您的程序执行其他操作时在后台运行它。