embla (empty) → 0.1
raw patch · 5 files changed
+140/−0 lines, 5 filesdep +basedep +chronos
Dependencies added: base, chronos
Files
- CHANGELOG.md +12/−0
- LICENSE +29/−0
- README.md +6/−0
- embla.cabal +53/−0
- src/Embla.hs +40/−0
+ 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++[](https://hackage.haskell.org/package/embla)+[](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