never executed always true always false
1 {-# LANGUAGE CPP, StandaloneDeriving, GeneralizedNewtypeDeriving #-}
2
3 -- |
4 -- Types for referring to remote objects in Remote GHCi. For more
5 -- details, see Note [External GHCi pointers] in compiler/GHC/Runtime/Interpreter.hs
6 --
7 -- For details on Remote GHCi, see Note [Remote GHCi] in
8 -- compiler/GHC/Runtime/Interpreter.hs.
9 --
10 module GHCi.RemoteTypes
11 ( RemotePtr(..), toRemotePtr, fromRemotePtr, castRemotePtr
12 , HValue(..)
13 , RemoteRef, mkRemoteRef, localRef, freeRemoteRef
14 , HValueRef, toHValueRef
15 , ForeignRef, mkForeignRef, withForeignRef
16 , ForeignHValue
17 , unsafeForeignRefToRemoteRef, finalizeForeignRef
18 ) where
19
20 import Prelude -- See note [Why do we import Prelude here?]
21 import Control.DeepSeq
22 import Data.Word
23 import Foreign hiding (newForeignPtr)
24 import Foreign.Concurrent
25 import Data.Binary
26 import Unsafe.Coerce
27 import GHC.Exts
28 import GHC.ForeignPtr
29
30 -- -----------------------------------------------------------------------------
31 -- RemotePtr
32
33 -- Static pointers only; don't use this for heap-resident pointers.
34 -- Instead use HValueRef. We will fix the remote pointer to be 64 bits. This
35 -- should cover 64 and 32bit systems, and permits the exchange of remote ptrs
36 -- between machines of different word size. For example, when connecting to
37 -- an iserv instance on a different architecture with different word size via
38 -- -fexternal-interpreter.
39 newtype RemotePtr a = RemotePtr Word64
40
41 toRemotePtr :: Ptr a -> RemotePtr a
42 toRemotePtr p = RemotePtr (fromIntegral (ptrToWordPtr p))
43
44 fromRemotePtr :: RemotePtr a -> Ptr a
45 fromRemotePtr (RemotePtr p) = wordPtrToPtr (fromIntegral p)
46
47 castRemotePtr :: RemotePtr a -> RemotePtr b
48 castRemotePtr (RemotePtr a) = RemotePtr a
49
50 deriving instance Show (RemotePtr a)
51 deriving instance Binary (RemotePtr a)
52 deriving instance NFData (RemotePtr a)
53
54 -- -----------------------------------------------------------------------------
55 -- HValueRef
56
57 newtype HValue = HValue Any
58
59 instance Show HValue where
60 show _ = "<HValue>"
61
62 -- | A reference to a remote value. These are allocated and freed explicitly.
63 newtype RemoteRef a = RemoteRef (RemotePtr ())
64 deriving (Show, Binary)
65
66 -- We can discard type information if we want
67 toHValueRef :: RemoteRef a -> RemoteRef HValue
68 toHValueRef = unsafeCoerce
69
70 -- For convenience
71 type HValueRef = RemoteRef HValue
72
73 -- | Make a reference to a local value that we can send remotely.
74 -- This reference will keep the value that it refers to alive until
75 -- 'freeRemoteRef' is called.
76 mkRemoteRef :: a -> IO (RemoteRef a)
77 mkRemoteRef a = do
78 sp <- newStablePtr a
79 return $! RemoteRef (toRemotePtr (castStablePtrToPtr sp))
80
81 -- | Convert an HValueRef to an HValue. Should only be used if the HValue
82 -- originated in this process.
83 localRef :: RemoteRef a -> IO a
84 localRef (RemoteRef w) =
85 deRefStablePtr (castPtrToStablePtr (fromRemotePtr w))
86
87 -- | Release an HValueRef that originated in this process
88 freeRemoteRef :: RemoteRef a -> IO ()
89 freeRemoteRef (RemoteRef w) =
90 freeStablePtr (castPtrToStablePtr (fromRemotePtr w))
91
92 -- | An HValueRef with a finalizer
93 newtype ForeignRef a = ForeignRef (ForeignPtr ())
94
95 instance NFData (ForeignRef a) where
96 rnf x = x `seq` ()
97
98 type ForeignHValue = ForeignRef HValue
99
100 -- | Create a 'ForeignRef' from a 'RemoteRef'. The finalizer
101 -- should arrange to call 'freeHValueRef' on the 'HValueRef'. (since
102 -- this function needs to be called in the process that created the
103 -- 'HValueRef', it cannot be called directly from the finalizer).
104 mkForeignRef :: RemoteRef a -> IO () -> IO (ForeignRef a)
105 mkForeignRef (RemoteRef hvref) finalizer =
106 ForeignRef <$> newForeignPtr (fromRemotePtr hvref) finalizer
107
108 -- | Use a 'ForeignHValue'
109 withForeignRef :: ForeignRef a -> (RemoteRef a -> IO b) -> IO b
110 withForeignRef (ForeignRef fp) f =
111 withForeignPtr fp (f . RemoteRef . toRemotePtr)
112
113 unsafeForeignRefToRemoteRef :: ForeignRef a -> RemoteRef a
114 unsafeForeignRefToRemoteRef (ForeignRef fp) =
115 RemoteRef (toRemotePtr (unsafeForeignPtrToPtr fp))
116
117 finalizeForeignRef :: ForeignRef a -> IO ()
118 finalizeForeignRef (ForeignRef fp) = finalizeForeignPtr fp