-- | This module defines a type for mutable, integer-valued counters.
-- Counters are non-negative, monotonically increasing values and can
-- be used to track e.g. the number of requests served since program
-- start.  All operations on counters are thread-safe.
module System.Metrics.Counter
    (
      Counter
    , new
    , read
    , inc
    , add
    ) where

import qualified Data.Atomic as Atomic
import Data.Int (Int64)
import Prelude hiding (read)

-- | A mutable, integer-valued counter.
newtype Counter = C { Counter -> Atomic
unC :: Atomic.Atomic }

-- | Create a new, zero initialized, counter.
new :: IO Counter
new :: IO Counter
new = Atomic -> Counter
C (Atomic -> Counter) -> IO Atomic -> IO Counter
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` Int64 -> IO Atomic
Atomic.new Int64
0

-- | Get the current value of the counter.
read :: Counter -> IO Int64
read :: Counter -> IO Int64
read = Atomic -> IO Int64
Atomic.read (Atomic -> IO Int64) -> (Counter -> Atomic) -> Counter -> IO Int64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Counter -> Atomic
unC

-- | Increase the counter by one.
inc :: Counter -> IO ()
inc :: Counter -> IO ()
inc Counter
counter = Counter -> Int64 -> IO ()
add Counter
counter Int64
1

-- | Add the argument to the counter.
add :: Counter -> Int64 -> IO ()
add :: Counter -> Int64 -> IO ()
add Counter
counter = Atomic -> Int64 -> IO ()
Atomic.add (Counter -> Atomic
unC Counter
counter)