lsm-tree-1.0.0.0: src-core/Database/LSMTree/Internal/StrictArray.hs
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE UnboxedTuples #-}
{-# OPTIONS_HADDOCK not-home #-}
module Database.LSMTree.Internal.StrictArray (
StrictArray,
vectorToStrictArray,
indexStrictArray,
sizeofStrictArray,
) where
import Data.Elevator (Strict (Strict))
import qualified Data.Vector as V
import GHC.Exts ((+#))
import qualified GHC.Exts as GHC
import GHC.ST (ST (ST), runST)
import Unsafe.Coerce (unsafeCoerce)
data StrictArray a = StrictArray !(GHC.Array# (Strict a))
vectorToStrictArray :: forall a. V.Vector a -> StrictArray a
vectorToStrictArray v =
runST $ ST $ \s0 ->
case GHC.newArray# (case V.length v of GHC.I# l# -> l#)
(Strict (unsafeCoerce ())) s0 of
-- initialise with (), will be overwritten.
(# s1, a# #) ->
case go a# 0# s1 of
s2 -> case GHC.unsafeFreezeArray# a# s2 of
(# s3, a'# #) -> (# s3, StrictArray a'# #)
where
go :: forall s.
GHC.MutableArray# s (Strict a)
-> GHC.Int#
-> GHC.State# s
-> GHC.State# s
go a# i# s
| GHC.I# i# < V.length v
= let x = V.unsafeIndex v (GHC.I# i#)
-- We have to use seq# here to force the array element to WHNF
-- before putting it into the strict array. This should not be
-- necessary. https://github.com/sgraf812/data-elevator/issues/4
in case GHC.seq# x s of
(# s', x' #) ->
case GHC.writeArray# a# i# (Strict x') s' of
s'' -> go a# (i# +# 1#) s''
| otherwise = s
{-# INLINE indexStrictArray #-}
indexStrictArray :: StrictArray a -> Int -> a
indexStrictArray (StrictArray a#) (GHC.I# i#) =
case GHC.indexArray# a# i# of
(# Strict x #) -> x
{-# INLINE sizeofStrictArray #-}
sizeofStrictArray :: StrictArray a -> Int
sizeofStrictArray (StrictArray a#) =
GHC.I# (GHC.sizeofArray# a#)