summaryrefslogtreecommitdiff
path: root/Utility
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2014-08-20 16:45:58 -0400
committerGravatar Joey Hess <joey@kitenet.net>2014-08-20 16:45:58 -0400
commit679d9c0027ac996eea9f41a6f0f39af436801e89 (patch)
treed98ae7ba049e2daa4a99e6bcf55054bde5e5ab4d /Utility
parent86f9d7734d0c638d4c966fd87a5d7e97759e125b (diff)
reorganize and refactor lock code
Added a convenience Utility.LockFile that is not a windows/posix portability shim, but still manages to cut down on the boilerplate around locking. This commit was sponsored by Johan Herland.
Diffstat (limited to 'Utility')
-rw-r--r--Utility/LockFile.hs20
-rw-r--r--Utility/LockFile/Posix.hs47
-rw-r--r--Utility/LockFile/Windows.hs (renamed from Utility/WinLock.hs)11
3 files changed, 73 insertions, 5 deletions
diff --git a/Utility/LockFile.hs b/Utility/LockFile.hs
new file mode 100644
index 000000000..4f0d4ba3e
--- /dev/null
+++ b/Utility/LockFile.hs
@@ -0,0 +1,20 @@
+{- Lock files
+ -
+ - Posix and Windows lock files are extremely different.
+ - This module does *not* attempt to be a portability shim, it just exposes
+ - the native locking of the OS.
+ -
+ - Copyright 2014 Joey Hess <joey@kitenet.net>
+ -
+ - License: BSD-2-clause
+ -}
+
+{-# LANGUAGE CPP #-}
+
+module Utility.LockFile (module X) where
+
+#ifndef mingw32_HOST_OS
+import Utility.LockFile.Posix as X
+#else
+import Utility.LockFile.Windows as X
+#endif
diff --git a/Utility/LockFile/Posix.hs b/Utility/LockFile/Posix.hs
new file mode 100644
index 000000000..1538b491a
--- /dev/null
+++ b/Utility/LockFile/Posix.hs
@@ -0,0 +1,47 @@
+{- Posix lock files
+ -
+ - Copyright 2014 Joey Hess <joey@kitenet.net>
+ -
+ - License: BSD-2-clause
+ -}
+
+module Utility.LockFile.Posix (
+ lockShared,
+ lockExclusive,
+ dropLock,
+ createLockFile,
+ LockHandle
+) where
+
+import System.IO
+import System.Posix
+
+type LockFile = FilePath
+
+newtype LockHandle = LockHandle Fd
+
+-- Takes a shared lock, blocking until the lock is available.
+lockShared :: Maybe FileMode -> LockFile -> IO LockHandle
+lockShared = lock ReadLock
+
+-- Takes an exclusive lock, blocking until the lock is available.
+lockExclusive :: Maybe FileMode -> LockFile -> IO LockHandle
+lockExclusive = lock WriteLock
+
+-- The FileMode is used when creating a new lock file.
+lock :: LockRequest -> Maybe FileMode -> LockFile -> IO LockHandle
+lock lockreq mode lockfile = do
+ l <- createLockFile mode lockfile
+ waitToSetLock l (lockreq, AbsoluteSeek, 0, 0)
+ return (LockHandle l)
+
+-- Create and opens lock file, does not lock it.
+-- Close on exec flag is set so child processes do not inherit the lock.
+createLockFile :: Maybe FileMode -> LockFile -> IO Fd
+createLockFile mode lockfile = do
+ l <- openFd lockfile ReadWrite mode defaultFileFlags
+ setFdOption l CloseOnExec True
+ return l
+
+dropLock :: LockHandle -> IO ()
+dropLock (LockHandle fd) = closeFd fd
diff --git a/Utility/WinLock.hs b/Utility/LockFile/Windows.hs
index fc7c8a8a9..73c248b03 100644
--- a/Utility/WinLock.hs
+++ b/Utility/LockFile/Windows.hs
@@ -5,7 +5,7 @@
- License: BSD-2-clause
-}
-module Utility.WinLock (
+module Utility.LockFile.Windows (
lockShared,
lockExclusive,
dropLock,
@@ -17,9 +17,6 @@ import System.Win32.Types
import System.Win32.File
import Control.Concurrent
-{- Locking is exclusive, and prevents the file from being opened for read
- - or write by any other process. So for advisory locking of a file, a
- - different LockFile should be used. -}
type LockFile = FilePath
type LockHandle = HANDLE
@@ -30,7 +27,11 @@ lockShared :: LockFile -> IO (Maybe LockHandle)
lockShared = openLock fILE_SHARE_READ
{- Tries to take an exclusive lock on a file. Fails if another process has
- - a shared or exclusive lock. -}
+ - a shared or exclusive lock.
+ -
+ - Note that exclusive locking also prevents the file from being opened for
+ - read or write by any other progess. So for advisory locking of a file's
+ - content, a different LockFile should be used. -}
lockExclusive :: LockFile -> IO (Maybe LockHandle)
lockExclusive = openLock fILE_SHARE_NONE