Próbuję zrozumieć przykład MVar w GHC latest docs -Pomoc zrozumienia MVar przykład w Haskell
data SkipChan a = SkipChan (MVar (a, [MVar()])) (MVar())
newSkipChan :: IO (SkipChan a)
newSkipChan = do
sem <- newEmptyMVar
main <- newMVar (undefined, [sem])
return (SkipChan main sem)
putSkipChan :: SkipChan a -> a -> IO()
putSkipChan (SkipChan main _) v = do
(_, sems) <- takeMVar main
putMVar main (v, [])
mapM_ (sem -> putMVar sem()) sems
getSkipChan :: SkipChan a -> IO a
getSkipChan (SkipChan main sem) = do
takeMVar sem
(v, sems) <- takeMVar main
putMVar main (v, sem:sems)
return v
dupSkipChan :: SkipChan a -> IO (SkipChan a)
dupSkipChan (SkipChan main _) = do
sem <- newEmptyMVar
(v, sems) <- takeMVar main
putMVar main (v, sem:sems)
return (SkipChan main sem)
rozumiem większość programu, ale na dwa pytania -
- to operacje takie jak
putSkipChan
atomowy? Wygląda na to, że unikniesz blokowania naputMVar
, wykonując najpierwtakeMVar
. Ale czy to nie zawiedzie, jeśli coś innego zadzwoni pod numerputMVar
potakeMVar
, ale przedputMVar
? W takich przypadkach wygląda na to, że program zostanie zablokowany na zawsze. - Dlaczego
dupSkipChan
dołączyćsem
do listy semaforów wSkipChan
? Czy to nie jest robione przezgetSkipChan
. Wydaje mi się, że wywołaniedupSkipChan
, a następniegetSkipChan
(która wydaje się być tym, co ma zrobić, aby mieć wiele czytników) spowodowałoby blok, gdyputSkipChan
próbuje obudzić ten sam semafor dwa razy?