Tôi đang cố gắng để hiểu được ví dụ MVAr trong GHC latest docs -Trợ giúp hiểu dụ MVAr trong 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)
Tôi hiểu hầu hết các chương trình nhưng đối với hai câu hỏi -
- Are hoạt động như
putSkipChan
nguyên tử? Dường như tránh chặn trênputMVar
bằng cách trước tiên thực hiệntakeMVar
. Nhưng điều đó sẽ không thành công nếu một cái gì đó khác gọiputMVar
sautakeMVar
nhưng trướcputMVar
? Trong những trường hợp như vậy, có vẻ như chương trình sẽ chặn mãi mãi. - Tại sao
dupSkipChan
nối thêmsem
vào danh sách các ẩn dụ trongSkipChan
? Điều đó không được thực hiện bởigetSkipChan
. Dường như với tôi gọi sốdupSkipChan
, theo sau làgetSkipChan
(có vẻ như những gì bạn có cần làm để có nhiều người đọc) sẽ gây ra một khối khiputSkipChan
cố gắng đánh thức cùng một semaphore hai lần?