summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2015-06-21 17:10:13 +0200
committerGregor Kleen <gkleen@yggdrasil.li>2015-06-21 17:10:13 +0200
commitd8ea165173a2b7ba514bb3eafac3d21fc1f4d086 (patch)
tree0d53f6c2db8ee286956eb57e39acaf62754e42b1 /src
parent42c671b4a48dd1431ab43c1f842af33e2fe5cbe9 (diff)
downloadtrivmix-d8ea165173a2b7ba514bb3eafac3d21fc1f4d086.tar
trivmix-d8ea165173a2b7ba514bb3eafac3d21fc1f4d086.tar.gz
trivmix-d8ea165173a2b7ba514bb3eafac3d21fc1f4d086.tar.bz2
trivmix-d8ea165173a2b7ba514bb3eafac3d21fc1f4d086.tar.xz
trivmix-d8ea165173a2b7ba514bb3eafac3d21fc1f4d086.zip
Switched build system structure & locks
Diffstat (limited to 'src')
-rw-r--r--src/Trivmix.hs32
1 files changed, 20 insertions, 12 deletions
diff --git a/src/Trivmix.hs b/src/Trivmix.hs
index 0c1a1a4..79b3804 100644
--- a/src/Trivmix.hs
+++ b/src/Trivmix.hs
@@ -27,6 +27,7 @@ import Control.Exception
27import System.IO.Error 27import System.IO.Error
28import System.IO 28import System.IO
29 29
30import System.FileLock
30import System.INotify 31import System.INotify
31 32
32import Data.Char 33import Data.Char
@@ -164,12 +165,13 @@ handleFiles :: INotify -> MVar Level -> [FilePath] -> IO ()
164handleFiles inotify level files = do 165handleFiles inotify level files = do
165 initLevel <- readMVar level 166 initLevel <- readMVar level
166 levelChanges <- (newChan :: IO (Chan Level)) 167 levelChanges <- (newChan :: IO (Chan Level))
168 stderrLock <- newMVar
167 let 169 let
168 handleFile file = do 170 handleFile file = do
169 levelChanges' <- dupChan levelChanges 171 levelChanges' <- dupChan levelChanges
170 forkIO $ forever $ do -- Broadcast level changes and update all files 172 forkIO $ forever $ do -- Broadcast level changes and update all files
171 readChan levelChanges' >>= writeLevel file 173 readChan levelChanges' >>= writeLevel file stderrLock
172 addWatch inotify watchedAttrs file (const $ readLevel levelChanges level file) 174 addWatch inotify watchedAttrs file (const $ readLevel levelChanges level file stderrLock)
173 mapM handleFile files 175 mapM handleFile files
174 forkIO $ forever $ do 176 forkIO $ forever $ do
175 readChan levelChanges >>= swapMVar level 177 readChan levelChanges >>= swapMVar level
@@ -193,7 +195,7 @@ onStateFile file initial action = do
193 hPutStrLn stderr $ "Removing ‘" ++ file ++ "’ (file)" 195 hPutStrLn stderr $ "Removing ‘" ++ file ++ "’ (file)"
194 removeFile file 196 removeFile file
195 acquireDir = (flip mapM) (reverse createDirs) $ \directory -> do 197 acquireDir = (flip mapM) (reverse createDirs) $ \directory -> do
196 hPutStrLn stderr $ "Creating ‘" ++ directory ++ "’ (dir" 198 hPutStrLn stderr $ "Creating ‘" ++ directory ++ "’ (dir)"
197 createDirectory directory 199 createDirectory directory
198 setFileMode directory defDirectoryMode 200 setFileMode directory defDirectoryMode
199 releaseDir = (flip mapM) createDirs $ \directory -> do 201 releaseDir = (flip mapM) createDirs $ \directory -> do
@@ -214,19 +216,21 @@ takeWhileM pred (x:xs) = do
214 False -> do 216 False -> do
215 return [] 217 return []
216 218
217readLevel :: Chan Level -> MVar Level -> FilePath -> IO () 219readLevel :: Chan Level -> MVar Level -> FilePath -> MVar () -> IO ()
218readLevel levelChan current file = catch action handler 220readLevel levelChan current file stderrLock = catch action handler
219 where 221 where
220 action = do 222 action = do
221 level <- readFile file >>= readIO . stripSpace 223 level <- withFileLock file Shared $ readFile file >>= readIO . stripSpace
222 oldLevel <- readMVar current 224 oldLevel <- readMVar current
223 when (oldLevel /= level) $ do 225 when (oldLevel /= level) $ do
224 writeChan levelChan level 226 writeChan levelChan level
225 hPutStrLn stderr $ "Detected new level: " ++ (show level) 227 withMVarLock stderrLock $
228 hPutStrLn stderr $ "Detected new level: " ++ (show level)
226 handler e = if isUserError e 229 handler e = if isUserError e
227 then do 230 then do
228 hPutStrLn stderr $ "Could not parse new level from ‘" ++ file ++ "’ - overwriting." 231 withMVarLock stderrLock $
229 readMVar current >>= writeLevel file 232 hPutStrLn stderr $ "Could not parse new level from ‘" ++ file ++ "’ - overwriting."
233 readMVar current >>= writeLevel file stderrLock
230 else throw e 234 else throw e
231 stripSpace = reverse . stripSpace' . reverse . stripSpace' 235 stripSpace = reverse . stripSpace' . reverse . stripSpace'
232 stripSpace' [] = [] 236 stripSpace' [] = []
@@ -234,7 +238,11 @@ readLevel levelChan current file = catch action handler
234 then stripSpace' xs 238 then stripSpace' xs
235 else l 239 else l
236 240
237writeLevel :: FilePath -> Level -> IO () 241writeLevel :: FilePath -> MVar () -> Level -> IO ()
238writeLevel file level = do 242writeLevel file stderrLock level = withFileLock file Exclusive $ do
239 hPutStrLn stderr $ "Writing out level ‘" ++ (show level) ++ "’ to ‘" ++ file ++ "’" 243 withMVarLock stderrLock $
244 hPutStrLn stderr $ "Writing out level ‘" ++ (show level) ++ "’ to ‘" ++ file ++ "’"
240 writeFile file (show level ++ "\n") 245 writeFile file (show level ++ "\n")
246
247withMVarLock :: MVar () -> IO a -> IO a
248withMVarLock lock = bracket_ (putMVar lock ()) (takeMVar lock)