Ticket #5943: mvarBug.hs

File mvarBug.hs, 3.8 KB (added by cobb, 14 months ago)
Line 
1{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2
3import Control.Applicative
4import Control.Monad
5import Control.Monad.Fix
6import Data.IORef
7import Data.Maybe
8import Prelude hiding (until)
9import System.Mem.Weak
10
11newtype Signal a = S (IO a) deriving (Functor, Applicative, Monad)
12type UpdatePool = [Weak (IO (), IO ())]
13newtype SignalGen a = SG { unSG :: IORef UpdatePool -> IO a }
14data Phase a = Ready a | Updated a a
15
16instance Functor SignalGen where
17    fmap = liftM
18
19instance Applicative SignalGen where
20    pure = return
21    (<*>) = ap
22
23instance Monad SignalGen where
24    return x = SG $ \_ -> return x
25    SG g >>= f = SG $ \p -> g p >>= \x -> unSG (f x) p
26
27instance MonadFix SignalGen where
28    mfix f = SG $ \p -> mfix $ \x -> unSG (f x) p
29
30start :: SignalGen (Signal a) -- ^ the generator of the top-level signal
31      -> IO (IO a)            -- ^ the computation to sample the signal
32start (SG gen) = do
33    pool <- newIORef []
34    S sample <- gen pool
35    return $ do
36        print "res <- sample"
37        res <- sample
38        print "superstep pool"
39        superstep pool
40        print "return res"
41        return res
42
43-- | Performing the two-phase superstep.
44superstep :: IORef UpdatePool -> IO ()
45superstep pool = loop id []
46  where
47    deref ptr = (fmap.fmap) ((,) ptr) (deRefWeak ptr)
48    loop getPtrs final = do
49      print "(ptrs,acts) <- unzip.catMaybes <$> (mapM deref =<< readIORef pool)"
50      (ptrs,acts) <- unzip.catMaybes <$> (mapM deref =<< readIORef pool)
51      print "case acts of"
52      case acts of
53          [] -> do
54              print "[] -> do sequence_ final"
55              sequence_ final
56              print "writeIORef pool (getPtrs []"
57              writeIORef pool (getPtrs [])
58              print "done: writeIORef pool (getPtrs []"
59          _  -> do
60              print "_  -> do writeIORef pool []"
61              writeIORef pool []
62              print "mapM_ fst acts"
63              mapM_ fst acts
64              print "loop ((ptrs++) . getPtrs) (mapM_ snd acts : final)"
65              loop ((ptrs++) . getPtrs) (mapM_ snd acts : final)
66              print "done: loop ((ptrs++) . getPtrs) (mapM_ snd acts : final)"
67
68delay :: a                    -- ^ initial output at creation time
69      -> Signal a             -- ^ the signal to delay
70      -> SignalGen (Signal a) -- ^ the delayed signal
71delay x0 (S s) = SG $ \pool -> do
72  print "ref <- newIORef (Ready x0)"
73  ref <- newIORef (Ready x0)
74  let update x = print "s >>= \\x' -> x' `seq`" >> s >>= \x' -> x' `seq` (print "    writeIORef ref (Updated x' x)" >> writeIORef ref (Updated x' x))
75      upd = print "readIORef ref >>= \v -> case v of" >> readIORef ref >>= \v -> case v of
76              Ready x -> print "Ready x -> update x" >> update x
77              _       -> print "_       -> return ()" >> return ()
78
79      fin = print "readIORef ref >>= \v -> case v o" >> readIORef ref >>= \v -> case v of
80              Updated x _ -> print "Updated x _ -> writeIORef ref $! Ready x" >> (writeIORef ref $! Ready x)
81              _           -> error "Signal not updated!"
82
83      sig = S $ print "readIORef ref >>= \v -> case v of" >> readIORef ref >>= \v -> case v of
84              Ready x     -> print "Ready x     -> return x" >> return x
85              Updated _ x -> print "Updated _ x -> return x" >> return x
86  print "updateActions <- mkWeak sig (upd,fin) Nothing"
87  updateActions <- mkWeak sig (upd,fin) Nothing
88  print "modifyIORef pool (updateActions:)"
89  modifyIORef pool (updateActions:)
90  print "return sig"
91  return sig
92
93
94stateful :: a                    -- ^ initial state
95         -> (a -> a)             -- ^ state transformation
96         -> SignalGen (Signal a)
97stateful x0 f = mfix $ \sig -> delay x0 (f <$> sig)
98
99main = do
100    net <- start $ stateful 0 (1+)
101    print "1st iteration"
102    net -- ok for first time
103    print "2nd iteration"
104    net -- error: thread blocked indefinitely in an MVar operation