Haskell中的并发文件读/写?

时间:2014-04-30 18:35:35

标签: haskell file-io concurrency

我有一个大文件,用于存储Binary数据。有多个线程读取和写入这些文件,我当前的设计使用单个Lock同步它们。这样,我在Handle中只有一个ReadWriteMode打开一个文件,并且所有线程在他们想要做一些I / O时争取单个锁。

我想通过允许多个读者同时工作来改进这一点。我尝试的是使用RWLock并打开多个Handles。 RWLock将确保只有一个线程修改文件,同时允许多个线程(我有多个句柄打开,编译时常量)同时读取。在尝试运行时,我被Handle中的运行时allows only one ReadWriteMode随时存在于文件中。

我该如何解决这种情况?我假设获取/释放Handle是一项昂贵的操作,因此在获取RWLock之后只是以适当的模式打开文件并不是一个真正的选择。或者也许有一个包提供类似于Java FileChannel的{​​{3}}和read方法的API?

PS:我想支持32位架构,因此文件无法实现内存映射IO> 4GiB,对吧?

2 个答案:

答案 0 :(得分:1)

您应该围绕文件句柄和互斥锁构建一个类型。这是一个简单的实现,我认为它可以用于您的目的。

module SharedHandle (SharedHandle, newSharedHandle, withSharedHandle) where

import Control.Concurrent.MVar
import System.IO              

data SharedHandle = SharedHandle Handle (MVar ())

newSharedHandle :: IO Handle -> IO SharedHandle
newSharedHandle makeHandle = do
    handle <- makeHandle
    lock <- newMVar()
    return $ SharedHandle handle lock

withSharedHandle :: SharedHandle -> (Handle -> IO a) -> IO a
withSharedHandle (SharedHandle handle lock) operation = do
    () <- takeMVar lock
    val <- operation handle
    putMVar lock ()
    return val

我在这里做的是我创建了一个新的数据类型,就其本质而言,只是一个文件句柄。唯一的区别是它还带有自己的个人互斥锁,用MVar实现。我提供了两个用于操作这种新类型的函数。 newSharedHandle执行一个操作,该操作将创建一个普通句柄并创建一个带有全锁的共享句柄。 withSharedHandle接受一个操作来操作句柄,锁定共享句柄,执行操作,然后解锁句柄。请注意,模块不提供构造函数或访问器,因此我们可以确保没有任何进程忘记释放锁定,并且我们永远不会在一次特定访问时遇到死锁。

使用这种新类型替换程序中的所有文件句柄可以解决您的问题。

答案 1 :(得分:1)

所以你的问题是你不想使用有状态Handle s(状态是文件中的当前位置)?在这种情况下,我猜你需要preadpwrite

man pread

对于Haskell绑定:http://hackage.haskell.org/package/unix-bytestring-0.3.7.2/docs/System-Posix-IO-ByteString.html

有关用法示例,您可以在此处查看:https://github.com/errge/PrefetchFS/blob/master/PrefetchHandle.hs