No subject


Thu Jul 5 12:38:43 CEST 2012


data NLItem = NLItem {-# UNPACK #-} !Int
                     {-# UNPACK #-} !(MVar ())

All the {-# UNPACK #-} pragma does is embed the contents of a strict
single-constructor data declaration *directly* into the structure
containing it; it's like you declared NLItem as such:

    data NLItem = NLItem Word# (MVar# RealWorld ())

except that if you call functions that want an Int or MVar thunk, the
compiler will automatically re-box them in a new I#/MVar constructor.

Many copies of pointers to the same MVar# may exist; they are all
'identical' MVars; equality is defined as such:
    instance Eq (MVar a) where
            (MVar mvar1#) == (MVar mvar2#) = sameMVar# mvar1# mvar2#

where sameMVar# is a primitive that is probably just raw pointer equality.

Because of this, boxed MVars can be garbage collected without necessarily
garbage-collecting the MVar# it holds, if a live reference to that MVar#
still exists elsewhere.

  -- ryan

[1]
http://hackage.haskell.org/packages/archive/future/2.0.0/doc/html/src/Control-Concurrent-Future.html
[2]
http://hackage.haskell.org/packages/archive/named-lock/0.1/doc/html/src/Control-Concurrent-NamedLock.html
[3]
http://www.haskell.org/ghc/docs/7.4.1/html/libraries/base/src/GHC-MVar.html#MVar

On Mon, Jul 30, 2012 at 9:25 PM, Leon Smith <leon.p.smith at gmail.com> wrote:

> I admit I don't know exactly how MVars are implemented,  but given that
> they can be aliased and have indefinite extent,   I would think that they
> look something vaguely like a  cdatatype ** var,  basically a pointer to an
> MVar (which is itself a pointer,  modulo some other things such as a thread
> queue.)
>
> And,  I would think that "unpacking" such an structure would basically be
> eliminating one layer of indirection,  so it would then look vague like a
> cdatatype * var.    But again,  given aliasing and indefinite extent, this
> would seem to be a difficult thing to do.
>
> Actually this isn't too difficult if an MVar only exists in a single
> unpacked structure:   other references to the MVar can simply be pointers
> into the structure.   But the case where an MVar is unpacked into two
> different structures suggests that,  at least in some cases,  an "unpacked"
> MVar is still a cdatatype ** var;
>
> So, is my understanding more or less correct?  Does anybody have a good,
> succinct explanation of how MVars are implemented,  and how they are
> unpacked?
>
> One final question,   assuming that unpacking an MVar really does
> eliminate a layer of indirection,  and that other references to that MVar
> are simply pointers into a larger structure,   what happens to that larger
> structure when there are no more references to it (but still some
> references to the MVar?)    Given the complications that must arise out of
> a doubly "unpacked" MVar,  I'm going to guess that the larger structure
> does get garbage collected in this case,  and that the MVar becomes
> dislodged from this structure.   Would that MVar then be placed directly
> inside another unpacked reference, if one is available?
>
> Best,
> Leon
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
>

--e89a8f23494bda1bb604c6191d44
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

I&#39;m not sure I totally understand your question about &#39;unpacking&#3=
9; an MVar, but I&#39;m going to assume you mean data structures that use t=
he {-# UNPACK #-} pragma, like in Control.Concurrent.Future [1] and Control=
.Concurrent.NamedLock [2].<br>
<br>Here is how MVar is defined in GHC [3]:<br>=A0=A0=A0 data MVar a =3D MV=
ar (MVar# RealWorld a)<br><br>A &quot;MVar# s a&quot; is an unboxed pointer=
 to a structure understood by the GHC runtime.<br><br>So yes, you can imagi=
ne a MVar as a pointer-to-pointer.=A0 The structure it points at likely has=
 another pointer to the embedded boxed &quot;a&quot;, so it may even be poi=
nter-to-pointer-to-pointer.<br>
<br>The MVar data structure exists to allow laziness; for example<br>
<br>
=A0=A0 let x =3D unsafePerformIO (newMVar ()) in ()<br>
<br>
is likely to not allocate an MVar#, just a thunk that would create an=20
MVar if it was evaluated.=A0 Unboxed objects (represented by convetion=20
with # in GHC), on the other hand, are strict, so if you have an MVar#=20
RealWorld (), you know it points to a valid MVar#.<br><br>From [2] we have<=
br>data NLItem =3D NLItem {-# UNPACK #-} !Int<br>=A0=A0=A0=A0=A0=A0=A0=A0=
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 {-# UNPACK #-} !(MVar ())<br><br>All t=
he {-# UNPACK #-} pragma does is embed the contents of a strict single-cons=
tructor data declaration *directly* into the structure containing it; it&#3=
9;s like you declared NLItem as such:<br>
<br>=A0=A0=A0 data NLItem =3D NLItem Word# (MVar# RealWorld ())<br><br>exce=
pt that if you call functions that want an Int or MVar thunk, the compiler =
will automatically re-box them in a new I#/MVar constructor.<br><br>Many co=
pies of pointers to the same MVar# may exist; they are all &#39;identical&#=
39; MVars; equality is defined as such:<br>
=A0=A0=A0 instance Eq (MVar a) where<br>=A0 =A0=A0 =A0=A0=A0=A0=A0=A0 (MVar=
 mvar1#) =3D=3D (MVar mvar2#) =3D sameMVar# mvar1# mvar2#<br><br>where same=
MVar# is a primitive that is probably just raw pointer equality.<br><br>Bec=
ause of this, boxed MVars can be garbage collected without necessarily garb=
age-collecting the MVar# it holds, if a live reference to that MVar# still =
exists elsewhere.<br>
<br>=A0 -- ryan<br><br>[1] <a href=3D"http://hackage.haskell.org/packages/a=
rchive/future/2.0.0/doc/html/src/Control-Concurrent-Future.html">http://hac=
kage.haskell.org/packages/archive/future/2.0.0/doc/html/src/Control-Concurr=
ent-Future.html</a><br>
[2] <a href=3D"http://hackage.haskell.org/packages/archive/named-lock/0.1/d=
oc/html/src/Control-Concurrent-NamedLock.html">http://hackage.haskell.org/p=
ackages/archive/named-lock/0.1/doc/html/src/Control-Concurrent-NamedLock.ht=
ml</a><br>
[3] <a href=3D"http://www.haskell.org/ghc/docs/7.4.1/html/libraries/base/sr=
c/GHC-MVar.html#MVar">http://www.haskell.org/ghc/docs/7.4.1/html/libraries/=
base/src/GHC-MVar.html#MVar</a><br><br><div class=3D"gmail_quote">On Mon, J=
ul 30, 2012 at 9:25 PM, Leon Smith <span dir=3D"ltr">&lt;<a href=3D"mailto:=
leon.p.smith at gmail.com" target=3D"_blank">leon.p.smith at gmail.com</a>&gt;</s=
pan> wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div>I admit I don&#39;t know exactly how MV=
ars are implemented, =A0but given that they can be aliased and have indefin=
ite extent, =A0 I would think that they look something vaguely like a =A0cd=
atatype ** var, =A0basically a pointer to an MVar (which is itself a pointe=
r, =A0modulo some other things such as a thread queue.)</div>

<div><br></div><div>And, =A0I would think that &quot;unpacking&quot; such a=
n structure would basically be eliminating one layer of indirection, =A0so =
it would then look vague like a cdatatype * var. =A0 =A0But again, =A0given=
 aliasing and indefinite extent, this would seem to be a difficult thing to=
 do.</div>

<div><br></div><div>Actually this isn&#39;t too difficult if an MVar only e=
xists in a single unpacked structure: =A0 other references to the MVar can =
simply be pointers into the structure. =A0 But the case where an MVar is un=
packed into two different structures suggests that, =A0at least in some cas=
es, =A0an &quot;unpacked&quot; MVar is still a cdatatype ** var;</div>

<div><br></div><div>So, is my understanding more or less correct? =A0Does a=
nybody have a good, succinct explanation of how MVars are implemented, =A0a=
nd how they are unpacked?</div><div><br></div><div>One final question, =A0 =
assuming that unpacking an MVar really does eliminate a layer of indirectio=
n, =A0and that other references to that MVar are simply pointers into a lar=
ger structure, =A0 what happens to that larger structure when there are no =
more references to it (but still some references to the MVar?) =A0 =A0Given=
 the complications that must arise out of a doubly &quot;unpacked&quot; MVa=
r, =A0I&#39;m going to guess that the larger structure does get garbage col=
lected in this case, =A0and that the MVar becomes dislodged from this struc=
ture. =A0 Would that MVar then be placed directly inside another unpacked r=
eference, if one is available?</div>

<div><br></div><div>Best,</div><div>Leon</div>
<br>_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href=3D"mailto:Haskell-Cafe at haskell.org">Haskell-Cafe at haskell.org</a><br=
>
<a href=3D"http://www.haskell.org/mailman/listinfo/haskell-cafe" target=3D"=
_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
<br></blockquote></div><br>

--e89a8f23494bda1bb604c6191d44--



More information about the Haskell-Cafe mailing list