<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 12pt;
font-family:Calibri
}
--></style></head>
<body class='hmmessage'><div dir='ltr'>It is NOT benign.<br>The global can be written before the initialization of what it points to is done.<br>The result is wrong.<br><br><br>It IS benign if multiple threads go and allocate separate multiple initialized TEXTs.<br>That's not the problem.<br><br><br> - Jay<br><br><br><div><div id="SkyDrivePlaceholder"></div>> CC: jay.krell@cornell.edu; m3devel@elegosoft.com<br>> From: hosking@cs.purdue.edu<br>> Subject: Re: [M3devel] race conditions in lock-free code...<br>> Date: Mon, 27 Aug 2012 09:27:38 -0400<br>> To: mika@async.caltech.edu<br>> <br>> So why is this anything other than benign? It's a cache and there's no problem if different threads get different texts. Don't cripple performance unnecessarily. The collector will reclaim any unreachable text.<br>> <br>> Sent from my iPad<br>> <br>> On Aug 27, 2012, at 3:17 AM, Mika Nystrom <mika@async.caltech.edu> wrote:<br>> <br>> > Oh I see now.<br>> > <br>> > It's not that the processor reorders in any tricky way. It is that the<br>> > write performed by Text8.New could be sitting around processor 1's cache<br>> > indefinitely without actually getting written back to main memory.<br>> > Processor 2 might see the new pointer, but when reading the memory pointed<br>> > to, would get uninitialized memory. I think this can happen on Alpha but<br>> > maybe not X86 (without further reorderings anyhow)?<br>> > <br>> > Any chance any of the pthreads bugs could be of this nature? How are the<br>> > pthreads doing? I gathered some bugs were fixed but I haven't tried the<br>> > system for a while.<br>> > <br>> > Mika<br>> > <br>> > <br>> > Jay K writes:<br>> >> --_86f22d85-5540-4565-bf73-232aaafdc94b_<br>> >> Content-Type: text/plain; charset="iso-8859-1"<br>> >> Content-Transfer-Encoding: quoted-printable<br>> >> <br>> >> The processor can reorder. Across call/ret at least in general.<br>> >> <br>> >> <br>> >> The compiler can also reorder=2C if you have whole-program-optimization=2C =<br>> >> link-time-code-gen (Microsoft "LTCG")=2C link-time-optimization (gcc "LTO")=<br>> >> . (We don't=2C but real world systems certainly do.)<br>> >> <br>> >> <br>> >> - Jay<br>> >> <br>> >> <br>> >>> To: jay.krell@cornell.edu=3B m3devel@elegosoft.com=3B mika@async.caltech.=<br>> >> edu<br>> >>> Subject: Re: [M3devel] race conditions in lock-free code...<br>> >>> Date: Sun=2C 26 Aug 2012 22:32:48 -0700<br>> >>> From: mika@async.caltech.edu<br>> >>> =20<br>> >>> Sorry=2C I can't seem to quote your message.<br>> >>> =20<br>> >>> You say that Text8.New's result can be assigned to fromCharCache[c]<br>> >>> before Text8.New is done running. How is that possible? Surely<br>> >>> Text8.New has to calculate its result before it can be assigned<br>> >>> anywhere. Yes possibly FromChar allocates space for the result of<br>> >>> Text8.New but the assignment of whatever appears in that space can't<br>> >>> happen until *after* Text8.New has run. Unless you are saying that<br>> >>> the running of Text8.New and FromChar are intertwined somehow..?<br>> >>> I know compilers do some odd things but that doesn't sound right...<br>> >>> =20<br>> >>> If Text8.New took fromCharCache[c] as a VAR parameter you might be<br>> >>> right=2C though. But it doesn't...<br>> >>> =20<br>> >>> Am I missing something?<br>> >>> =20<br>> >>> Mika<br>> >>> =20<br>> >>> Mika Nystrom writes:<br>> >>>> <br>> >>>> Yeah it's a race condition=2C in theory. But is it important? If you g=<br>> >> et<br>> >>>> the wrong copy=2C there will be two TEXTs representing one CHAR. But no<br>> >>>> one ever said FromChar was guaranteed to return the same pointer when<br>> >>>> you call it with the same CHAR...<br>> >>>> <br>> >>>> Mika<br>> >>>> <br>> >>>> Jay K writes:<br>> >>>>> --_5f23896e-68ee-44da-82dd-311cd8c58979_<br>> >>>>> Content-Type: text/plain=3B charset=3D"iso-8859-1"<br>> >>>>> Content-Transfer-Encoding: quoted-printable<br>> >>>>> <br>> >>>>> We have race conditions=3D2C like this=3D2C m3core/src/Text.m3:<br>> >>>>> <br>> >>>>> <br>> >>>>> VAR fromCharCache :=3D3D ARRAY CHAR OF T {NIL=3D2C ..}=3D3B (* 1-char t=<br>> >> exts *)<br>> >>>>> <br>> >>>>> <br>> >>>>> PROCEDURE FromChar (c: CHAR): T =3D3D<br>> >>>>> VAR buf: ARRAY [0..0] OF CHAR=3D3B<br>> >>>>> BEGIN<br>> >>>>> IF fromCharCache [c] =3D3D NIL THEN<br>> >>>>> buf [0] :=3D3D c=3D3B<br>> >>>>> fromCharCache[c] :=3D3D Text8.New (buf)=3D3B<br>> >>>>> END=3D3B<br>> >>>>> RETURN fromCharCache [c]<br>> >>>>> END FromChar=3D3B<br>> >>>>> <br>> >>>>> <br>> >>>>> It should be:<br>> >>>>> <br>> >>>>> <br>> >>>>> PROCEDURE FromChar (c: CHAR): T =3D3D<br>> >>>>> =3D0A=3D<br>> >>>>> VAR buf: ARRAY [0..0] OF CHAR=3D3B<br>> >>>>> =3D0A=3D<br>> >>>>> BEGIN<br>> >>>>> =3D0A=3D<br>> >>>>> IF fromCharCache [c] =3D3D NIL THEN<br>> >>>>> =3D0A=3D<br>> >>>>> buf [0] :=3D3D c=3D3B<br>> >>>>> =3D0A=3D<br>> >>>>> WITH a =3D3D Text8.New (buf) DO<br>> >>>>> MemoryBarrier()=3D3B<br>> >>>>> fromCharCache[c] :=3D3D a=3D3B<br>> >>>>> END=3D3B<br>> >>>>> =3D0A=3D<br>> >>>>> END=3D3B<br>> >>>>> =3D0A=3D<br>> >>>>> RETURN fromCharCache [c]<br>> >>>>> =3D0A=3D<br>> >>>>> END FromChar=3D3B<br>> >>>>> =3D0A=3D<br>> >>>>> <br>> >>>>> <br>> >>>>> to ensure that all of Text8.New() finishes before the assignment to fro=<br>> >> mCha=3D<br>> >>>>> rCache[c] is made.<br>> >>>>> <br>> >>>>> <br>> >>>>> Can the compiler somehow catch these?<br>> >>>>> I fear they are a small epidemic.<br>> >>>>> For a long time people didn't realize where all the compiler and proces=<br>> >> sor =3D<br>> >>>>> could reorder.<br>> >>>>> <br>> >>>>> <br>> >>>>> Do we have the right constructs by now to fix them?<br>> >>>>> I think we do.<br>> >>>>> <br>> >>>>> <br>> >>>>> - Jay<br>> >>>>> =3D<br>> >>>>> <br>> >>>>> --_5f23896e-68ee-44da-82dd-311cd8c58979_<br>> >>>>> Content-Type: text/html=3B charset=3D"iso-8859-1"<br>> >>>>> Content-Transfer-Encoding: quoted-printable<br>> >>>>> <br>> >>>>> <html><br>> >>>>> <head><br>> >>>>> <style><!--<br>> >>>>> .hmmessage P<br>> >>>>> {<br>> >>>>> margin:0px=3D3B<br>> >>>>> padding:0px<br>> >>>>> }<br>> >>>>> body.hmmessage<br>> >>>>> {<br>> >>>>> font-size: 12pt=3D3B<br>> >>>>> font-family:Calibri<br>> >>>>> }<br>> >>>>> --></style></head><br>> >>>>> <body class=3D3D'hmmessage'><div dir=3D3D'ltr'>We have race conditions=<br>> >> =3D2C like =3D<br>> >>>>> this=3D2C m3core/src/Text.m3:<br><br><br>VAR fromCharCache :=3D3D ARRAY=<br>> >> CHAR OF=3D<br>> >>>>> T {NIL=3D2C ..}=3D3B (* 1-char texts *)<br><br><br>PROCEDURE FromChar =<br>> >> (c: CHAR=3D<br>> >>>>> ): T =3D3D<br> =3D3B VAR buf: ARRAY [0..0] OF CHAR=3D3B<br> =3D=<br>> >> 3B BEGIN<br>=3D<br>> >>>>>  =3D3B =3D3B =3D3B IF fromCharCache [c] =3D3D NIL THEN<br>&=<br>> >> nbsp=3D3B =3D<br>> >>>>> =3D3B =3D3B =3D3B =3D3B buf [0] :=3D3D c=3D3B<br> =3D3B=<br>> >>  =3D3B =3D3B&n=3D<br>> >>>>> bsp=3D3B =3D3B fromCharCache[c] :=3D3D Text8.New (buf)=3D3B<br>&nbs=<br>> >> p=3D3B =3D3B=3D<br>> >>>>>  =3D3B END=3D3B<br> =3D3B =3D3B =3D3B RETURN fromCharCa=<br>> >> che [c]<br>&nb=3D<br>> >>>>> sp=3D3B END FromChar=3D3B<br><br><br>It should be:<br><br><br>PROCEDURE=<br>> >> FromCha=3D<br>> >>>>> r (c: CHAR): T =3D3D<br>=3D0A=3D<br>> >>>>>  =3D3B VAR buf: ARRAY [0..0] OF CHAR=3D3B<br>=3D0A=3D<br>> >>>>>  =3D3B BEGIN<br>=3D0A=3D<br>> >>>>>  =3D3B =3D3B =3D3B IF fromCharCache [c] =3D3D NIL THEN<br>=<br>> >> =3D0A=3D<br>> >>>>>  =3D3B =3D3B =3D3B =3D3B =3D3B buf [0] :=3D3D c=3D3=<br>> >> B<br>=3D0A=3D<br>> >>>>>  =3D3B =3D3B =3D3B =3D3B =3D3B WITH a =3D3D Text8.N=<br>> >> ew (buf) DO<br>&=3D<br>> >>>>> nbsp=3D3B =3D3B =3D3B =3D3B =3D3B =3D3B =3D3B M=<br>> >> emoryBarrier()=3D3B<=3D<br>> >>>>> br> =3D3B =3D3B =3D3B =3D3B =3D3B =3D3B =3D=<br>> >> 3B fromCharCache[c=3D<br>> >>>>> ] :=3D3D a=3D3B<br> =3D3B =3D3B =3D3B =3D3B END=3D3B<br=<br>> >>> =3D0A=3D<br>> >>>>>  =3D3B =3D3B =3D3B END=3D3B<br>=3D0A=3D<br>> >>>>>  =3D3B =3D3B =3D3B RETURN fromCharCache [c]<br>=3D0A=3D<br>> >>>>>  =3D3B END FromChar=3D3B<br>=3D0A=3D<br>> >>>>> <br><br>to ensure that all of Text8.New() finishes before the assignmen=<br>> >> t to=3D<br>> >>>>> fromCharCache[c] is made.<br><br><br>Can the compiler somehow catch th=<br>> >> ese?=3D<br>> >>>>> <br>I fear they are a small epidemic.<br>For a long time people didn't =<br>> >> real=3D<br>> >>>>> ize where all the compiler and processor could reorder.<br><br><br>Do w=<br>> >> e ha=3D<br>> >>>>> ve the right constructs by now to fix them?<br>I think we do.<br><br><b=<br>> >> r> -=3D<br>> >>>>> Jay<br> </div></body><br>> >>>>> </html>=3D<br>> >>>>> <br>> >>>>> --_5f23896e-68ee-44da-82dd-311cd8c58979_--<br>> >> =<br>> >> <br>> >> --_86f22d85-5540-4565-bf73-232aaafdc94b_<br>> >> Content-Type: text/html; charset="iso-8859-1"<br>> >> Content-Transfer-Encoding: quoted-printable<br>> >> <br>> >> <html><br>> >> <head><br>> >> <style><!--<br>> >> .hmmessage P<br>> >> {<br>> >> margin:0px=3B<br>> >> padding:0px<br>> >> }<br>> >> body.hmmessage<br>> >> {<br>> >> font-size: 12pt=3B<br>> >> font-family:Calibri<br>> >> }<br>> >> --></style></head><br>> >> <body class=3D'hmmessage'><div dir=3D'ltr'>The processor can reorder. Acros=<br>> >> s call/ret at least in general.<br><br><br>The compiler can also reorder=2C=<br>> >> if you have whole-program-optimization=2C link-time-code-gen (Microsoft "L=<br>> >> TCG")=2C link-time-optimization (gcc "LTO"). (We don't=2C but real world sy=<br>> >> stems certainly do.)<br><br><br> =3B- Jay<br><br><br><div><div id=3D"Sk=<br>> >> yDrivePlaceholder"></div>>=3B To: jay.krell@cornell.edu=3B m3devel@elegos=<br>> >> oft.com=3B mika@async.caltech.edu<br>>=3B Subject: Re: [M3devel] race con=<br>> >> ditions in lock-free code...<br>>=3B Date: Sun=2C 26 Aug 2012 22:32:48 -0=<br>> >> 700<br>>=3B From: mika@async.caltech.edu<br>>=3B <br>>=3B Sorry=2C I =<br>> >> can't seem to quote your message.<br>>=3B <br>>=3B You say that Text8.N=<br>> >> ew's result can be assigned to fromCharCache[c]<br>>=3B before Text8.New =<br>> >> is done running. How is that possible? Surely<br>>=3B Text8.New has to =<br>> >> calculate its result before it can be assigned<br>>=3B anywhere. Yes pos=<br>> >> sibly FromChar allocates space for the result of<br>>=3B Text8.New but th=<br>> >> e assignment of whatever appears in that space can't<br>>=3B happen until=<br>> >> *after* Text8.New has run. Unless you are saying that<br>>=3B the runni=<br>> >> ng of Text8.New and FromChar are intertwined somehow..?<br>>=3B I know co=<br>> >> mpilers do some odd things but that doesn't sound right...<br>>=3B <br>&g=<br>> >> t=3B If Text8.New took fromCharCache[c] as a VAR parameter you might be<br>=<br>> >> >=3B right=2C though. But it doesn't...<br>>=3B <br>>=3B Am I missin=<br>> >> g something?<br>>=3B <br>>=3B Mika<br>>=3B <br>>=3B Mika Nystr=<br>> >> om writes:<br>>=3B >=3B<br>>=3B >=3BYeah it's a race condition=2C i=<br>> >> n theory. But is it important? If you get<br>>=3B >=3Bthe wrong copy=<br>> >> =2C there will be two TEXTs representing one CHAR. But no<br>>=3B >=3B=<br>> >> one ever said FromChar was guaranteed to return the same pointer when<br>&g=<br>> >> t=3B >=3Byou call it with the same CHAR...<br>>=3B >=3B<br>>=3B >=<br>> >> =3B Mika<br>>=3B >=3B<br>>=3B >=3BJay K writes:<br>>=3B >=<br>> >> =3B>=3B--_5f23896e-68ee-44da-82dd-311cd8c58979_<br>>=3B >=3B>=3BCon=<br>> >> tent-Type: text/plain=3B charset=3D"iso-8859-1"<br>>=3B >=3B>=3BConte=<br>> >> nt-Transfer-Encoding: quoted-printable<br>>=3B >=3B>=3B<br>>=3B >=<br>> >> =3B>=3BWe have race conditions=3D2C like this=3D2C m3core/src/Text.m3:<br=<br>> >>> >=3B >=3B>=3B<br>>=3B >=3B>=3B<br>>=3B >=3B>=3BVAR fromC=<br>> >> harCache :=3D3D ARRAY CHAR OF T {NIL=3D2C ..}=3D3B (* 1-char texts *)<br>&g=<br>> >> t=3B >=3B>=3B<br>>=3B >=3B>=3B<br>>=3B >=3B>=3BPROCEDURE Fr=<br>> >> omChar (c: CHAR): T =3D3D<br>>=3B >=3B>=3B VAR buf: ARRAY [0..0] OF =<br>> >> CHAR=3D3B<br>>=3B >=3B>=3B BEGIN<br>>=3B >=3B>=3B IF fromCh=<br>> >> arCache [c] =3D3D NIL THEN<br>>=3B >=3B>=3B buf [0] :=3D3D c=3D3=<br>> >> B<br>>=3B >=3B>=3B fromCharCache[c] :=3D3D Text8.New (buf)=3D3B<=<br>> >> br>>=3B >=3B>=3B END=3D3B<br>>=3B >=3B>=3B RETURN fromCha=<br>> >> rCache [c]<br>>=3B >=3B>=3B END FromChar=3D3B<br>>=3B >=3B>=3B=<br>> >> <br>>=3B >=3B>=3B<br>>=3B >=3B>=3BIt should be:<br>>=3B >=<br>> >> =3B>=3B<br>>=3B >=3B>=3B<br>>=3B >=3B>=3BPROCEDURE FromChar (=<br>> >> c: CHAR): T =3D3D<br>>=3B >=3B>=3B=3D0A=3D<br>>=3B >=3B>=3B VA=<br>> >> R buf: ARRAY [0..0] OF CHAR=3D3B<br>>=3B >=3B>=3B=3D0A=3D<br>>=3B &=<br>> >> gt=3B>=3B BEGIN<br>>=3B >=3B>=3B=3D0A=3D<br>>=3B >=3B>=3B =<br>> >> IF fromCharCache [c] =3D3D NIL THEN<br>>=3B >=3B>=3B=3D0A=3D<br>>=<br>> >> =3B >=3B>=3B buf [0] :=3D3D c=3D3B<br>>=3B >=3B>=3B=3D0A=3D<=<br>> >> br>>=3B >=3B>=3B WITH a =3D3D Text8.New (buf) DO<br>>=3B >=<br>> >> =3B>=3B MemoryBarrier()=3D3B<br>>=3B >=3B>=3B fromCha=<br>> >> rCache[c] :=3D3D a=3D3B<br>>=3B >=3B>=3B END=3D3B<br>>=3B >=<br>> >> =3B>=3B=3D0A=3D<br>>=3B >=3B>=3B END=3D3B<br>>=3B >=3B>=3B=<br>> >> =3D0A=3D<br>>=3B >=3B>=3B RETURN fromCharCache [c]<br>>=3B >=<br>> >> =3B>=3B=3D0A=3D<br>>=3B >=3B>=3B END FromChar=3D3B<br>>=3B >=<br>> >> =3B>=3B=3D0A=3D<br>>=3B >=3B>=3B<br>>=3B >=3B>=3B<br>>=3B &=<br>> >> gt=3B>=3Bto ensure that all of Text8.New() finishes before the assignment=<br>> >> to fromCha=3D<br>>=3B >=3B>=3BrCache[c] is made.<br>>=3B >=3B>=<br>> >> =3B<br>>=3B >=3B>=3B<br>>=3B >=3B>=3BCan the compiler somehow c=<br>> >> atch these?<br>>=3B >=3B>=3BI fear they are a small epidemic.<br>>=<br>> >> =3B >=3B>=3BFor a long time people didn't realize where all the compile=<br>> >> r and processor =3D<br>>=3B >=3B>=3Bcould reorder.<br>>=3B >=3B&g=<br>> >> t=3B<br>>=3B >=3B>=3B<br>>=3B >=3B>=3BDo we have the right cons=<br>> >> tructs by now to fix them?<br>>=3B >=3B>=3BI think we do.<br>>=3B &=<br>> >> gt=3B>=3B<br>>=3B >=3B>=3B<br>>=3B >=3B>=3B - Jay<br>>=3B &=<br>> >> gt=3B>=3B =3D<br>>=3B >=3B>=3B<br>>=3B >=3B>=3B--_=<br>> >> 5f23896e-68ee-44da-82dd-311cd8c58979_<br>>=3B >=3B>=3BContent-Type: t=<br>> >> ext/html=3B charset=3D"iso-8859-1"<br>>=3B >=3B>=3BContent-Transfer-E=<br>> >> ncoding: quoted-printable<br>>=3B >=3B>=3B<br>>=3B >=3B>=3B<=<br>> >> =3Bhtml>=3B<br>>=3B >=3B>=3B<=3Bhead>=3B<br>>=3B >=3B>=3B=<br>> >> <=3Bstyle>=3B<=3B!--<br>>=3B >=3B>=3B.hmmessage P<br>>=3B >=<br>> >> =3B>=3B{<br>>=3B >=3B>=3Bmargin:0px=3D3B<br>>=3B >=3B>=3Bpadd=<br>> >> ing:0px<br>>=3B >=3B>=3B}<br>>=3B >=3B>=3Bbody.hmmessage<br>>=<br>> >> =3B >=3B>=3B{<br>>=3B >=3B>=3Bfont-size: 12pt=3D3B<br>>=3B >=<br>> >> =3B>=3Bfont-family:Calibri<br>>=3B >=3B>=3B}<br>>=3B >=3B>=3B=<br>> >> -->=3B<=3B/style>=3B<=3B/head>=3B<br>>=3B >=3B>=3B<=3Bbod=<br>> >> y class=3D3D'hmmessage'>=3B<=3Bdiv dir=3D3D'ltr'>=3BWe have race cond=<br>> >> itions=3D2C like =3D<br>>=3B >=3B>=3Bthis=3D2C m3core/src/Text.m3:<=<br>> >> =3Bbr>=3B<=3Bbr>=3B<=3Bbr>=3BVAR fromCharCache :=3D3D ARRAY CHAR =<br>> >> OF=3D<br>>=3B >=3B>=3B T {NIL=3D2C ..}=3D3B (* 1-char texts *)<=3Bb=<br>> >> r>=3B<=3Bbr>=3B<=3Bbr>=3BPROCEDURE FromChar (c: CHAR=3D<br>>=3B=<br>> >> >=3B>=3B): T =3D3D<=3Bbr>=3B&=3Bnbsp=3D3B VAR buf: ARRAY [0..0]=<br>> >> OF CHAR=3D3B<=3Bbr>=3B&=3Bnbsp=3D3B BEGIN<=3Bbr>=3B=3D<br>>=<br>> >> =3B >=3B>=3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B IF fromCha=<br>> >> rCache [c] =3D3D NIL THEN<=3Bbr>=3B&=3Bnbsp=3D3B&=3Bnbsp=3D<br>&g=<br>> >> t=3B >=3B>=3B=3D3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B buf =<br>> >> [0] :=3D3D c=3D3B<=3Bbr>=3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B&=3Bnbsp=<br>> >> =3D3B&=3Bn=3D<br>>=3B >=3B>=3Bbsp=3D3B&=3Bnbsp=3D3B fromCharCac=<br>> >> he[c] :=3D3D Text8.New (buf)=3D3B<=3Bbr>=3B&=3Bnbsp=3D3B&=3Bnbsp=<br>> >> =3D3B=3D<br>>=3B >=3B>=3B&=3Bnbsp=3D3B END=3D3B<=3Bbr>=3B&=<br>> >> =3Bnbsp=3D3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B RETURN fromCharCache [c]<=3B=<br>> >> br>=3B&=3Bnb=3D<br>>=3B >=3B>=3Bsp=3D3B END FromChar=3D3B<=3Bb=<br>> >> r>=3B<=3Bbr>=3B<=3Bbr>=3BIt should be:<=3Bbr>=3B<=3Bbr>=<br>> >> =3B<=3Bbr>=3BPROCEDURE FromCha=3D<br>>=3B >=3B>=3Br (c: CHAR): T =<br>> >> =3D3D<=3Bbr>=3B=3D0A=3D<br>>=3B >=3B>=3B&=3Bnbsp=3D3B VAR buf:=<br>> >> ARRAY [0..0] OF CHAR=3D3B<=3Bbr>=3B=3D0A=3D<br>>=3B >=3B>=3B&=<br>> >> =3Bnbsp=3D3B BEGIN<=3Bbr>=3B=3D0A=3D<br>>=3B >=3B>=3B&=3Bnbsp=<br>> >> =3D3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B IF fromCharCache [c] =3D3D NIL THEN&l=<br>> >> t=3Bbr>=3B=3D0A=3D<br>>=3B >=3B>=3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B=<br>> >> &=3Bnbsp=3D3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B buf [0] :=3D3D c=3D3B<=<br>> >> =3Bbr>=3B=3D0A=3D<br>>=3B >=3B>=3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B&=<br>> >> amp=3Bnbsp=3D3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B WITH a =3D3D Text8.New (buf=<br>> >> ) DO<=3Bbr>=3B&=3B=3D<br>>=3B >=3B>=3Bnbsp=3D3B&=3Bnbsp=3D3=<br>> >> B&=3Bnbsp=3D3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B&=3Bnbs=<br>> >> p=3D3B MemoryBarrier()=3D3B<=3B=3D<br>>=3B >=3B>=3Bbr>=3B&=3Bn=<br>> >> bsp=3D3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B&am=<br>> >> p=3Bnbsp=3D3B&=3Bnbsp=3D3B fromCharCache[c=3D<br>>=3B >=3B>=3B] :=<br>> >> =3D3D a=3D3B<=3Bbr>=3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B&=<br>> >> amp=3Bnbsp=3D3B END=3D3B<=3Bbr>=3B=3D0A=3D<br>>=3B >=3B>=3B&=<br>> >> =3Bnbsp=3D3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B END=3D3B<=3Bbr>=3B=3D0A=3D=<br>> >> <br>>=3B >=3B>=3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B&=3Bnbsp=3D3B RET=<br>> >> URN fromCharCache [c]<=3Bbr>=3B=3D0A=3D<br>>=3B >=3B>=3B&=3Bnb=<br>> >> sp=3D3B END FromChar=3D3B<=3Bbr>=3B=3D0A=3D<br>>=3B >=3B>=3B<=<br>> >> =3Bbr>=3B<=3Bbr>=3Bto ensure that all of Text8.New() finishes before =<br>> >> the assignment to=3D<br>>=3B >=3B>=3B fromCharCache[c] is made.<=3B=<br>> >> br>=3B<=3Bbr>=3B<=3Bbr>=3BCan the compiler somehow catch these?=<br>> >> =3D<br>>=3B >=3B>=3B<=3Bbr>=3BI fear they are a small epidemic.&l=<br>> >> t=3Bbr>=3BFor a long time people didn't real=3D<br>>=3B >=3B>=3Bize=<br>> >> where all the compiler and processor could reorder.<=3Bbr>=3B<=3Bbr&=<br>> >> gt=3B<=3Bbr>=3BDo we ha=3D<br>>=3B >=3B>=3Bve the right construct=<br>> >> s by now to fix them?<=3Bbr>=3BI think we do.<=3Bbr>=3B<=3Bbr>=<br>> >> =3B<=3Bbr>=3B -=3D<br>>=3B >=3B>=3B Jay<=3Bbr>=3B =<br>> >> <=3B/div>=3B<=3B/body>=3B<br>>=3B >=3B>=3B<=3B/html>=3B=<br>> >> =3D<br>>=3B >=3B>=3B<br>>=3B >=3B>=3B--_5f23896e-68ee-44da-82dd=<br>> >> -311cd8c58979_--<br></div> </div></body><br>> >> </html>=<br>> >> <br>> >> --_86f22d85-5540-4565-bf73-232aaafdc94b_--<br></div> </div></body>
</html>