2011-10-22 3 views
9

STM 트랜잭션에서 스레드가 무기한 차단 된 것으로 RTS가 결정한 시간 간격을 늘릴 수있는 방법이 있습니까?Haskell : STM 트랜잭션에서 무기한 차단 된 스레드

import Control.Concurrent (ThreadId) 
import Control.Concurrent.MVar (MVar,newMVar,withMVar) 
import Control.Concurrent.STM 
import qualified Control.Concurrent.ThreadManager as TM 

data ThreadManager = ThreadManager { tmCounter::TVar Int, tmTM::MVar TM.ThreadManager } 

data Settings = Settings { 
    maxThreadsCount::Int } 

createThreadManager :: Settings -> IO ThreadManager 
createThreadManager s = do 
    counter <- atomically $ newTVar (maxThreadsCount s) 
    tm <- TM.make >>= newMVar 
    return $ ThreadManager counter tm 

forkManaged :: ThreadManager -> IO() -> IO ThreadId 
forkManaged tm fn = do 
    atomically $ do 
     counter <- readTVar $ tmCounter tm 
     check $ counter > 0 
     writeTVar (tmCounter tm) (counter - 1) 
    withMVar (tmTM tm) $ \thrdmgr -> TM.fork thrdmgr $ do 
     fn 
     atomically $ do 
      counter <- readTVar $ tmCounter tm 
      writeTVar (tmCounter tm) (counter + 1) 

확실 동시에 실행하는 관리 스레드의 양이 maxThreadsCount 초과하지 않도록한다 forkManaged : 다음은 내 코드입니다. 그것은 무거운 하중까지 잘 작동합니다. 로드가 많은 경우 RTS에서 예외가 발생합니다. 부하가 심한 상황에서 리소스에 대한 동시 경쟁이 치열한 상황에서 스레드 중 일부는 STM 컨텍스트에 액세스 할 시간이 없다고 생각합니다. 그래서 저는 RTS가이 예외를 던지기로 결정할 때 시간 간격을 늘리는 것이 문제를 해결할 것이라고 생각합니다.

+4

시간 초과를 결정 했습니까? 로그를 사용하여 두 개의 '재시도'가 서로 기다리고있을 때를 결정했다고 생각했습니다. –

+0

@ Daniel : Daniel, STM을 사용하여 코드를 제공하여 질문을 업데이트했습니다. 이것이 내가 타임 아웃 문제를 생각하는 이유입니다. –

+0

'fn'이 예외를 던지고 카운터가 증가하지 않도록 할 수 있습니까? –

답변

7

다니엘 바그너입니다. 시간 초과에 대한 결정은 내리지 않습니다. rts의 관련 코드는 다음과 같습니다. Schedule.c

예외가 발생하는 곳의 resurrectThreads 함수를 참조하십시오. 주석은 GC 다음에 쓰레기로 발견 된 스레드에만 던져 질 것이라고 설명합니다. ezyang은 mvars에 대해 이것이 어떻게 작동하는지에 대해 설명했습니다. [출처를 확인한 후 이전의 문서에 설명 된 내용이 아닌 간단한 가드/재시도임을 깨달았습니다. 이제 Daniel Wagner가 올바른지 의심해 봅니다. 문제는 카운터가 증가하지 않는 것입니다.]

+0

Sclv, Daniel, 특히 ghc의 rts 구현에 유용한 링크에 대해 감사드립니다. 나는 나의 코드를 다시 한번 점검 할 것이다. –