为什么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中的功能,但这也不起作用,可能是出于同样的原因。
答案 0 :(得分:12)
GHC RTS appears to use signals own purposes,这意味着在睡眠被其中一个信号中断之前不久。我也不认为这是一个错误,运行时确实come with its own territory,可以这么说。 Haskellian的方法是使用threadDelay
,但如果没有一些技巧,C程序就不容易访问它。
尽管其他信号中断,proper way仍会重复恢复睡眠状态。我建议使用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;
}
答案 1 :(得分:1)
所有并发原语总是有一个clawback语句,它们可能阻塞的时间比指定的时间短 - 它们可能会伪造地返回。这与语言无关,它是并发的本质,所以如果你想等待指定的时间,你需要在任何语言中构建一个循环来检查睡眠后的时钟。