Why doesn't sleep work?
Why does c_sleep
return immediately in the following code?
{-# 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
Note: Actually, I would like to use sleep
in C code to simulate some heavy computation in a function func
and call that function in Haskell, but that doesn't work either, probably for the same reasons.
GHC's 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, so to speak. The Haskellian approach would be to use threadDelay
but it's not easy for a C program to access that without some trickery.
The proper way is to repeatedly resume the sleep despite interruptions from other signals. I recommend using nanosleep
since sleep
only has a precision of seconds and the signals appear to occur much more frequently than that.
#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;
}
All concurrency primitives always have a clawback statement that they may block for less time than specified - they may return spuriously. This is nothing to do with the language, it is the nature of concurrency, so if you want to wait for exactly the specified amount of time, in any language you need to construct a loop checking the clock after the sleep.
链接地址: http://www.djcxy.com/p/43408.html上一篇: 真实世界Haskell,第5章,SimpleJSON编译错误
下一篇: 为什么不睡觉工作?