| Copyright | (c) 2013, 2014 Peter Trsko |
|---|---|
| License | BSD3 |
| Maintainer | peter.trsko@gmail.com |
| Stability | experimental |
| Portability | CPP, NoImplicitPrelude |
| Safe Haskell | Safe-Inferred |
| Language | Haskell2010 |
System.IO.LockFile
Description
Provide exclusive access to a resource using lock file.
- withLockFile :: (MonadMask m, MonadIO m) => LockingParameters -> FilePath -> m a -> Throws LockingException m a
- withLockFile_ :: (MonadMask m, MonadIO m) => LockingParameters -> FilePath -> m () -> Throws LockingException m ()
- withLockFile' :: (MonadMask m, MonadIO m) => LockingParameters -> FilePath -> m a -> m a
- data LockingParameters = LockingParameters {}
- data RetryStrategy
- = No
- | Indefinitely
- | NumberOfTimes !Word8
- data LockingException
- withLockExt :: FilePath -> FilePath
Usage Example
Following example acquires lock file and then waits 1000000 micro seconds
before releasing it. Note also that it is possible to specify retry
strategy. Here we set it to No and therefore this code won't retry to
acquire lock file after first failure.
module Main (main)
where
import Control.Concurrent (threadDelay)
-- From base package, but GHC specific.
import qualified Control.Monad.TaggedException as Exception (handle)
-- From tagged-exception-core package.
-- http://hackage.haskell.org/package/tagged-exception-core
import Data.Default.Class (Default(def))
-- From data-default-class package, alternatively it's possible to use
-- data-default package version 0.5.2 and above.
-- http://hackage.haskell.org/package/data-default-class
-- http://hackage.haskell.org/package/data-default
import System.IO.LockFile
( LockingParameters(retryToAcquireLock)
, RetryStrategy(No)
, withLockFile
)
main :: IO ()
main = handleException
. withLockFile lockParams lockFile $ threadDelay 1000000
where
lockParams = def
{ retryToAcquireLock = No
}
lockFile = "/var/run/lock/my-example-lock"
handleException = Exception.handle
$ putStrLn . ("Locking failed with: " ++) . show
This command line example shows that trying to execute two instances of
example at the same time will result in failure of the second one.
$ ghc example.hs [1 of 1] Compiling Main ( example.hs, example.o ) Linking example ... $ ./example & ./example [1] 7893 Locking failed with: Unable to acquire lock file: "/var/run/lock/my-example-lock" $ [1]+ Done ./example
Run computation with locked resource.
Arguments
| :: (MonadMask m, MonadIO m) | |
| => LockingParameters | |
| -> FilePath | Lock file name. |
| -> m a | |
| -> Throws LockingException m a |
Acquire a lock file before running computation and release it when it's done.
If "action" raises IOException then this is not wrapped by
LockingException. Only IOException that occurred during locking or
unlocking is mapped to LockingException. This doesn't affect the fact
that lock file is removed even if "action" fails.
Arguments
| :: (MonadMask m, MonadIO m) | |
| => LockingParameters | |
| -> FilePath | Lock file name. |
| -> m () | |
| -> Throws LockingException m () |
Type restricted version of withLockFile.
Arguments
| :: (MonadMask m, MonadIO m) | |
| => LockingParameters | |
| -> FilePath | Lock file name. |
| -> m a | |
| -> m a |
Version of withLockFile that hides exception witness from its type
signature.
Configuration
data LockingParameters Source
Locking algorithm parameters. When in doubt, use def, otherwise start
with it. Example:
lockedDo
:: (MonadMask m, MonadIO m)
=> FilePath
-> m a
-> Throws LockingException m a
lockedDo = withLockFile lockParams lockFile
where
lockParams = def
{ retryToAcquireLock = NumberOfTimes 3
}
lockFile = withLockExt "/var/lock/my-app"
Constructors
| LockingParameters | |
Fields
| |
Instances
| Eq LockingParameters | |
| Data LockingParameters | |
| Read LockingParameters | |
| Show LockingParameters | |
| Generic LockingParameters | |
| Default LockingParameters | Defined as:
Sleep interval is inspired by |
| Typeable * LockingParameters | |
| type Rep LockingParameters |
data RetryStrategy Source
Defines strategy for handling situations when lock-file is already acquired.
Constructors
| No | Don't retry at all. |
| Indefinitely | Retry indefinitely. |
| NumberOfTimes !Word8 | Retry only specified number of times.
If equal to zero then it is interpreted same way as |
Instances
Exceptions
data LockingException Source
Constructors
| UnableToAcquireLockFile FilePath | Wasn't able to aquire lock file specified as an argument. |
| CaughtIOException IOException |
|
Utility functions
withLockExt :: FilePath -> FilePath Source
Append default lock file extension. Useful e.g. for generating lock file name out of regular file name.