Talk:Parallelism vs. Concurrency
Jump to navigation
Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Parallelism vs concurrency: what's the difference?
Visible side effects.
- Have a look at this
ugly eysore"prototype definition" ofpar
:
par :: a -> b -> b par x y = case unsafeLocalState (forkIO (evalIO x >> return ())) of !_ -> y
where:
evalIO :: a -> IO a forkIO :: IO () -> IO ThreadId
Assuming:
x
is well-defined (it contains nounsafe...
calls),x
is well-behaved (not throwing exceptions or causing errors);
then:
forkIO
attaches aThreadId
to its argument, adds it to the work-queue and returns the identifier;par
then returnsy
;- Some time later,
forkIO
's argument is called, causingevalIO
to start evaluatingx
.
If
y
is still being evaluated when the evaluation ofx
commences, then we have elementary parallelism: concurrency, but with no visible side-effects.
- Now have a look at this
equally-as-uglyprototype definition forspawnIO
forkIO
:
forkIO :: IO () -> IO ThreadId forkIO act = do let t = unsafeLocalState act case par t () of !_ -> do i' <- itsThreadId t case i' of Just i -> return i Nothing -> ioError "forkIO"
where:
itsThreadId :: a -> IO (Maybe ThreadId)
Assuming:
par
anditsThreadId
are primitive,itsThreadId
would returnNothing
if it's argument had not been previously used bypar
;
then:
- Evaluating
par t ()
causes a newThreadId
to be attached tot
by the implementation; itsThreadId
retrievesi'
, the (possible) identifier fort
;forkIO
then extracts and returns the identifier.
This looks very much like elementary concurrency: parallelism, but having visible side effects.
Can either of these prototypes ever go mainstream?
- As shown by it's type signature,
par
is supposed to be pure: avoiding the use ofunsafeLocalState
means making it primitive; - Considering it's already
IO
-based,forkIO
withoutunsafeLocalState
seems more likely.
This looks interesting:
forkIO :: (OI -> ()) -> OI -> ThreadId
forkIO act u = let !(u1:u2:u3:_) = parts u in
let t = act u1 in
case par t () of
!_ -> case itsThreadId t u2 of
Just i -> i
Nothing -> ioError "forkIO" u3
-- Atravers Tue Apr 20 06:04:10 UTC 2021