Finalizers etcetera

Malcolm Wallace Malcolm.Wallace at
Fri Oct 11 10:33:29 EDT 2002

Alastair Reid <alastair at> writes:

> Malcolm: are you ready to add MVars to NHC?

I have just done a little investigation to try to discover exactly
what MVars are semantically, since it is far from obvious from the
name alone.  The GHC user's guide (7.2.15) has the following:

    type MVar# s elt        -- primitive

    newMVar#    :: State# s -> (# State# s, MVar# s elt #)
    takeMVar#   :: SynchVar# s elt -> State# s -> (# State# s, elt #)
    putMVar#    :: SynchVar# s elt -> State# s -> State# s

where the inconsistent naming suggests that MVars were once named
SynchVars, which would make much more sense.  (Why do implementers
always go for shorter-to-type rather than easier-to-understand?)

As another aside, in the hierarchical libraries docs (package base,
Control.Concurrent.MVar) there appears to be an ambiguity:

    readMVar :: MVar a -> IO a
    This is a combination of takeMVar and putMVar; ie. it takes the
    value from the MVar, puts it back, and also returns it.

It specifically avoids describing the combination as atomic, so I
am uncertain whether the thread can be pre-empted between the 'take'
and the 'put'?  Normally the answer would be yes, but then there is no
benefit from having a separate 'readMVar' to combine the operations,
so I am guessing that it /should/ be atomic.

Now to the question of whether we can implement something like this
in nhc98.  Tricky one.  What does it mean for the only thread in a
single-thread system to block waiting on another thread?  Deadlock
of course, as you already pointed out.  It seems a bit pointless to
implement that!

I think the key point here is that for MVars to make sense, you
need concurrency.  And if you really want to manipulate shared state
safely in Haskell, it implies MVars.  Thus, the need for concurrency
has always been your objection to writing finalisers in Haskell.

However, I now do /not/ think it is finalisers in Haskell per se
that are the problem.  The problem is the desire to manipulate shared
state in a concurrent manner.  The FFI specification is a stand-alone
specification extending Haskell'98 only, and should neither rely on
concurrency nor outlaw it.  Thus it seems sensible for the FFI to say:

  (1) do not manipulate shared state in a finaliser unless your host
      system implements concurrency;
  (2) if you do manipulate shared state in a finaliser, then you must
      use the model for mutual exclusion provided by the host system
      (e.g. MVars, or storing the shared state in the foreign
      language only).


More information about the FFI mailing list