我如何监视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
中有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
中包装该内容,以便在程序执行其他操作时在后台运行它。