[Haskell-cafe] What does unpacking an MVar really mean?

Bertram Felgenhauer bertram.felgenhauer at googlemail.com
Tue Jul 31 13:37:38 CEST 2012


Leon Smith wrote:
> I am familiar with the source of Control.Concurrent.MVar,  and I do see {-#
> UNPACK #-}'ed MVars around,  for example in GHC's IO manager.     What I
> should have asked is,  what does an MVar# look like?  This cannot be
> inferred from Haskell source;  though I suppose I could have tried to read
> the Runtime source.

So let's have a brief look at the source. MVar# is an RTS specific
heap object which contains three pointers:

(from ghc/includes/rts/storage/Closures.h)

typedef struct {
    StgHeader                header;
    struct StgMVarTSOQueue_ *head;
    struct StgMVarTSOQueue_ *tail;
    StgClosure*              value;
} StgMVar;

The 'value' pointer refers to the actual value held by the mutable
variable, if any. The 'head' and 'tail' pointers are used for
managing a linked list of threads blocked on the mutable variable.

An MVar (if evaluated) contains just a pointer the MVar# object.

To access the value of an MVar, one starts with a pointer to the MVar
heap object. Then,

  1. Make sure that the MVar is evaluated, using standard lazy
     evaluation (follow indirections, enter thunks, ...).

     In the best case that's a check of a tag bit in the pointer.

  2. Read the pointer to the MVar# in the MVar.

  3. access the 'value' field of the StgMVar record, which
     results in another pointer to a heap object representing
     the actual data held by the MVar.

     (In reality the code has to check whether the MVar is full
     or not, and block if necessary. This is quite involved; see
     stg_takeMVarzh  in  ghc/rts/PrimOps.cmm)

That's two dereferences and some bookkeeping work.

In loops, the compiler will often unpack the MVar, so that you can
expect the first two steps to be performed just once.

Unpacking an MVar into a bigger record means that the pointer to the
MVar# will be stored in the record directly, rather than a pointer
to an MVar object that holds a pointer to the MVar#.

Note that MVar# itself cannot be unpacked -- the StgMVar record will
always be a separate heap object.

> I was asking the dual question:  if the MVar# exists in some data
> structure,  can that data structure still be garbage collected when there
> is a reference to the MVar#,  but not the data structure it is contained
> within.

Yes, because the data structure only contains a pointer to an MVar#
(StgMVar record) that will live on.

Best regards,

Bertram



More information about the Haskell-Cafe mailing list