cc39ddeccfbb962ab2ac058ee20e540d99a819a5
[ghc.git] / libraries / base / Control / Concurrent.hs
1 {-# LANGUAGE Trustworthy #-}
2 {-# LANGUAGE CPP
3 , MagicHash
4 , UnboxedTuples
5 , ScopedTypeVariables
6 , RankNTypes
7 #-}
8 {-# OPTIONS_GHC -Wno-deprecations #-}
9 -- kludge for the Control.Concurrent.QSem, Control.Concurrent.QSemN
10 -- and Control.Concurrent.SampleVar imports.
11
12 -----------------------------------------------------------------------------
13 -- |
14 -- Module : Control.Concurrent
15 -- Copyright : (c) The University of Glasgow 2001
16 -- License : BSD-style (see the file libraries/base/LICENSE)
17 --
18 -- Maintainer : libraries@haskell.org
19 -- Stability : experimental
20 -- Portability : non-portable (concurrency)
21 --
22 -- A common interface to a collection of useful concurrency
23 -- abstractions.
24 --
25 -----------------------------------------------------------------------------
26
27 module Control.Concurrent (
28 -- * Concurrent Haskell
29
30 -- $conc_intro
31
32 -- * Basic concurrency operations
33
34 ThreadId,
35 myThreadId,
36
37 forkIO,
38 forkFinally,
39 forkIOWithUnmask,
40 killThread,
41 throwTo,
42
43 -- ** Threads with affinity
44 forkOn,
45 forkOnWithUnmask,
46 getNumCapabilities,
47 setNumCapabilities,
48 threadCapability,
49
50 -- * Scheduling
51
52 -- $conc_scheduling
53 yield,
54
55 -- ** Blocking
56
57 -- $blocking
58
59 -- ** Waiting
60 threadDelay,
61 threadWaitRead,
62 threadWaitWrite,
63 threadWaitReadSTM,
64 threadWaitWriteSTM,
65
66 -- * Communication abstractions
67
68 module Control.Concurrent.MVar,
69 module Control.Concurrent.Chan,
70 module Control.Concurrent.QSem,
71 module Control.Concurrent.QSemN,
72
73 -- * Bound Threads
74 -- $boundthreads
75 rtsSupportsBoundThreads,
76 forkOS,
77 forkOSWithUnmask,
78 isCurrentThreadBound,
79 runInBoundThread,
80 runInUnboundThread,
81
82 -- * Weak references to ThreadIds
83 mkWeakThreadId,
84
85 -- * GHC's implementation of concurrency
86
87 -- |This section describes features specific to GHC's
88 -- implementation of Concurrent Haskell.
89
90 -- ** Haskell threads and Operating System threads
91
92 -- $osthreads
93
94 -- ** Terminating the program
95
96 -- $termination
97
98 -- ** Pre-emption
99
100 -- $preemption
101
102 -- ** Deadlock
103
104 -- $deadlock
105
106 ) where
107
108 import Control.Exception.Base as Exception
109
110 import GHC.Conc hiding (threadWaitRead, threadWaitWrite,
111 threadWaitReadSTM, threadWaitWriteSTM)
112 import GHC.IO ( unsafeUnmask, catchException )
113 import GHC.IORef ( newIORef, readIORef, writeIORef )
114 import GHC.Base
115
116 import System.Posix.Types ( Fd )
117 import Foreign.StablePtr
118 import Foreign.C.Types
119
120 #if defined(mingw32_HOST_OS)
121 import Foreign.C
122 import System.IO
123 import Data.Functor ( void )
124 #else
125 import qualified GHC.Conc
126 #endif
127
128 import Control.Concurrent.MVar
129 import Control.Concurrent.Chan
130 import Control.Concurrent.QSem
131 import Control.Concurrent.QSemN
132
133 {- $conc_intro
134
135 The concurrency extension for Haskell is described in the paper
136 /Concurrent Haskell/
137 <http://www.haskell.org/ghc/docs/papers/concurrent-haskell.ps.gz>.
138
139 Concurrency is \"lightweight\", which means that both thread creation
140 and context switching overheads are extremely low. Scheduling of
141 Haskell threads is done internally in the Haskell runtime system, and
142 doesn't make use of any operating system-supplied thread packages.
143
144 However, if you want to interact with a foreign library that expects your
145 program to use the operating system-supplied thread package, you can do so
146 by using 'forkOS' instead of 'forkIO'.
147
148 Haskell threads can communicate via 'MVar's, a kind of synchronised
149 mutable variable (see "Control.Concurrent.MVar"). Several common
150 concurrency abstractions can be built from 'MVar's, and these are
151 provided by the "Control.Concurrent" library.
152 In GHC, threads may also communicate via exceptions.
153 -}
154
155 {- $conc_scheduling
156
157 Scheduling may be either pre-emptive or co-operative,
158 depending on the implementation of Concurrent Haskell (see below
159 for information related to specific compilers). In a co-operative
160 system, context switches only occur when you use one of the
161 primitives defined in this module. This means that programs such
162 as:
163
164
165 > main = forkIO (write 'a') >> write 'b'
166 > where write c = putChar c >> write c
167
168 will print either @aaaaaaaaaaaaaa...@ or @bbbbbbbbbbbb...@,
169 instead of some random interleaving of @a@s and @b@s. In
170 practice, cooperative multitasking is sufficient for writing
171 simple graphical user interfaces.
172 -}
173
174 {- $blocking
175 Different Haskell implementations have different characteristics with
176 regard to which operations block /all/ threads.
177
178 Using GHC without the @-threaded@ option, all foreign calls will block
179 all other Haskell threads in the system, although I\/O operations will
180 not. With the @-threaded@ option, only foreign calls with the @unsafe@
181 attribute will block all other threads.
182
183 -}
184
185 -- | Fork a thread and call the supplied function when the thread is about
186 -- to terminate, with an exception or a returned value. The function is
187 -- called with asynchronous exceptions masked.
188 --
189 -- > forkFinally action and_then =
190 -- > mask $ \restore ->
191 -- > forkIO $ try (restore action) >>= and_then
192 --
193 -- This function is useful for informing the parent when a child
194 -- terminates, for example.
195 --
196 -- @since 4.6.0.0
197 forkFinally :: IO a -> (Either SomeException a -> IO ()) -> IO ThreadId
198 forkFinally action and_then =
199 mask $ \restore ->
200 forkIO $ try (restore action) >>= and_then
201
202 -- ---------------------------------------------------------------------------
203 -- Bound Threads
204
205 {- $boundthreads
206 #boundthreads#
207
208 Support for multiple operating system threads and bound threads as described
209 below is currently only available in the GHC runtime system if you use the
210 /-threaded/ option when linking.
211
212 Other Haskell systems do not currently support multiple operating system threads.
213
214 A bound thread is a haskell thread that is /bound/ to an operating system
215 thread. While the bound thread is still scheduled by the Haskell run-time
216 system, the operating system thread takes care of all the foreign calls made
217 by the bound thread.
218
219 To a foreign library, the bound thread will look exactly like an ordinary
220 operating system thread created using OS functions like @pthread_create@
221 or @CreateThread@.
222
223 Bound threads can be created using the 'forkOS' function below. All foreign
224 exported functions are run in a bound thread (bound to the OS thread that
225 called the function). Also, the @main@ action of every Haskell program is
226 run in a bound thread.
227
228 Why do we need this? Because if a foreign library is called from a thread
229 created using 'forkIO', it won't have access to any /thread-local state/ -
230 state variables that have specific values for each OS thread
231 (see POSIX's @pthread_key_create@ or Win32's @TlsAlloc@). Therefore, some
232 libraries (OpenGL, for example) will not work from a thread created using
233 'forkIO'. They work fine in threads created using 'forkOS' or when called
234 from @main@ or from a @foreign export@.
235
236 In terms of performance, 'forkOS' (aka bound) threads are much more
237 expensive than 'forkIO' (aka unbound) threads, because a 'forkOS'
238 thread is tied to a particular OS thread, whereas a 'forkIO' thread
239 can be run by any OS thread. Context-switching between a 'forkOS'
240 thread and a 'forkIO' thread is many times more expensive than between
241 two 'forkIO' threads.
242
243 Note in particular that the main program thread (the thread running
244 @Main.main@) is always a bound thread, so for good concurrency
245 performance you should ensure that the main thread is not doing
246 repeated communication with other threads in the system. Typically
247 this means forking subthreads to do the work using 'forkIO', and
248 waiting for the results in the main thread.
249
250 -}
251
252 -- | 'True' if bound threads are supported.
253 -- If @rtsSupportsBoundThreads@ is 'False', 'isCurrentThreadBound'
254 -- will always return 'False' and both 'forkOS' and 'runInBoundThread' will
255 -- fail.
256 foreign import ccall unsafe rtsSupportsBoundThreads :: Bool
257
258
259 {- |
260 Like 'forkIO', this sparks off a new thread to run the 'IO'
261 computation passed as the first argument, and returns the 'ThreadId'
262 of the newly created thread.
263
264 However, 'forkOS' creates a /bound/ thread, which is necessary if you
265 need to call foreign (non-Haskell) libraries that make use of
266 thread-local state, such as OpenGL (see "Control.Concurrent#boundthreads").
267
268 Using 'forkOS' instead of 'forkIO' makes no difference at all to the
269 scheduling behaviour of the Haskell runtime system. It is a common
270 misconception that you need to use 'forkOS' instead of 'forkIO' to
271 avoid blocking all the Haskell threads when making a foreign call;
272 this isn't the case. To allow foreign calls to be made without
273 blocking all the Haskell threads (with GHC), it is only necessary to
274 use the @-threaded@ option when linking your program, and to make sure
275 the foreign import is not marked @unsafe@.
276 -}
277
278 forkOS :: IO () -> IO ThreadId
279
280 foreign export ccall forkOS_entry
281 :: StablePtr (IO ()) -> IO ()
282
283 foreign import ccall "forkOS_entry" forkOS_entry_reimported
284 :: StablePtr (IO ()) -> IO ()
285
286 forkOS_entry :: StablePtr (IO ()) -> IO ()
287 forkOS_entry stableAction = do
288 action <- deRefStablePtr stableAction
289 action
290
291 foreign import ccall forkOS_createThread
292 :: StablePtr (IO ()) -> IO CInt
293
294 failNonThreaded :: IO a
295 failNonThreaded = fail $ "RTS doesn't support multiple OS threads "
296 ++"(use ghc -threaded when linking)"
297
298 forkOS action0
299 | rtsSupportsBoundThreads = do
300 mv <- newEmptyMVar
301 b <- Exception.getMaskingState
302 let
303 -- async exceptions are masked in the child if they are masked
304 -- in the parent, as for forkIO (see #1048). forkOS_createThread
305 -- creates a thread with exceptions masked by default.
306 action1 = case b of
307 Unmasked -> unsafeUnmask action0
308 MaskedInterruptible -> action0
309 MaskedUninterruptible -> uninterruptibleMask_ action0
310
311 action_plus = catch action1 childHandler
312
313 entry <- newStablePtr (myThreadId >>= putMVar mv >> action_plus)
314 err <- forkOS_createThread entry
315 when (err /= 0) $ fail "Cannot create OS thread."
316 tid <- takeMVar mv
317 freeStablePtr entry
318 return tid
319 | otherwise = failNonThreaded
320
321 -- | Like 'forkIOWithUnmask', but the child thread is a bound thread,
322 -- as with 'forkOS'.
323 forkOSWithUnmask :: ((forall a . IO a -> IO a) -> IO ()) -> IO ThreadId
324 forkOSWithUnmask io = forkOS (io unsafeUnmask)
325
326 -- | Returns 'True' if the calling thread is /bound/, that is, if it is
327 -- safe to use foreign libraries that rely on thread-local state from the
328 -- calling thread.
329 isCurrentThreadBound :: IO Bool
330 isCurrentThreadBound = IO $ \ s# ->
331 case isCurrentThreadBound# s# of
332 (# s2#, flg #) -> (# s2#, isTrue# (flg /=# 0#) #)
333
334
335 {- |
336 Run the 'IO' computation passed as the first argument. If the calling thread
337 is not /bound/, a bound thread is created temporarily. @runInBoundThread@
338 doesn't finish until the 'IO' computation finishes.
339
340 You can wrap a series of foreign function calls that rely on thread-local state
341 with @runInBoundThread@ so that you can use them without knowing whether the
342 current thread is /bound/.
343 -}
344 runInBoundThread :: IO a -> IO a
345
346 runInBoundThread action
347 | rtsSupportsBoundThreads = do
348 bound <- isCurrentThreadBound
349 if bound
350 then action
351 else do
352 ref <- newIORef undefined
353 let action_plus = Exception.try action >>= writeIORef ref
354 bracket (newStablePtr action_plus)
355 freeStablePtr
356 (\cEntry -> forkOS_entry_reimported cEntry >> readIORef ref) >>=
357 unsafeResult
358 | otherwise = failNonThreaded
359
360 {- |
361 Run the 'IO' computation passed as the first argument. If the calling thread
362 is /bound/, an unbound thread is created temporarily using 'forkIO'.
363 @runInBoundThread@ doesn't finish until the 'IO' computation finishes.
364
365 Use this function /only/ in the rare case that you have actually observed a
366 performance loss due to the use of bound threads. A program that
367 doesn't need its main thread to be bound and makes /heavy/ use of concurrency
368 (e.g. a web server), might want to wrap its @main@ action in
369 @runInUnboundThread@.
370
371 Note that exceptions which are thrown to the current thread are thrown in turn
372 to the thread that is executing the given computation. This ensures there's
373 always a way of killing the forked thread.
374 -}
375 runInUnboundThread :: IO a -> IO a
376
377 runInUnboundThread action = do
378 bound <- isCurrentThreadBound
379 if bound
380 then do
381 mv <- newEmptyMVar
382 mask $ \restore -> do
383 tid <- forkIO $ Exception.try (restore action) >>= putMVar mv
384 let wait = takeMVar mv `catchException` \(e :: SomeException) ->
385 Exception.throwTo tid e >> wait
386 wait >>= unsafeResult
387 else action
388
389 unsafeResult :: Either SomeException a -> IO a
390 unsafeResult = either Exception.throwIO return
391
392 -- ---------------------------------------------------------------------------
393 -- threadWaitRead/threadWaitWrite
394
395 -- | Block the current thread until data is available to read on the
396 -- given file descriptor (GHC only).
397 --
398 -- This will throw an 'IOError' if the file descriptor was closed
399 -- while this thread was blocked. To safely close a file descriptor
400 -- that has been used with 'threadWaitRead', use
401 -- 'GHC.Conc.closeFdWith'.
402 threadWaitRead :: Fd -> IO ()
403 threadWaitRead fd
404 #if defined(mingw32_HOST_OS)
405 -- we have no IO manager implementing threadWaitRead on Windows.
406 -- fdReady does the right thing, but we have to call it in a
407 -- separate thread, otherwise threadWaitRead won't be interruptible,
408 -- and this only works with -threaded.
409 | threaded = withThread (waitFd fd 0)
410 | otherwise = case fd of
411 0 -> do _ <- hWaitForInput stdin (-1)
412 return ()
413 -- hWaitForInput does work properly, but we can only
414 -- do this for stdin since we know its FD.
415 _ -> errorWithoutStackTrace "threadWaitRead requires -threaded on Windows, or use System.IO.hWaitForInput"
416 #else
417 = GHC.Conc.threadWaitRead fd
418 #endif
419
420 -- | Block the current thread until data can be written to the
421 -- given file descriptor (GHC only).
422 --
423 -- This will throw an 'IOError' if the file descriptor was closed
424 -- while this thread was blocked. To safely close a file descriptor
425 -- that has been used with 'threadWaitWrite', use
426 -- 'GHC.Conc.closeFdWith'.
427 threadWaitWrite :: Fd -> IO ()
428 threadWaitWrite fd
429 #if defined(mingw32_HOST_OS)
430 | threaded = withThread (waitFd fd 1)
431 | otherwise = errorWithoutStackTrace "threadWaitWrite requires -threaded on Windows"
432 #else
433 = GHC.Conc.threadWaitWrite fd
434 #endif
435
436 -- | Returns an STM action that can be used to wait for data
437 -- to read from a file descriptor. The second returned value
438 -- is an IO action that can be used to deregister interest
439 -- in the file descriptor.
440 --
441 -- @since 4.7.0.0
442 threadWaitReadSTM :: Fd -> IO (STM (), IO ())
443 threadWaitReadSTM fd
444 #if defined(mingw32_HOST_OS)
445 | threaded = do v <- newTVarIO Nothing
446 mask_ $ void $ forkIO $ do result <- try (waitFd fd 0)
447 atomically (writeTVar v $ Just result)
448 let waitAction = do result <- readTVar v
449 case result of
450 Nothing -> retry
451 Just (Right ()) -> return ()
452 Just (Left e) -> throwSTM (e :: IOException)
453 let killAction = return ()
454 return (waitAction, killAction)
455 | otherwise = errorWithoutStackTrace "threadWaitReadSTM requires -threaded on Windows"
456 #else
457 = GHC.Conc.threadWaitReadSTM fd
458 #endif
459
460 -- | Returns an STM action that can be used to wait until data
461 -- can be written to a file descriptor. The second returned value
462 -- is an IO action that can be used to deregister interest
463 -- in the file descriptor.
464 --
465 -- @since 4.7.0.0
466 threadWaitWriteSTM :: Fd -> IO (STM (), IO ())
467 threadWaitWriteSTM fd
468 #if defined(mingw32_HOST_OS)
469 | threaded = do v <- newTVarIO Nothing
470 mask_ $ void $ forkIO $ do result <- try (waitFd fd 1)
471 atomically (writeTVar v $ Just result)
472 let waitAction = do result <- readTVar v
473 case result of
474 Nothing -> retry
475 Just (Right ()) -> return ()
476 Just (Left e) -> throwSTM (e :: IOException)
477 let killAction = return ()
478 return (waitAction, killAction)
479 | otherwise = errorWithoutStackTrace "threadWaitWriteSTM requires -threaded on Windows"
480 #else
481 = GHC.Conc.threadWaitWriteSTM fd
482 #endif
483
484 #if defined(mingw32_HOST_OS)
485 foreign import ccall unsafe "rtsSupportsBoundThreads" threaded :: Bool
486
487 withThread :: IO a -> IO a
488 withThread io = do
489 m <- newEmptyMVar
490 _ <- mask_ $ forkIO $ try io >>= putMVar m
491 x <- takeMVar m
492 case x of
493 Right a -> return a
494 Left e -> throwIO (e :: IOException)
495
496 waitFd :: Fd -> CInt -> IO ()
497 waitFd fd write = do
498 throwErrnoIfMinus1_ "fdReady" $
499 fdReady (fromIntegral fd) write iNFINITE 0
500
501 iNFINITE :: CInt
502 iNFINITE = 0xFFFFFFFF -- urgh
503
504 foreign import ccall safe "fdReady"
505 fdReady :: CInt -> CInt -> CInt -> CInt -> IO CInt
506 #endif
507
508 -- ---------------------------------------------------------------------------
509 -- More docs
510
511 {- $osthreads
512
513 #osthreads# In GHC, threads created by 'forkIO' are lightweight threads, and
514 are managed entirely by the GHC runtime. Typically Haskell
515 threads are an order of magnitude or two more efficient (in
516 terms of both time and space) than operating system threads.
517
518 The downside of having lightweight threads is that only one can
519 run at a time, so if one thread blocks in a foreign call, for
520 example, the other threads cannot continue. The GHC runtime
521 works around this by making use of full OS threads where
522 necessary. When the program is built with the @-threaded@
523 option (to link against the multithreaded version of the
524 runtime), a thread making a @safe@ foreign call will not block
525 the other threads in the system; another OS thread will take
526 over running Haskell threads until the original call returns.
527 The runtime maintains a pool of these /worker/ threads so that
528 multiple Haskell threads can be involved in external calls
529 simultaneously.
530
531 The "System.IO" library manages multiplexing in its own way. On
532 Windows systems it uses @safe@ foreign calls to ensure that
533 threads doing I\/O operations don't block the whole runtime,
534 whereas on Unix systems all the currently blocked I\/O requests
535 are managed by a single thread (the /IO manager thread/) using
536 a mechanism such as @epoll@ or @kqueue@, depending on what is
537 provided by the host operating system.
538
539 The runtime will run a Haskell thread using any of the available
540 worker OS threads. If you need control over which particular OS
541 thread is used to run a given Haskell thread, perhaps because
542 you need to call a foreign library that uses OS-thread-local
543 state, then you need bound threads (see "Control.Concurrent#boundthreads").
544
545 If you don't use the @-threaded@ option, then the runtime does
546 not make use of multiple OS threads. Foreign calls will block
547 all other running Haskell threads until the call returns. The
548 "System.IO" library still does multiplexing, so there can be multiple
549 threads doing I\/O, and this is handled internally by the runtime using
550 @select@.
551 -}
552
553 {- $termination
554
555 In a standalone GHC program, only the main thread is
556 required to terminate in order for the process to terminate.
557 Thus all other forked threads will simply terminate at the same
558 time as the main thread (the terminology for this kind of
559 behaviour is \"daemonic threads\").
560
561 If you want the program to wait for child threads to
562 finish before exiting, you need to program this yourself. A
563 simple mechanism is to have each child thread write to an
564 'MVar' when it completes, and have the main
565 thread wait on all the 'MVar's before
566 exiting:
567
568 > myForkIO :: IO () -> IO (MVar ())
569 > myForkIO io = do
570 > mvar <- newEmptyMVar
571 > forkFinally io (\_ -> putMVar mvar ())
572 > return mvar
573
574 Note that we use 'forkFinally' to make sure that the
575 'MVar' is written to even if the thread dies or
576 is killed for some reason.
577
578 A better method is to keep a global list of all child
579 threads which we should wait for at the end of the program:
580
581 > children :: MVar [MVar ()]
582 > children = unsafePerformIO (newMVar [])
583 >
584 > waitForChildren :: IO ()
585 > waitForChildren = do
586 > cs <- takeMVar children
587 > case cs of
588 > [] -> return ()
589 > m:ms -> do
590 > putMVar children ms
591 > takeMVar m
592 > waitForChildren
593 >
594 > forkChild :: IO () -> IO ThreadId
595 > forkChild io = do
596 > mvar <- newEmptyMVar
597 > childs <- takeMVar children
598 > putMVar children (mvar:childs)
599 > forkFinally io (\_ -> putMVar mvar ())
600 >
601 > main =
602 > later waitForChildren $
603 > ...
604
605 The main thread principle also applies to calls to Haskell from
606 outside, using @foreign export@. When the @foreign export@ed
607 function is invoked, it starts a new main thread, and it returns
608 when this main thread terminates. If the call causes new
609 threads to be forked, they may remain in the system after the
610 @foreign export@ed function has returned.
611 -}
612
613 {- $preemption
614
615 GHC implements pre-emptive multitasking: the execution of
616 threads are interleaved in a random fashion. More specifically,
617 a thread may be pre-empted whenever it allocates some memory,
618 which unfortunately means that tight loops which do no
619 allocation tend to lock out other threads (this only seems to
620 happen with pathological benchmark-style code, however).
621
622 The rescheduling timer runs on a 20ms granularity by
623 default, but this may be altered using the
624 @-i\<n\>@ RTS option. After a rescheduling
625 \"tick\" the running thread is pre-empted as soon as
626 possible.
627
628 One final note: the
629 @aaaa@ @bbbb@ example may not
630 work too well on GHC (see Scheduling, above), due
631 to the locking on a 'System.IO.Handle'. Only one thread
632 may hold the lock on a 'System.IO.Handle' at any one
633 time, so if a reschedule happens while a thread is holding the
634 lock, the other thread won't be able to run. The upshot is that
635 the switch from @aaaa@ to
636 @bbbbb@ happens infrequently. It can be
637 improved by lowering the reschedule tick period. We also have a
638 patch that causes a reschedule whenever a thread waiting on a
639 lock is woken up, but haven't found it to be useful for anything
640 other than this example :-)
641 -}
642
643 {- $deadlock
644
645 GHC attempts to detect when threads are deadlocked using the garbage
646 collector. A thread that is not reachable (cannot be found by
647 following pointers from live objects) must be deadlocked, and in this
648 case the thread is sent an exception. The exception is either
649 'BlockedIndefinitelyOnMVar', 'BlockedIndefinitelyOnSTM',
650 'NonTermination', or 'Deadlock', depending on the way in which the
651 thread is deadlocked.
652
653 Note that this feature is intended for debugging, and should not be
654 relied on for the correct operation of your program. There is no
655 guarantee that the garbage collector will be accurate enough to detect
656 your deadlock, and no guarantee that the garbage collector will run in
657 a timely enough manner. Basically, the same caveats as for finalizers
658 apply to deadlock detection.
659
660 There is a subtle interaction between deadlock detection and
661 finalizers (as created by 'Foreign.Concurrent.newForeignPtr' or the
662 functions in "System.Mem.Weak"): if a thread is blocked waiting for a
663 finalizer to run, then the thread will be considered deadlocked and
664 sent an exception. So preferably don't do this, but if you have no
665 alternative then it is possible to prevent the thread from being
666 considered deadlocked by making a 'StablePtr' pointing to it. Don't
667 forget to release the 'StablePtr' later with 'freeStablePtr'.
668 -}