-- | Thread operations.
module Sound.Osc.Time.Thread where

import Control.Concurrent {- base -}
import Control.Monad {- base -}

import Sound.Osc.Time {- hosc -}

-- | The 'pauseThread' limit (in seconds).
--   Values larger than this require a different thread delay mechanism, see 'sleepThread'.
--   The value is the number of microseconds in @maxBound::Int@.
pauseThreadLimit :: Fractional n => n
pauseThreadLimit :: forall n. Fractional n => n
pauseThreadLimit = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
maxBound::Int) forall a. Fractional a => a -> a -> a
/ n
1e6

-- | Pause current thread for the indicated duration (in seconds), see 'pauseThreadLimit'.
pauseThreadFor :: RealFrac n => n -> IO ()
pauseThreadFor :: forall n. RealFrac n => n -> IO ()
pauseThreadFor n
n = forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (n
n forall a. Ord a => a -> a -> Bool
> n
0) (Int -> IO ()
threadDelay (forall a b. (RealFrac a, Integral b) => a -> b
floor (n
n forall a. Num a => a -> a -> a
* n
1e6)))

-- | Pause current thread until the given time, see 'pauseThreadLimit'.
pauseThreadUntilTime :: RealFrac n => n -> IO ()
pauseThreadUntilTime :: forall n. RealFrac n => n -> IO ()
pauseThreadUntilTime n
t = forall n. RealFrac n => n -> IO ()
pauseThreadFor forall b c a. (b -> c) -> (a -> b) -> a -> c
. (n
t forall a. Num a => a -> a -> a
-) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Real a, Fractional b) => a -> b
realToFrac forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO NtpReal
currentTime

-- | Sleep current thread for the indicated duration (in seconds).
--   Divides long sleeps into parts smaller than 'pauseThreadLimit'.
sleepThreadFor :: RealFrac n => n -> IO ()
sleepThreadFor :: forall n. RealFrac n => n -> IO ()
sleepThreadFor n
n =
    if n
n forall a. Ord a => a -> a -> Bool
>= forall n. Fractional n => n
pauseThreadLimit
    then let n' :: n
n' = forall n. Fractional n => n
pauseThreadLimit forall a. Num a => a -> a -> a
- n
1
         in forall n. RealFrac n => n -> IO ()
pauseThreadFor n
n' forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall n. RealFrac n => n -> IO ()
sleepThreadFor (n
n forall a. Num a => a -> a -> a
- n
n')
    else forall n. RealFrac n => n -> IO ()
pauseThreadFor n
n

-- | Sleep current thread until the given time.
--   Divides long sleeps into parts smaller than 'pauseThreadLimit'.
sleepThreadUntilTime :: RealFrac n => n -> IO ()
sleepThreadUntilTime :: forall n. RealFrac n => n -> IO ()
sleepThreadUntilTime n
t = forall n. RealFrac n => n -> IO ()
sleepThreadFor forall b c a. (b -> c) -> (a -> b) -> a -> c
. (n
t forall a. Num a => a -> a -> a
-) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Real a, Fractional b) => a -> b
realToFrac forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO NtpReal
currentTime