packages feed

fixed-timestep 0.1.0.0 → 0.2.0.0

raw patch · 6 files changed

+140/−95 lines, 6 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Time.Flick: secnd :: Flicks
- TimeStep: Boottime :: Clock
- TimeStep: Monotonic :: Clock
- TimeStep: MonotonicCoarse :: Clock
- TimeStep: MonotonicRaw :: Clock
- TimeStep: ProcessCPUTime :: Clock
- TimeStep: Realtime :: Clock
- TimeStep: RealtimeCoarse :: Clock
- TimeStep: ThreadCPUTime :: Clock
- TimeStep: asyncRepeatedly :: Rational -> IO a -> IO (Async void)
- TimeStep: asyncRepeatedly' :: Rational -> Clock -> IO a -> IO (Async void)
- TimeStep: data Clock
- TimeStep: data TimeStepClock
- TimeStep: instance GHC.Classes.Eq TimeStep.TimeStepClock
- TimeStep: loopUsing :: TimeStepClock -> IO a -> IO void
- TimeStep: newClock :: Rational -> Clock -> IO TimeStepClock
- TimeStep: repeatedly :: Rational -> IO a -> IO void
- TimeStep: repeatedly' :: Rational -> Clock -> IO a -> IO void
+ Time.Flick: oneSecond :: Flicks
+ Time.Repeatedly: Boottime :: Clock
+ Time.Repeatedly: Monotonic :: Clock
+ Time.Repeatedly: MonotonicCoarse :: Clock
+ Time.Repeatedly: MonotonicRaw :: Clock
+ Time.Repeatedly: ProcessCPUTime :: Clock
+ Time.Repeatedly: Realtime :: Clock
+ Time.Repeatedly: RealtimeCoarse :: Clock
+ Time.Repeatedly: ThreadCPUTime :: Clock
+ Time.Repeatedly: asyncRepeatedly :: Rational -> IO a -> IO (Async void)
+ Time.Repeatedly: asyncRepeatedly' :: Rational -> Clock -> IO a -> IO (Async void)
+ Time.Repeatedly: data Clock
+ Time.Repeatedly: data TimeStepClock
+ Time.Repeatedly: instance GHC.Classes.Eq Time.Repeatedly.TimeStepClock
+ Time.Repeatedly: loopUsing :: TimeStepClock -> IO a -> IO void
+ Time.Repeatedly: newClock :: Rational -> Clock -> IO TimeStepClock
+ Time.Repeatedly: repeatedly :: Rational -> IO a -> IO void
+ Time.Repeatedly: repeatedly' :: Rational -> Clock -> IO a -> IO void

Files

CHANGELOG.md view
@@ -1,5 +1,13 @@ # Revision history for fixed-timestep
 
-## 0.1.0.0 -- YYYY-mm-dd
+## 0.2.0.0 -- 2019-03-25
 
