2015-05-20 18 views
5

Haskell'de iletiyi uygulamak için kanalları/STM'yi kullanmaya çalışıyorum. Belki bu korkunç bir fikir, ve Haskell'de geçen mesajı uygulamak/kullanmak için daha iyi bir yol var. Bu durumda, bana bildirin; Ancak, araştırmam eş zamanlı Haskell hakkında bazı temel sorular açmıştır.Haskell, Kanallar, STM, iletilen, İleti Gönderiliyor

STM ve özellikle de Haskell'deki uygulama hakkında harika şeyler duydum. Okumayı ve yazmayı desteklediğinden ve bazı güvenlik avantajlarına sahip olduğundan, birisinin orada başlayacağını düşündüm. Bu benim en büyük soru karşımıza çıkıyor: chan bir TChan Int

msg <- atomically $ readTChan chan 

, üzerinde bir değere sahip kanal için bekleyen bir bekleme neden olur?

aşağıdaki programı düşünün:

p chan = do 
    atomically $ writeTChan chan 1 
    atomically $ writeTChan chan 2 

q chan = do 
    msg1 <- atomically $ readTChan chan 
    msg2 <- atomically $ readTChan chan 
    -- for testing purposes 
    putStrLn $ show msg1 
    putStrLn $ show msg2 

main = do 
    chan <- atomically $ newTChan 
    p chan 
    q chan 

ghc açığa kavuşturabilir -threaded ile bu derlemek ve programı çalıştırın ve gerçekten de sen 1 konsola baskılı ardından 2 olsun. Şimdi, bunun yerine

main = do 
    chan <- atomically $ newTChan 
    forkIO $ p chan 
    forkIO $ q chan 

yaptığımızı varsayalım. Şimdi, eğer - dişliyi kullanırsak, ya hiç bir şey basmayacak, 1 ya da 1, sonra 2'ye terminali basacak; Bununla birlikte, eğer-ile-derlemediyseniz, her zaman 1 sonra 2'yi basar. Soru 2: -işaretli ile değil arasındaki fark nedir? Eşzamanlı şeyler olarak çalışmadıklarını hayal ediyorum ve onlar birbiri ardına koşuyorlar. Bu aşağıdaki ile tutarlıdır.

Şimdi, benim düşüncemde p ve q eşzamanlı olarak çalışıyor olsaydım; yani onları çatallıyorum, ters sırada koşabilmeli. Farz edelim ki, eğer bu olmadan bir derleme yapmazsam, konsola basılmış hiçbir şey elde edemiyorum. Eğer ben ile derlediysem, bazen yaparım. Her ne kadar 1'i 2, genellikle sadece 1'i ya da hiçbir şeyi almamak çok nadirdir. Bunu Control.Concurrent.Chan ile de denedim ve tutarlı sonuçlar elde ettim.

İkinci büyük soru: Kanallar ve çatallar birlikte nasıl çalıyor ve yukarıdaki programda neler oluyor?

Herhangi bir oranda, STM ile iletilen iletiyi böylesine saf bir şekilde benzemediğim görülüyor. Belki de Cloud Haskell bu sorunları çözen bir seçenek - gerçekten bilmiyorum. İleti alıp vermeyle ilgili bilgi almak için, ~~> sokete yazınız ~~> soketinden ~~> okuduğumuzda, seriyi okuyacaksınız.

+0

Re çağrıları geçerseniz çalışmaya devam edecektir: "-threaded değil arasındaki fark nedir", Hoşunuza gidebilecek [ Haskell'in diş modeli ile ilgili açıklamam] (http://dmwit.com/gtk2hs). Gtk özgü bitleri yoksayın. –

cevap

8

Hayır senin fikrin doğru - sadece forkIO küçük bir noktaya cevapsız - Bu kindof olduğu için hangi TChan s:

sorun ana iş parçacığı ile oluşturulan iş parçacığı bitmesini beklemek alışkanlık olduğunu forkIO (see here for reference)

yüzden referans verilen ipucu kullanımı ise:

import Control.Concurrent 
import Control.Concurrent.STM 

p :: Num a => TChan a -> IO() 
p chan = do 
    atomically $ writeTChan chan 1 
    atomically $ writeTChan chan 2 

q chan = do 
    msg1 <- atomically $ readTChan chan 
    msg2 <- atomically $ readTChan chan 
    -- for testing purposes 
    putStrLn $ show msg1 
    putStrLn $ show msg2 

main :: IO() 
main = do 
    children <- newMVar [] 
    chan <- atomically $ newTChan 
    _ <- forkChild children $ p chan 
    _ <- forkChild children $ q chan 
    waitForChildren children 
    return() 

waitForChildren :: MVar [MVar()] -> IO() 
waitForChildren children = do 
    cs <- takeMVar children 
    case cs of 
    [] -> return() 
    m:ms -> do 
     putMVar children ms 
     takeMVar m 
     waitForChildren children 

forkChild :: MVar [MVar()] -> IO() -> IO ThreadId 
forkChild children io = do 
    mvar <- newEmptyMVar 
    childs <- takeMVar children 
    putMVar children (mvar:childs) 
    forkFinally io (\_ -> putMVar mvar()) 

bu iş s beklendiği gibi:

d:/Temp $ ghc --make -threaded tchan.hs 
[1 of 1] Compiling Main    (tchan.hs, tchan.o) 
Linking tchan.exe ... 
d:/Temp $ ./tchan.exe 
1 
2 
d:/Temp $ 

ve tabii ki sen p ve q çok

+1

bu 'forkChild' /' waitForChildren' şey kolaylaştırabilirsiniz herhangi modül/kütüphane var mı? – Bergi