@@ -149,6 +149,7 @@ module Control.Distributed.Process
149149 -- * Local versions of 'spawn'
150150 , spawnLocal
151151 , spawnChannelLocal
152+ , callLocal
152153 -- * Reconnecting
153154 , reconnect
154155 , reconnectPort
@@ -302,6 +303,7 @@ import Control.Distributed.Process.Internal.Spawn
302303 , spawnSupervised
303304 , call
304305 )
306+import Control.Exception (SomeException, throwIO)
305307
306308-- INTERNAL NOTES
307309--
@@ -392,3 +394,20 @@ spawnChannelLocal proc = do
392394 liftIO $ putMVar mvar sport
393395 proc rport
394396 takeMVar mvar
397+
398+-- | Local version of 'call'. Running a process in this way isolates it from
399+-- messages sent to the caller process, and also allows silently dropping late
400+-- or duplicate messages sent to the isolated process after it exits.
401+-- Silently dropping messages may not always be the best approach.
402+callLocal ::
403+ Process a -- ^ Process to run
404+ -> Process a -- ^ Value returned
405+callLocal proc = do
406+ mv <- liftIO newEmptyMVar
407+ self <- getSelfPid
408+ _ <- spawnLocal $ do
409+ link self
410+ try proc >>= liftIO . putMVar mv
411+ liftIO $ takeMVar mv >>=
412+ either (throwIO :: SomeException -> IO a) return
413+