haskell ghc ffi

haskell - ¿Por qué no funciona el sueño?



ghc ffi (2)

El RTS de GHC parece utilizar señales para sus own purposes , lo que significa que no pasará mucho tiempo antes de que una de estas señales interrumpa el sueño. Tampoco creo que sea un error, el tiempo de ejecución viene con su propio territorio , por así decirlo. El enfoque haskelliano sería usar threadDelay pero no es fácil para un programa C acceder a eso sin algunos trucos.

La forma correcta es reanudar repetidamente el sueño a pesar de las interrupciones de otras señales. Recomiendo usar nanosleep ya que el sleep solo tiene una precisión de segundos y las señales parecen ocurrir con mucha más frecuencia que eso.

#include <errno.h> #include <time.h> /* same as ''sleep'' except it doesn''t get interrupted by signals */ int keep_sleeping(unsigned long sec) { struct timespec rem, req = { (time_t) sec, 0 }; /* warning: may overflow */ while ((rem.tv_sec || rem.tv_nsec) && nanosleep(&req, &rem)) { if (errno != EINTR) /* this check is probably unnecessary */ return -1; req = rem; } return 0; }

¿Por qué c_sleep regresa inmediatamente en el siguiente código?

{-# LANGUAGE ForeignFunctionInterface #-} import Foreign.C.Types import Data.Time.Clock import Control.Concurrent foreign import ccall unsafe "unistd.h sleep" c_sleep :: CUInt -> IO CUInt main :: IO () main = do getCurrentTime >>= print . utctDayTime c_sleep 10 >>= print -- this doesn''t sleep getCurrentTime >>= print . utctDayTime threadDelay $ 10 * 1000 * 1000 -- this does sleep getCurrentTime >>= print . utctDayTime

$ ghc --make Sleep.hs && ./Sleep [1 of 1] Compiling Main ( Sleep.hs, Sleep.o ) Linking Sleep ... 29448.191603s 10 29448.20158s 29458.211402s $ ghc --version The Glorious Glasgow Haskell Compilation System, version 7.8.3 $ cabal --version cabal-install version 1.20.0.3 using version 1.20.0.0 of the Cabal library

Nota: En realidad, me gustaría usar el código de sleep en código C para simular algunos cálculos pesados ​​en una función de func y llamar a esa función en Haskell, pero eso tampoco funciona, probablemente por las mismas razones.


Todas las primitivas de concurrencia siempre tienen una declaración de recuperación que pueden bloquear por menos tiempo que el especificado; pueden regresar falsamente. Esto no tiene nada que ver con el idioma, es la naturaleza de la concurrencia, por lo que si desea esperar exactamente la cantidad de tiempo especificada, en cualquier idioma que necesite construir un bucle que compruebe el reloj después de la suspensión.