2011-10-22 8 views
9

¿Hay alguna manera de aumentar un intervalo de tiempo, en función del cual el RTS decide que el hilo ha bloqueado indefinidamente en una transacción STM? Aquí está mi código:Haskell: hilo bloqueado indefinidamente en una transacción 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) 

forkManaged se asegura de que la cantidad de hilos que se ejecutan simultáneamente administrados no exceda maxThreadsCount. Funciona bien hasta una carga pesada. Bajo carga pesada, RTS arroja una excepción. Creo que bajo mucha carga, en la competencia concurrente de recursos, algunos de los hilos simplemente no tienen tiempo para acceder al contexto de STM. Entonces, creo que aumentar el intervalo de tiempo cuando RTS decide lanzar esta excepción puede resolver el problema.

+4

¿Estás seguro de que la decisión se toma con tiempos de espera? Pensé que usaba sus registros para decidir cuándo dos 'retry's estaban esperando el uno al otro. –

+0

@ Daniel: Daniel, actualicé la pregunta proporcionando mi código usando STM. Es por eso que creo que el problema con el tiempo de espera. –

+0

¿Es posible que 'fn' arroje una excepción y evite que el contador se incremente? –

Respuesta

7

Daniel Wagner tiene razón. La decisión no se toma con tiempos de espera. El código relevante en el rts está en Schedule.c

Consulte la función resurrectThreads para donde se produce la excepción. El comentario describe que esto solo se lanza a los hilos que se encuentran como basura después de GC. ezyang describe cómo funcionaba para MVARs: http://blog.ezyang.com/2011/07/blockedindefinitelyonmvar/

[mala especulación en relación con check retirada cuando he comprobado su fuente y se dio cuenta de que era sólo un guardia sencilla/reintentar y no lo que se describe en un documento anterior - ¡Uy! Ahora sospecho que Daniel Wagner también está en lo correcto aquí, y el problema es que el contador no se está incrementando.]

+0

Sclv, Daniel, gracias por su respuesta, ¡especialmente por los enlaces útiles a la implementación de rts de ghc! Revisaré mi código una vez más. –

Cuestiones relacionadas