为什么不睡觉工作?

为什么c_sleep在下面的代码中立即返回?

{-# 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 

注意:实际上,我想用C代码中的sleep来模拟函数func中的一些繁重计算,并在Haskell中调用该函数,但这也不起作用,可能出于同样的原因。


GHC的RTS似乎将信号用于自己的目的,这意味着在睡眠被这些信号之一中断之前不会很久。 我认为这也不是一个错误,运行时确实有自己的领域,可以这么说。 Haskellian的方法是使用threadDelay但对于C程序来说,访问它并不容易。

正确的方法是反复恢复睡眠,尽管来自其他信号的中断。 我建议使用nanosleep因为sleep只有几秒钟的精确度,并且信号似乎比这更频繁地发生。

#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;
}

所有并发原语总是有一个回拨语句,它们可能会阻塞的时间少于指定的时间 - 它们可能会虚假地返回。 这与语言无关,它是并发性的本质,所以如果你想等待指定的时间量,用任何语言你都需要构建一个循环来检查睡眠后的时钟。

链接地址: http://www.djcxy.com/p/43407.html

上一篇: Why doesn't sleep work?

下一篇: GHC version check in code