{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE ViewPatterns #-}
module ErsatzPointer
(
(:=>) ((:=>)),
establish,
establish_,
onDismantle,
(:=>?),
dereference,
dismantle,
Source (..),
PrimitiveIdentity,
)
where
import Data.Functor
import GHC.Conc
import GHC.Exts
import GHC.IO
import GHC.IORef
import GHC.MVar
import GHC.STRef
import GHC.Weak
data a :=> b = forall (a# :: TYPE 'UnliftedRep).
ErsatzPointer
{ (a :=> b) -> a
source :: a,
()
sourceIdentity# :: a#,
(a :=> b) -> b
target :: b,
(a :=> b) -> Maybe (IO ())
maybeFinalizer :: !(Maybe (IO ()))
}
{-# COMPLETE (:=>) #-}
pattern (:=>) :: Source a => a -> b -> (a :=> b)
pattern source $b:=> :: a -> b -> a :=> b
$m:=> :: forall r a b.
Source a =>
(a :=> b) -> (a -> b -> r) -> (Void# -> r) -> r
:=> target <-
ErsatzPointer {source, target}
where
a
source :=> b
target =
case a -> PrimitiveIdentity
forall a. Source a => a -> PrimitiveIdentity
primitiveIdentity a
source of
PrimitiveIdentity# a
sourceIdentity# ->
ErsatzPointer :: forall a b (a# :: TYPE 'UnliftedRep).
a -> a# -> b -> Maybe (IO ()) -> a :=> b
ErsatzPointer
{ a
source :: a
source :: a
source,
a
sourceIdentity# :: a
sourceIdentity# :: a
sourceIdentity#,
b
target :: b
target :: b
target,
maybeFinalizer :: Maybe (IO ())
maybeFinalizer = Maybe (IO ())
forall a. Maybe a
Nothing
}
establish :: (a :=> b) -> IO (a :=>? b)
establish :: (a :=> b) -> IO (a :=>? b)
establish pointer :: a :=> b
pointer@ErsatzPointer {a#
sourceIdentity# :: a#
sourceIdentity# :: ()
sourceIdentity#, Maybe (IO ())
maybeFinalizer :: Maybe (IO ())
maybeFinalizer :: forall a b. (a :=> b) -> Maybe (IO ())
maybeFinalizer} =
IO (Weak (a :=> b)) -> IO (a :=>? b)
coerce (a# -> (a :=> b) -> Maybe (IO ()) -> IO (Weak (a :=> b))
forall (source# :: TYPE 'UnliftedRep) target.
source# -> target -> Maybe (IO ()) -> IO (Weak target)
makeWeakPointer a#
sourceIdentity# a :=> b
pointer Maybe (IO ())
maybeFinalizer)
establish_ :: (a :=> b) -> IO ()
establish_ :: (a :=> b) -> IO ()
establish_ =
IO (a :=>? b) -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO (a :=>? b) -> IO ())
-> ((a :=> b) -> IO (a :=>? b)) -> (a :=> b) -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a :=> b) -> IO (a :=>? b)
forall a b. (a :=> b) -> IO (a :=>? b)
establish
onDismantle :: (a :=> b) -> IO () -> (a :=> b)
onDismantle :: (a :=> b) -> IO () -> a :=> b
onDismantle a :=> b
pointer IO ()
finalizer =
a :=> b
pointer {maybeFinalizer :: Maybe (IO ())
maybeFinalizer = (a :=> b) -> Maybe (IO ())
forall a b. (a :=> b) -> Maybe (IO ())
maybeFinalizer a :=> b
pointer Maybe (IO ()) -> Maybe (IO ()) -> Maybe (IO ())
forall a. Semigroup a => a -> a -> a
<> IO () -> Maybe (IO ())
forall a. a -> Maybe a
Just IO ()
finalizer}
newtype a :=>? b
= ErsatzPointerReference (Weak (a :=> b))
dereference :: (a :=>? b) -> IO (Maybe (a :=> b))
dereference :: (a :=>? b) -> IO (Maybe (a :=> b))
dereference (ErsatzPointerReference Weak (a :=> b)
weak) =
Weak (a :=> b) -> IO (Maybe (a :=> b))
forall v. Weak v -> IO (Maybe v)
deRefWeak Weak (a :=> b)
weak
dismantle :: (a :=>? b) -> IO ()
dismantle :: (a :=>? b) -> IO ()
dismantle (ErsatzPointerReference Weak (a :=> b)
weak) =
Weak (a :=> b) -> IO ()
forall v. Weak v -> IO ()
finalize Weak (a :=> b)
weak
class Source a where
primitiveIdentity :: a -> PrimitiveIdentity
instance Source (IORef a) where
primitiveIdentity :: IORef a -> PrimitiveIdentity
primitiveIdentity :: IORef a -> PrimitiveIdentity
primitiveIdentity (IORef (STRef MutVar# RealWorld a
var#)) = MutVar# RealWorld a -> PrimitiveIdentity
forall (a :: TYPE 'UnliftedRep). a -> PrimitiveIdentity
PrimitiveIdentity# MutVar# RealWorld a
var#
instance Source (MVar a) where
primitiveIdentity :: MVar a -> PrimitiveIdentity
primitiveIdentity :: MVar a -> PrimitiveIdentity
primitiveIdentity (MVar MVar# RealWorld a
var#) = MVar# RealWorld a -> PrimitiveIdentity
forall (a :: TYPE 'UnliftedRep). a -> PrimitiveIdentity
PrimitiveIdentity# MVar# RealWorld a
var#
instance Source (TVar a) where
primitiveIdentity :: TVar a -> PrimitiveIdentity
primitiveIdentity :: TVar a -> PrimitiveIdentity
primitiveIdentity (TVar TVar# RealWorld a
var#) = TVar# RealWorld a -> PrimitiveIdentity
forall (a :: TYPE 'UnliftedRep). a -> PrimitiveIdentity
PrimitiveIdentity# TVar# RealWorld a
var#
data PrimitiveIdentity where
PrimitiveIdentity# :: forall (a :: TYPE 'UnliftedRep). a -> PrimitiveIdentity
makeWeakPointer :: forall (source# :: TYPE 'UnliftedRep) target. source# -> target -> Maybe (IO ()) -> IO (Weak target)
makeWeakPointer :: source# -> target -> Maybe (IO ()) -> IO (Weak target)
makeWeakPointer source#
source# target
target = \case
Maybe (IO ())
Nothing ->
(State# RealWorld -> (# State# RealWorld, Weak target #))
-> IO (Weak target)
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO \State# RealWorld
s0# ->
case source#
-> target
-> State# RealWorld
-> (# State# RealWorld, Weak# target #)
forall a b.
a -> b -> State# RealWorld -> (# State# RealWorld, Weak# b #)
mkWeakNoFinalizer# source#
source# target
target State# RealWorld
s0# of
(# State# RealWorld
s1#, Weak# target
weak# #) -> (# State# RealWorld
s1#, Weak# target -> Weak target
forall v. Weak# v -> Weak v
Weak Weak# target
weak# #)
Just (IO State# RealWorld -> (# State# RealWorld, () #)
finalizer#) ->
(State# RealWorld -> (# State# RealWorld, Weak target #))
-> IO (Weak target)
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO \State# RealWorld
s0# ->
case source#
-> target
-> (State# RealWorld -> (# State# RealWorld, () #))
-> State# RealWorld
-> (# State# RealWorld, Weak# target #)
forall a b c.
a
-> b
-> (State# RealWorld -> (# State# RealWorld, c #))
-> State# RealWorld
-> (# State# RealWorld, Weak# b #)
mkWeak# source#
source# target
target State# RealWorld -> (# State# RealWorld, () #)
finalizer# State# RealWorld
s0# of
(# State# RealWorld
s1#, Weak# target
weak# #) -> (# State# RealWorld
s1#, Weak# target -> Weak target
forall v. Weak# v -> Weak v
Weak Weak# target
weak# #)