packages feed

embla (empty) → 0.1

raw patch · 5 files changed

+140/−0 lines, 5 filesdep +basedep +chronos

Dependencies added: base, chronos

Files

+ CHANGELOG.md view
@@ -0,0 +1,12 @@+# Changelog++`embla` uses [PVP Versioning][1].+The changelog is available [on GitHub][2].++0.0.0+=====++* Initially created.++[1]: https://pvp.haskell.org+[2]: https://github.com/chessai/embla/releases
+ LICENSE view
@@ -0,0 +1,29 @@+BSD 3-Clause License++Copyright (c) 2019, chessai+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice, this+   list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright notice,+   this list of conditions and the following disclaimer in the documentation+   and/or other materials provided with the distribution.++3. Neither the name of the copyright holder nor the names of its+   contributors may be used to endorse or promote products derived from+   this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,6 @@+# embla++[![Hackage](https://img.shields.io/hackage/v/embla.svg)](https://hackage.haskell.org/package/embla)+[![BSD3 license](https://img.shields.io/badge/license-BSD3-blue.svg)](LICENSE)++execute actions periodically while avoiding drift
+ embla.cabal view
@@ -0,0 +1,53 @@+cabal-version: 2.2+name:+  embla+version:+  0.1+synopsis:+  execute actions periodically while avoiding drift+description:+  This package is intended for use cases when 'cron'+  is overkill, but the importance of avoiding drift+  is still there. No care is taken w.r.t. GC times.+homepage:+  https://github.com/chessai/embla+bug-reports:+  https://github.com/chessai/embla/issues+license:+  BSD-3-Clause+license-file:+  LICENSE+author:+  chessai+maintainer:+  chessai <chessai1996@gmail.com>+copyright:+  © 2019 chessai+category:+  Utility+build-type:+  Simple+extra-doc-files:+    README.md+  , CHANGELOG.md+tested-with:+  GHC == 8.4.4, GHC == 8.6.3++library+  hs-source-dirs:+    src+  exposed-modules:+    Embla+  build-depends:+    , base >= 4.11 && < 4.14+    , chronos >= 1.0.4 && < 1.1+  ghc-options:+    -Wall+  default-language:+    Haskell2010++source-repository head+  type:+    git+  location:+    https://github.com/chessai/embla.git
+ src/Embla.hs view
@@ -0,0 +1,40 @@+-- | This package is intended for use cases when 'cron' is overkill,+--   but the importance of avoiding drift is still there. No care is+--   taken w.r.t. GC times.+module Embla+  ( embla+  ) where++import Control.Concurrent (threadDelay)+import GHC.Clock (getMonotonicTimeNSec)+import qualified Chronos as C++-- | Given an 'IO' action and an interval at which to perform it,+--   perform the 'IO' action repeatedly at every interval. This function+--   is useful when you have an 'IO' action that can take a significant/variable+--   amount of time, and you want to avoid drift.+--+--   /Note/: This function will not work as expected if the given 'IO' action+--   takes longer than the polling interval.+--+--   /Note/: No care is taken w.r.t. GC times.+embla :: Int -> IO a -> IO a+embla interval io = do+  anchor <- fmap fromIntegral getMonotonicTimeNSec+  let go = do+        _ <- io+        threadDelay =<< solveTime anchor interval+        go+  go+ +solveTime :: ()+  => Int+  -> Int+  -> IO Int+solveTime t0 p = do+  C.Time now' <- C.now+  let now = fromIntegral now'+  let p' = p * 1000000000+  let untilNextTime = ((div (now - t0) p') + 1) * p'+  let solved = div (t0 + untilNextTime - now) 1000+  pure solved