Make a Weak pointer to an IORef, using the second argument as a finalizer
to run when IORef is garbage-collected

Memory Model

In a concurrent program, IORef operations may appear out-of-order
to another thread, depending on the memory model of the underlying
processor architecture. For example, on x86, loads can move ahead
of stores, so in the following example:

it is possible that the string critical section is printed
twice, even though there is no interleaving of the operations of the
two threads that allows that outcome. The memory model of x86
allows readIORef to happen before the earlier writeIORef.

The implementation is required to ensure that reordering of memory
operations cannot cause type-correct code to go wrong. In
particular, when inspecting the value read from an IORef, the
memory writes that created that value must have occurred from the
point of view of the current therad.