{-# OPTIONS_HADDOCK not-home #-}

module Database.LSMTree.Internal.UniqCounter (
  UniqCounter (..),
  newUniqCounter,
  incrUniqCounter,
  Unique,
  uniqueToInt,
  uniqueToRunNumber,
  uniqueToTableId,
  uniqueToCursorId,
) where

import           Control.Monad.Primitive (PrimMonad, PrimState)
import           Data.Primitive.PrimVar as P
import           Database.LSMTree.Internal.RunNumber

-- | A unique value derived from a 'UniqCounter'.
newtype Unique = Unique Int

-- | Use specialised versions like 'uniqueToRunNumber' where possible.
uniqueToInt :: Unique -> Int
uniqueToInt :: Unique -> Int
uniqueToInt (Unique Int
n) = Int
n

uniqueToRunNumber :: Unique -> RunNumber
uniqueToRunNumber :: Unique -> RunNumber
uniqueToRunNumber (Unique Int
n) = Int -> RunNumber
RunNumber Int
n

uniqueToTableId :: Unique -> TableId
uniqueToTableId :: Unique -> TableId
uniqueToTableId (Unique Int
n) = Int -> TableId
TableId Int
n

uniqueToCursorId :: Unique -> CursorId
uniqueToCursorId :: Unique -> CursorId
uniqueToCursorId (Unique Int
n) = Int -> CursorId
CursorId Int
n

-- | An atomic counter for producing 'Unique' values.
--
newtype UniqCounter m = UniqCounter (PrimVar (PrimState m) Int)

{-# INLINE newUniqCounter #-}
newUniqCounter :: PrimMonad m => Int -> m (UniqCounter m)
newUniqCounter :: forall (m :: * -> *). PrimMonad m => Int -> m (UniqCounter m)
newUniqCounter = (PrimVar (PrimState m) Int -> UniqCounter m)
-> m (PrimVar (PrimState m) Int) -> m (UniqCounter m)
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap PrimVar (PrimState m) Int -> UniqCounter m
forall (m :: * -> *). PrimVar (PrimState m) Int -> UniqCounter m
UniqCounter (m (PrimVar (PrimState m) Int) -> m (UniqCounter m))
-> (Int -> m (PrimVar (PrimState m) Int))
-> Int
-> m (UniqCounter m)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> m (PrimVar (PrimState m) Int)
forall (m :: * -> *) a.
(PrimMonad m, Prim a) =>
a -> m (PrimVar (PrimState m) a)
P.newPrimVar

{-# INLINE incrUniqCounter #-}
-- | Atomically, return the current state of the counter, and increment the
-- counter.
incrUniqCounter :: PrimMonad m => UniqCounter m -> m Unique
incrUniqCounter :: forall (m :: * -> *). PrimMonad m => UniqCounter m -> m Unique
incrUniqCounter (UniqCounter PrimVar (PrimState m) Int
uniqVar) =
  Int -> Unique
Unique (Int -> Unique) -> m Int -> m Unique
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PrimVar (PrimState m) Int -> Int -> m Int
forall (m :: * -> *).
PrimMonad m =>
PrimVar (PrimState m) Int -> Int -> m Int
P.fetchAddInt PrimVar (PrimState m) Int
uniqVar Int
1