packages feed

haskus-binary-1.6: src/lib/Haskus/Memory/Allocator/Malloc.hs

{-# LANGUAGE UnliftedFFITypes #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}

-- | Malloc memory allocator
module Haskus.Memory.Allocator.Malloc
   ( newBuffer
   , newFinalizedBuffer
   , freeBuffer
   )
where

import GHC.Exts
import Foreign.Ptr (nullPtr)
import Haskus.Utils.Monad
import qualified Haskus.Memory.Buffer as B
import Haskus.Memory.Buffer (Buffer)

foreign import ccall unsafe "malloc"  malloc_ :: Word -> IO (Ptr ())
foreign import ccall unsafe "free"    free    :: Addr# -> IO ()

-- | Allocate a new Buffer using system ``malloc``
newBuffer :: Word -> IO (Maybe Buffer)
newBuffer sz@(W# sz#) = do
   p <- malloc_ sz
   case p == nullPtr of
      True  -> return Nothing
      False -> case p of
         Ptr addr -> pure (Just (B.attachExternalBuffer addr sz#))

-- | Allocate a new finalized buffer using system ``malloc`` and finalized with
-- ``free``.
newFinalizedBuffer :: Word -> IO (Maybe Buffer)
newFinalizedBuffer sz@(W# sz#) = do
   p <- malloc_ sz
   case p == nullPtr of
      True  -> return Nothing
      False -> case p of
         Ptr addr -> do
          b  <- B.attachFinalizedBuffer addr sz#
          B.addFinalizer b (free addr)
          pure (Just b)
   
-- | Free a malloc-ed Buffer
freeBuffer :: Buffer -> IO ()
{-# INLINABLE freeBuffer #-}
freeBuffer = \case
  B.InBuffer {}        -> error "freeBuffer: unexpected managed buffer"
  B.OutBuffer addr _ _ -> liftIO (free addr)