在 haskell 中实施频道 -- 解决尴尬的小队
Implementing channels in haskell -- Tackling the awkward squad
在论文 Tackling the awkward squad 中,Simon Peyton Jones 提供了 "possible implementation" 的 Channel
。
type Channel a = (MVar (Stream a) , -- Read end
MVar (Stream a) ) -- Write end (the hole)
type Stream a = MVar (Item a)
data Item a = MkItem a (Stream a)
现在,他实现了这样一个功能putChan :: Channel a -> a -> IO ()
putChan (read, write) val
= do { new_hole <- newEmptyVar ;
old_hole <- takeMVar write ;
putMVar write new_hole ;
putMVar old_hole (MkItem val new_hole) }
上面的函数从 write 中取出一个 MVar,然后将一个空的 MVar 放入其中。
然后它写入从 write.
中提取的 old_hole
问题是,为什么要写入old_hole?已经从write中取出,作用域仅限于当前块,那有什么区别呢?
The question is, why does it write to old_hole? It has been taken out from write and its scope is limited to the current block only, then what difference does it make?
不完全是。 old_hole
在 阅读方 上是 "in scope"。全图还得看newChan
:
newChan = do {
read <- newEmptyMVar ;
write <- newEmptyMVar ;
hole <- newEmptyMVar ;
putMVar read hole ;
putMVar write hole ;
return (read,write) }
所以在调用 newChan
之后 putChan
中的“old_hole
”与 newChan
中的 hole
相同 MVar
。随着通道操作的进行,old_hole
总是嵌套在 read
的 MVar
中的某个地方。
我发现链表式通道的设计一开始真的很难理解。该论文中的插图很好地展示了结构,但基本思想是读者 "peel off" 一层 MVar 来显示一个值,而作者插入 MVar 堆的值 "at the bottom",维护指向最底部的指针。
顺便说一句,这是Control.Concurrent.Chan
中使用的设计
在论文 Tackling the awkward squad 中,Simon Peyton Jones 提供了 "possible implementation" 的 Channel
。
type Channel a = (MVar (Stream a) , -- Read end
MVar (Stream a) ) -- Write end (the hole)
type Stream a = MVar (Item a)
data Item a = MkItem a (Stream a)
现在,他实现了这样一个功能putChan :: Channel a -> a -> IO ()
putChan (read, write) val
= do { new_hole <- newEmptyVar ;
old_hole <- takeMVar write ;
putMVar write new_hole ;
putMVar old_hole (MkItem val new_hole) }
上面的函数从 write 中取出一个 MVar,然后将一个空的 MVar 放入其中。
然后它写入从 write.
问题是,为什么要写入old_hole?已经从write中取出,作用域仅限于当前块,那有什么区别呢?
The question is, why does it write to old_hole? It has been taken out from write and its scope is limited to the current block only, then what difference does it make?
不完全是。 old_hole
在 阅读方 上是 "in scope"。全图还得看newChan
:
newChan = do {
read <- newEmptyMVar ;
write <- newEmptyMVar ;
hole <- newEmptyMVar ;
putMVar read hole ;
putMVar write hole ;
return (read,write) }
所以在调用 newChan
之后 putChan
中的“old_hole
”与 newChan
中的 hole
相同 MVar
。随着通道操作的进行,old_hole
总是嵌套在 read
的 MVar
中的某个地方。
我发现链表式通道的设计一开始真的很难理解。该论文中的插图很好地展示了结构,但基本思想是读者 "peel off" 一层 MVar 来显示一个值,而作者插入 MVar 堆的值 "at the bottom",维护指向最底部的指针。
顺便说一句,这是Control.Concurrent.Chan
中使用的设计