我想了解在GHC latest docs的無功例子 -幫助理解在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)
我瞭解大部分程序但兩個問題 -
- 仿若
putSkipChan
操作原子?它似乎通過首先執行takeMVar
來避免阻止putMVar
。但是如果在takeMVar
之後但在putMVar
之前撥打putMVar
,那麼這不會失敗嗎?在這種情況下,程序似乎會永遠封鎖。 - 爲什麼
dupSkipChan
將sem
附加到SkipChan
中的信號量列表?這不是由getSkipChan
完成的。在我看來,調用dupSkipChan
然後getSkipChan
(這似乎是你有要做多讀者)會導致一個塊時putSkipChan
試圖喚醒同一信號量兩次?