summaryrefslogtreecommitdiff
path: root/src/compiler/GF/Infra
diff options
context:
space:
mode:
authorhallgren <hallgren@chalmers.se>2014-09-08 15:43:20 +0000
committerhallgren <hallgren@chalmers.se>2014-09-08 15:43:20 +0000
commit4eb6b55e980fda9c4d260820f5a6d38dde3d0991 (patch)
treec771181c860137fb7a5bec7eaf3f899292b00aae /src/compiler/GF/Infra
parent4d28c7632e83aed413c22001ec0821971f58f14d (diff)
(1) Refactor concurrency, (2) write to .gfo.tmp then rename to .gfo
(1) introduces the module GF.Infra.Concurreny with lifted concurrency operators (to reduce uses of liftIO) and some additional concurrency utilities, e.g. a function for sequential logging that is used in both GF.CompileInParallel and GFServer. (2) avoids leaving broken .gfo files behind if compilation is aborted.
Diffstat (limited to 'src/compiler/GF/Infra')
-rw-r--r--src/compiler/GF/Infra/Concurrency.hs48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/compiler/GF/Infra/Concurrency.hs b/src/compiler/GF/Infra/Concurrency.hs
new file mode 100644
index 000000000..5fc15ead7
--- /dev/null
+++ b/src/compiler/GF/Infra/Concurrency.hs
@@ -0,0 +1,48 @@
+-- | Lifted concurrency operators and a some useful concurrency abstractions
+module GF.Infra.Concurrency(
+ module GF.Infra.Concurrency,
+ C.forkIO,
+ C.MVar,C.modifyMVar,C.modifyMVar_,
+ C.Chan
+ ) where
+import qualified Control.Concurrent as C
+import System.IO.Unsafe(unsafeInterleaveIO)
+import Control.Monad((<=<))
+import Control.Monad.Trans(MonadIO(..))
+
+-- * Futures
+
+newtype Future a = Future {now::IO a}
+
+spawn io = do v <- newEmptyMVar
+ C.forkIO $ putMVar v =<< io
+ return (Future (readMVar v))
+
+parMapM f = mapM now <=< mapM (spawn . f)
+
+-- * Single-threaded logging
+
+newLog put =
+ do logchan <- newChan
+ liftIO $ C.forkIO (mapM_ put =<< getChanContents logchan)
+ return (writeChan logchan)
+
+-- * Lifted concurrency operators
+
+newMVar x = liftIO $ C.newMVar x
+readMVar v = liftIO $ C.readMVar v
+putMVar v = liftIO . C.putMVar v
+
+newEmptyMVar :: MonadIO io => io (C.MVar a)
+newEmptyMVar = liftIO C.newEmptyMVar
+
+newChan :: MonadIO io => io (C.Chan a)
+newChan = liftIO C.newChan
+
+getChanContents ch = liftIO $ C.getChanContents ch
+writeChan ch = liftIO . C.writeChan ch
+
+
+-- * Delayed IO
+
+lazyIO = unsafeInterleaveIO