为什么睡眠不起作用?
Why doesn't sleep work?
为什么在下面的代码中 c_sleep
return 立即出现?
{-# 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 && ./睡眠
[1 of 1] 编译 Main ( Sleep.hs, Sleep.o )
连接睡眠...
29448.191603s
10
29448.20158s
29458.211402s
$ ghc --version
The Glorious Glasgow Haskell 编译系统,版本 7.8.3
$ cabal --version
cabal 安装版本 1.20.0.3
使用 1.20.0.0 版的 Cabal 库
注意:其实我想在C代码中使用sleep
来模拟函数func
中的一些繁重计算并调用that 在 Haskell 中起作用,但它也不起作用,可能出于相同的原因。
GHC 的 RTS appears to use signals for its own purposes, which means it won't be long before a sleep gets interrupted by one of these signals. I don't think it's a bug either, the runtime does 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;
}
所有并发原语总是有一个回扣声明,它们可能阻塞的时间少于指定的时间 - 它们可能 return 虚假。这与语言无关,这是并发的本质,所以如果你想准确地等待指定的时间量,在任何语言中你都需要在睡眠后构造一个循环检查时钟。
为什么在下面的代码中 c_sleep
return 立即出现?
{-# 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 && ./睡眠 [1 of 1] 编译 Main ( Sleep.hs, Sleep.o ) 连接睡眠... 29448.191603s 10 29448.20158s 29458.211402s $ ghc --version The Glorious Glasgow Haskell 编译系统,版本 7.8.3 $ cabal --version cabal 安装版本 1.20.0.3 使用 1.20.0.0 版的 Cabal 库
注意:其实我想在C代码中使用sleep
来模拟函数func
中的一些繁重计算并调用that 在 Haskell 中起作用,但它也不起作用,可能出于相同的原因。
GHC 的 RTS appears to use signals for its own purposes, which means it won't be long before a sleep gets interrupted by one of these signals. I don't think it's a bug either, the runtime does 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;
}
所有并发原语总是有一个回扣声明,它们可能阻塞的时间少于指定的时间 - 它们可能 return 虚假。这与语言无关,这是并发的本质,所以如果你想准确地等待指定的时间量,在任何语言中你都需要在睡眠后构造一个循环检查时钟。