2010-01-11 5 views
8

제목이 다소 흐릿 할 수 있습니다. 이것은 내가 의미하는 바입니다 :하스켈의 두 입력을 동시에 기다리는 중

두 가지 방법으로 프로그램에 입력 할 수 있습니다. 첫 번째는 키보드를 통해 getLine 함수를 사용하여 행이 읽힐 때까지 차단합니다. 다른 하나는 TChan을 통해 말하며, readTChan chan을 사용하면 채널에 값이 나타날 때까지 블록이 만들어지고 읽히게됩니다.

모두 값을 기다릴 수 있습니다. 단일 스레드를 사용하고 CPU가 100 %로 이동하지 못하도록합니다. 두 값 중 하나를 사용할 수있게되면이 값을 가져와 프로그램을 다시 시작합니다. (두 가지 값 중 어느 것을 수신했는지 알려면 Either을 사용하십시오.)

이것이 가능합니까?

대단히 감사합니다!

+1

어떻게 IO 스레드 호출의 getline을 가진, 그리고뿐만 아니라 TChan에 그 결과를 넣어 어떻습니까? 그것이 작동해야하는 것처럼 들리는데. – yairchu

+0

정확히 하나의 스레드를 사용하고 싶습니까? 예를 들어, 3 개의 입력을 기다릴 필요가 없다면 어떻게 될까요? 아니면 5? 아니면 10? 왜 임의의 제한 사항입니까? – ADEpt

+0

여러 스레드가 사용되고 있고 CPU가 100 %였던 코드가 있다고 생각합니까? 다른 사람들이 이유를 알 수 있도록 코드를 게시 할 수도 있습니다. 올바른 해결책은 스레드이며 단순히 구현 문제 일 수 있습니다. – Godeke

답변

12

"단일 스레드 사용"이 여기에 적합하다고 생각하지 않습니다. 어쨌든 TChan에 쓰려면 하스켈 스레드를 여러 개 사용해야합니다. 이 작업을 수행하려면 두 개의 Haskell 스레드를 사용해야하며 MVar 또는 유사한 것을 사용하여 도착한 첫 번째 결과를 전달해야합니다. 예를 들면 다음과 같습니다.

module Main where 

import System.IO 
import Control.Concurrent 
import Control.Concurrent.MVar 
import Control.Concurrent.STM 
import Control.Concurrent.STM.TChan 

main = do 
    chan <- newTChanIO 
    forkIO (threadTChanWrite chan) 
    threadMultiplexedRead chan 

threadTChanWrite chan = do 
    threadDelay 5000000 
    atomically $ writeTChan chan 3 

threadMultiplexedRead chan = do 
    mvar <- newEmptyMVar 
    forkIO (threadKeyboardRead mvar) 
    forkIO (threadTChanRead mvar chan) 
    v <- readMVar mvar 
    print v 

threadKeyboardRead mvar = do 
    str <- getLine 
    putMVar mvar (Right str) 

threadTChanRead mvar chan = do 
    v <- atomically (readTChan chan) 
    putMVar mvar (Left v) 

적절하게 구현하면 나중에 남아있는 스레드가 정리됩니다 (btw).

5

나는 내 프로그램에 입력을 얻는 두 가지 방법이

당신은 공유 채널에 결과를 기록, 각각의 입력을 기다릴 2 개 스레드, 입력 소스 당 하나를 사용할 수 있어야합니다 또는 mvar가 제 3 스레드에 의해 관리된다.

+0

-1 : Q가 싱글 스레드 sol'n을 요구하는 방법을 무시했습니다. –

+3

@Charles 요점을 놓치고 있습니다. 하나 이상의 스레드를 사용하지 않는 것이 무의미하며, 그 사람은 왜 그런지 말하지 않습니다. – Rayne

+3

그는 왜 그런 말을 할 필요가 없으며 소원이 무의미하다는 것을 어떻게 알지 못합니다. –

1

hackage의 "async"패키지에는 race :: IO a -> IO b -> IO (Either a b) 도우미 기능이 있습니다.

두 개의 IO 작업을 동시에 실행하므로 하나는 getLine 일 수 있고 다른 하나는 MVar 또는 그 밖의 모든 차단 작업을 수행 할 수 있습니다. Either을 반환합니다. 어느 것이 먼저 반환되었는지 (다른 하나는 취소됨)를 나타냅니다.

https://hackage.haskell.org/package/async-2.0.2/docs/Control-Concurrent-Async.html#v:race

+1

IMO 정답입니다.수락 된 대답은 지나치게 복잡하며이 대답은 수락 응답에 필요하다고 말한 정리를 수행합니다. 'async' 대신'forkIO'를 사용해야 할 이유가 있습니다. –

관련 문제