@@ -47,6 +47,7 @@ import Data.Binary (encode, decode)
4747import qualified Data.Map as Map (insert)
4848import Data.Dynamic (toDyn)
4949import Control.Applicative ((<$>))
50+import Control.Monad (join)
5051import Language.Haskell.TH
5152 ( -- Q monad and operations
5253 Q
@@ -77,7 +78,11 @@ import Control.Distributed.Process.Internal.Types
7778 ( RemoteTable
7879 , Closure(..)
7980 , Static(..)
81+ , Process
82+ , ProcessId
83+ , CallReply(..)
8084 )
85+import Control.Distributed.Process (send, unClosure)
8186
8287--------------------------------------------------------------------------------
8388-- Top-level API --
@@ -87,9 +92,9 @@ import Control.Distributed.Process.Internal.Types
8792-- of functions
8893remotable :: [Name] -> Q [Dec]
8994remotable ns = do
90− (closures, decoders, inserts) <- unzip3 <$> mapM process ns
91− rtable <- createMetaData inserts
92− return $ concat closures ++ concat decoders ++ rtable
95+ (closures, inserts) <- unzip <$> mapM generateDefs ns
96+ rtable <- createMetaData (concat inserts)
97+ return $ concat closures ++ rtable
9398
9499-- | Create a closure
95100mkClosure :: Name -> Q Exp
@@ -110,22 +115,36 @@ createMetaData is =
110115--
111116-- Given an (f :: a -> b) in module M, create:
112117-- 1. f__closure :: a -> Closure b,
113−-- 2. f__dec :: ByteString -> b
114−-- 3. Map.insert "M.f" (toDyn f__dec)
115−process :: Name -> Q ([Dec], [Dec], Q Exp)
116−process n = do
118+-- 2. Map.insert "M.f" (toDyn ((f . enc) :: ByteString -> b))
119+--
120+-- Moreover, if b is of the form Process c, then additionally create
121+-- 3. Map.insert "M.f__call" (... :: ByteString -> Process ())
122+-- (see 'generateCallClosure')
123+generateDefs :: Name -> Q ([Dec], [Q Exp])
124+generateDefs n = do
117125 mType <- getType n
118126 case mType of
119127 Just (origName, ArrowT `AppT` arg `AppT` res) -> do
120128 (closure, label) <- generateClosure origName (return arg) (return res)
121− decoder <- generateDecoder origName (return res)
122− let decoderE = varE (decoderName n)
123− insert = [| Map.insert $(stringE label) (toDyn $decoderE) |]
124− return (closure, decoder, insert)
129+ let decoder = generateDecoder origName (return res)
130+ insert = [| Map.insert $(stringE label) (toDyn $decoder) |]
131+
132+ -- Generate special closure to support 'call'
133+ mResult <- processResult res
134+ insert' <- case mResult of
135+ Nothing ->
136+ return []
137+ Just result -> do
138+ let encoder = generateCallClosure origName (return result)
139+ label' = label ++ "__call"
140+ return . return $
141+ [| Map.insert $(stringE label') (toDyn $encoder) |]
142+
143+ return (closure, insert : insert')
125144 _ ->
126145 fail $ "remotable: " ++ show n ++ " is not a function"
127146
128−-- | Generate the closure creator (see 'process')
147+-- | Generate the closure creator (see 'generateDefs')
129148generateClosure :: Name -> Q Type -> Q Type -> Q ([Dec], String)
130149generateClosure n arg res = do
131150 closure <- sequence
@@ -137,12 +156,26 @@ generateClosure n arg res = do
137156 label :: String
138157 label = show $ n
139158
140−-- | Generate the decoder (see 'process')
141−generateDecoder :: Name -> Q Type -> Q [Dec]
142−generateDecoder n res = do
143− sequence [ sigD (decoderName n) [t| ByteString -> $res |]
144− , sfnD (decoderName n) [| $(varE n) . decode |]
145− ]
159+-- | If 't' is of the form 'Process b', return 'Just b'
160+processResult :: Type -> Q (Maybe Type)
161+processResult t = do
162+ process <- [t| Process |]
163+ case t of
164+ p `AppT` a | p == process -> return $ Just a
165+ _ -> return Nothing
166+
167+-- | Generate the decoder (see 'generateDefs')
168+generateDecoder :: Name -> Q Type -> Q Exp
169+generateDecoder n res = [| $(varE n) . decode :: ByteString -> $res |]
170+
171+-- | Generate the call-closure. This is necessary to support 'call'
172+generateCallClosure :: Name -> Q Type -> Q Exp
173+generateCallClosure n t =
174+ [| (\env -> do
175+ let (cl, them) = decode env :: (Closure (Process $t), ProcessId)
176+ join (unClosure cl) >>= send them . CallReply
177+ ) :: ByteString -> Process ()
178+ |]
146179
147180-- | The name for the function that generates the closure
148181closureName :: Name -> Name