{-# LANGUAGE CPP #-} {-# LANGUAGE ForeignFunctionInterface #-} {-| This module makes the operations exported by @System.Posix.Unistd@ available on all platforms. On POSIX systems it re-exports operations from @System.Posix.Unistd@, on other platforms it emulates the operations as far as possible. -} module System.PosixCompat.Unistd ( -- * System environment SystemID(..) , getSystemID -- * Sleeping , sleep , usleep , nanosleep ) where #ifndef mingw32_HOST_OS import System.Posix.Unistd #else import Control.Concurrent (threadDelay) import Foreign.C.String (CString, peekCString) import Foreign.C.Types (CInt(..), CSize(..)) import Foreign.Marshal.Array (allocaArray) data SystemID = SystemID { systemName :: String , nodeName :: String , release :: String , version :: String , machine :: String } deriving (Eq, Read, Show) getSystemID :: IO SystemID getSystemID = do let bufSize = 256 let call f = allocaArray bufSize $ \buf -> do ok <- f buf (fromIntegral bufSize) if ok == 1 then peekCString buf else return "" display <- call c_os_display_string vers <- call c_os_version_string arch <- call c_os_arch_string node <- call c_os_node_name return SystemID { systemName = "Windows" , nodeName = node , release = display , version = vers , machine = arch } -- | Sleep for the specified duration (in seconds). Returns the time -- remaining (if the sleep was interrupted by a signal, for example). -- -- On non-Unix systems, this is implemented in terms of -- 'Control.Concurrent.threadDelay'. -- -- GHC Note: the comment for 'usleep' also applies here. sleep :: Int -> IO Int sleep secs = threadDelay (secs * 1000000) >> return 0 -- | Sleep for the specified duration (in microseconds). -- -- On non-Unix systems, this is implemented in terms of -- 'Control.Concurrent.threadDelay'. -- -- GHC Note: 'Control.Concurrent.threadDelay' is a better -- choice. Without the @-threaded@ option, 'usleep' will block all other -- user threads. Even with the @-threaded@ option, 'usleep' requires a -- full OS thread to itself. 'Control.Concurrent.threadDelay' has -- neither of these shortcomings. usleep :: Int -> IO () usleep = threadDelay -- | Sleep for the specified duration (in nanoseconds). -- -- On non-Unix systems, this is implemented in terms of -- 'Control.Concurrent.threadDelay'. nanosleep :: Integer -> IO () nanosleep nsecs = threadDelay (round (fromIntegral nsecs / 1000 :: Double)) foreign import ccall "unixcompat_os_display_string" c_os_display_string :: CString -> CSize -> IO CInt foreign import ccall "unixcompat_os_version_string" c_os_version_string :: CString -> CSize -> IO CInt foreign import ccall "unixcompat_os_arch_string" c_os_arch_string :: CString -> CSize -> IO CInt foreign import ccall "unixcompat_os_node_name" c_os_node_name :: CString -> CSize -> IO CInt #endif