-* First version. Released on an unsuspecting world.
+* Rename `Time.Flick.secnd` to `Time.Flick.oneSecond`
+  * This pleases the Orthography Gods.
+* Move `TimeStep` module to `Time.Repeatedly`
+  * It makes more sense to keep all modules under one namespace.
+
+## 0.1.0.0 -- 2019-03-13
+
+* Released. Basic timekeeping in units of flicks, and
+  functions for repeatedly running actions.
+ README.md view
@@ -0,0 +1,38 @@+# fixed-timestep
+
+Pure Haskell library to run an action repeatedly, a specific amount of times per second.
+
+Internal timekeeping is done in [flicks](https://github.com/OculusVR/Flicks#README), a
+unit of time equal to precisely 1/705600000 of a second.
+
+Basic usage:
+
+```haskell
+λ> import Data.Time.Clock
+λ> import Time.Repeatedly
+λ> repeatedly 1 (print =<< getCurrentTime)
+2019-03-13 21:14:36.826248 UTC
+2019-03-13 21:14:37.8282926 UTC
+2019-03-13 21:14:38.8327692 UTC
+2019-03-13 21:14:39.8359494 UTC
+2019-03-13 21:14:40.8374415 UTC
+^CInterrupted.
+```
+
+Using `async`, you can repeat multiple actions independently, and also cancel them:
+
+```haskell
+λ> import Data.Time.Clock
+λ> import Control.Concurrent.Asyncx
+λ> import Time.Repeatedly
+λ> printer <- asyncRepeatedly 1 (print =<< getCurrentTime)
+2019-03-13 21:21:27.5228834 UTC
+2019-03-13 21:21:28.523892 UTC
+2019-03-13 21:21:29.5283634 UTC
+2019-03-13 21:21:30.5313565 UTC
+2019-03-13 21:21:31.535904 UTC
+2019-03-13 21:21:32.5373828 UTC
+2019-03-13 21:21:33.5393834 UTC
+2019-03-13 21:21:34.5408811 UTC
+cancel printer
+```
fixed-timestep.cabal view
@@ -4,7 +4,7 @@ -- http://haskell.org/cabal/users-guide/
 
 name:                fixed-timestep
-version:             0.1.0.0
+version:             0.2.0.0
 synopsis:            Pure Haskell library to repeat an action at a specific frequency.
 description:         Repeat IO actions at a specific frequency, using
                      flicks (1/705600000 of a second) for timekeeping.
@@ -17,7 +17,7 @@ maintainer:          Nicolas Stamm <nstamm@gmx.de>
 copyright:           2019 Nicolas Stamm (Solonarv)
 category:            Time
-extra-source-files:  CHANGELOG.md
+extra-source-files:  CHANGELOG.md, README.md
 
 source-repository head
   type:     git
@@ -25,7 +25,7 @@ 
 library
   exposed-modules:     Time.Flick
-                     , TimeStep
+                     , Time.Repeatedly
   -- other-modules:
   other-extensions:    DerivingStrategies GeneralizedNewtypeDeriving NamedFieldPuns
                        ScopedTypeVariables
lib/Time/Flick.hs view
@@ -4,11 +4,10 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeApplications #-}
 module Time.Flick
   ( -- * The Flicks data type
     Flicks(..)
-  , flicksPerSecond, secnd
+  , flicksPerSecond, oneSecond
     -- * Conversions
   , approxFlicks
   , periodForFreq
@@ -34,13 +33,13 @@ newtype Flicks = Flicks { unFlicks :: Int64 }
   deriving newtype (Eq, Ord, Show, Num, Enum, Integral, Real)
 
--- | How many flicks are in a second. Precisely 705600000.
+-- | How many flicks are in a second: precisely 705600000.
 flicksPerSecond :: Num a => a
 flicksPerSecond = 705600000
 
 -- | One second in flicks.
-secnd :: Flicks
-secnd = flicksPerSecond
+oneSecond :: Flicks
+oneSecond = flicksPerSecond
 
 -- | Convert a number of seconds into flicks, rounding towards zero.
 approxFlicks :: Rational -> Flicks
@@ -62,7 +61,7 @@ flicksToFixed :: forall r. HasResolution r => Flicks -> Fixed r
 flicksToFixed (Flicks t) = MkFixed val
   where
-    val = fromIntegral t * resolution (Proxy @r) `quot` flicksPerSecond
+    val = fromIntegral t * resolution (Proxy :: Proxy r) `quot` flicksPerSecond
 
 -- | Convert flicks into @'DiffTime'@
 flicksToDiffTime :: Flicks -> DiffTime
+ lib/Time/Repeatedly.hs view
@@ -0,0 +1,84 @@+-- | Utilities for repeatedly running @'IO'@ actions
+-- at a specific frequency.
+module Time.Repeatedly
+  ( -- * Repeating actions
+    repeatedly
+  , repeatedly'
+    -- * Repeating actions in another thread
+  , asyncRepeatedly
+  , asyncRepeatedly'
+    -- * Implementation details
+  , TimeStepClock
+  , newClock
+  , loopUsing
+    -- * Reexports (timekeeping)
+  , module Time.Flick
+  , Clock(..)
+  ) where
+
+import Control.Concurrent
+import Control.Monad
+import Data.Bifunctor
+import Data.Fixed (divMod')
+import Data.Int
+import Data.IORef
+import Data.Ratio
+
+import Control.Concurrent.Async
+import System.Clock
+
+import Time.Flick
+
+-- | Internal state of the stepper. Created using @'newClock'@.
+data TimeStepClock = TimeStepClock
+  { tscLastTick :: IORef Flicks
+  , tscDesiredTickTime :: Flicks
+  , tscClockType :: Clock
+  } deriving Eq
+
+-- | Run an action repeatedly at the specified frequency.
+-- Uses the 'Monotonic' clock for timing.
+repeatedly :: Rational -> IO a -> IO void
+repeatedly freq = repeatedly' freq Monotonic
+
+-- | Run an action repeatedly at the specified frequency,
+-- using the given clock type.
+repeatedly' :: Rational -> Clock -> IO a -> IO void
+repeatedly' freq clockTy act = do
+  clock <- newClock freq clockTy
+  loopUsing clock act
+
+-- | Run an action repeatedly at the specified frequency, in a separate thread.
+-- Uses the 'Monotonic' clock for timing.
+asyncRepeatedly :: Rational -> IO a -> IO (Async void)
+asyncRepeatedly freq = asyncRepeatedly' freq Monotonic
+
+-- | Run an action repeatedly at the specified frequency, in a separate thread,
+-- using the given clock type.
+asyncRepeatedly' :: Rational -> Clock -> IO a -> IO (Async void)
+asyncRepeatedly' freq clockTy act = do
+  clock <- newClock freq clockTy
+  async (loopUsing clock act)
+
+-- | Initialise a new clock structure for the given frequency and using
+-- the given clock type.
+newClock :: Rational -> Clock -> IO TimeStepClock
+newClock freq clockTy = do
+  leftoverRef <- newIORef =<< flicksNow clockTy
+  pure TimeStepClock
+    { tscLastTick = leftoverRef
+    , tscDesiredTickTime = periodForFreq freq
+    , tscClockType = clockTy
+    }
+
+-- | Repeat the given action using the information in the clock structure.
+loopUsing :: TimeStepClock -> IO a -> IO void
+loopUsing (TimeStepClock lastTickRef tickTime clockTy) act = forever $ do
+  now <- flicksNow clockTy
+  lastTick <- readIORef lastTickRef
+  let elapsed = now - lastTick
+      (ticksToRun, leftover) = elapsed `divMod` tickTime
+  replicateM_ (fromIntegral ticksToRun) act
+  writeIORef lastTickRef now
+  now' <- flicksNow clockTy
+  threadDelayFlicks (tickTime + now - now')
− lib/TimeStep.hs
@@ -1,84 +0,0 @@--- | Utilities for repeatedly running @'IO'@ actions
--- at a specific frequency.
-module TimeStep
-  ( -- * Repeating actions
-    repeatedly
-  , repeatedly'
-    -- * Repeating actions in another thread
-  , asyncRepeatedly
-  , asyncRepeatedly'
-    -- * Implementation details
-  , TimeStepClock
-  , newClock
-  , loopUsing
-    -- * Reexports (timekeeping)
-  , module Time.Flick
-  , Clock(..)
-  ) where
-
-import Control.Concurrent
-import Control.Monad
-import Data.Bifunctor
-import Data.Fixed (divMod')
-import Data.Int
-import Data.IORef
-import Data.Ratio
-
-import Control.Concurrent.Async
-import System.Clock
-
-import Time.Flick
-
--- | Internal state of the stepper. Created using @'newClock'@.
-data TimeStepClock = TimeStepClock
-  { tscLastTick :: IORef Flicks
-  , tscDesiredTickTime :: Flicks
-  , tscClockType :: Clock
-  } deriving Eq
-
--- | Run an action repeatedly at the specified frequency.
--- Uses the 'Monotonic' clock for timing.
-repeatedly :: Rational -> IO a -> IO void
-repeatedly freq = repeatedly' freq Monotonic
-
--- | Run an action repeatedly at the specified frequency,
--- using the given clock type.
-repeatedly' :: Rational -> Clock -> IO a -> IO void
-repeatedly' freq clockTy act = do
-  clock <- newClock freq clockTy
-  loopUsing clock act
-
--- | Run an action repeatedly at the specified frequency, in a separate thread.
--- Uses the 'Monotonic' clock for timing.
-asyncRepeatedly :: Rational -> IO a -> IO (Async void)
-asyncRepeatedly freq = asyncRepeatedly' freq Monotonic
-
--- | Run an action repeatedly at the specified frequency, in a separate thread,
--- using the given clock type.
-asyncRepeatedly' :: Rational -> Clock -> IO a -> IO (Async void)
-asyncRepeatedly' freq clockTy act = do
-  clock <- newClock freq clockTy
-  async (loopUsing clock act)
-
--- | Initialise a new clock structure for the given frequency and using
--- the given clock type.
-newClock :: Rational -> Clock -> IO TimeStepClock
-newClock freq clockTy = do
-  leftoverRef <- newIORef =<< flicksNow clockTy
-  pure TimeStepClock
-    { tscLastTick = leftoverRef
-    , tscDesiredTickTime = periodForFreq freq
-    , tscClockType = clockTy
-    }
-
--- | Repeat the given action using the information in the clock structure.
-loopUsing :: TimeStepClock -> IO a -> IO void
-loopUsing (TimeStepClock lastTickRef tickTime clockTy) act = forever $ do
-  now <- flicksNow clockTy
-  lastTick <- readIORef lastTickRef
-  let elapsed = now - lastTick
-      (ticksToRun, leftover) = elapsed `divMod` tickTime
-  replicateM_ (fromIntegral ticksToRun) act
-  writeIORef lastTickRef now
-  now' <- flicksNow clockTy
-  threadDelayFlicks (tickTime + now - now')