packages feed

pure-borrow-0.0.0.0: src/Control/Concurrent/DivideConquer/Utils/OnceChan/Linear/Unlifted.hs

{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE RoleAnnotations #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE UnliftedNewtypes #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# OPTIONS_GHC -Wno-name-shadowing #-}

module Control.Concurrent.DivideConquer.Utils.OnceChan.Linear.Unlifted (
  Sink#,
  Source#,
  new#,
  put#,
  take#,
) where

import Control.Monad.Borrow.Pure.Lifetime.Token
import Control.Monad.Borrow.Pure.Lifetime.Token.Unsafe (
  LinearOnly (..),
  LinearOnlyWitness (..),
 )
import GHC.Exts qualified as GHC
import Prelude.Linear
import Unsafe.Linear qualified as Unsafe

newtype Source# a = Source# (GHC.MVar# GHC.RealWorld a)

newtype Sink# a = Sink# (GHC.MVar# GHC.RealWorld a)

type role Source# representational

type role Sink# nominal

new# :: Linearly %1 -> (# Sink# a, Source# a #)
{-# NOINLINE new# #-}
new# = GHC.noinline $ Unsafe.toLinear $ \_ ->
  GHC.runRW# \s ->
    case GHC.newMVar# s of
      (# _, !v #) -> (# Sink# v, Source# v #)

take# :: Source# a %1 -> a
{-# INLINE take# #-}
take# = GHC.noinline $ Unsafe.toLinear \(Source# mv) ->
  GHC.runRW# \s ->
    case GHC.takeMVar# mv s of
      (# _, !a #) -> a

put# :: Sink# a %1 -> a %1 -> ()
{-# NOINLINE put# #-}
put# = GHC.noinline $ Unsafe.toLinear2 \(Sink# mv) !a ->
  GHC.runRW# \s ->
    case GHC.putMVar# mv a s of
      !_ -> ()

instance LinearOnly (Sink# a) where
  linearOnly = UnsafeLinearOnly

instance LinearOnly (Source# a) where
  linearOnly = UnsafeLinearOnly