summaryrefslogtreecommitdiff
path: root/src/compiler/GF/Infra/Concurrency.hs
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/Concurrency.hs
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/Concurrency.hs')
-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