<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'>Also, a compiler is free to reorder this stuff as well.<br>If it can see the body of the function and inline it.<br><br><br>Without an explicit lock/fence/barrier of some kind, including a call to a function that the compiler cannot see the body of, the compiler can reorder.<br>Our compiler doesn't see far, so that helps.<br>But that is an implementation detail of our compiler.<br><br><br>The C backend will make "WPO" / "LTCG" / "LTO" sort of more viable..and the compiler will then see more.<br>(all names for the same thing -- whole program optimization, link time code generation, link time optimization)<br><br><br> - Jay<br><br><div><div id="SkyDrivePlaceholder"></div><hr id="stopSpelling">From: jay.krell@cornell.edu<br>To: mika@async.caltech.edu<br>CC: m3devel@elegosoft.com<br>Subject: RE: [M3devel] race conditions in lock-free code...<br>Date: Mon, 27 Aug 2012 08:55:09 +0000<br><br>

<style><!--
.ExternalClass .ecxhmmessage P
{padding:0px;}
.ExternalClass body.ecxhmmessage
{font-size:12pt;font-family:Calibri;}

--></style>
<div dir="ltr">Sorry, right, it is about cache not processor.<br>A uniprocessor system has no race.<br>Uniprocessor systems barely exist any longer.<br>I wouldn't put this reordering past any processor, including x86. But I don't know.<br>It is unlikely this is a/the problem with pthreads, but I don't know.<br><br>I know at least one major problem with pthreads was fixed.<br>I haven't been looking at it.<br><br>I was meaning to check if the pthread bug that was fixed applied to Win32.<br><br>I'm deep in a C backend right now..really really hoping to pull it off...<br><br> - Jay<br><br><br><div><div id="ecxSkyDrivePlaceholder"></div>> To: jay.krell@cornell.edu<br>> Date: Mon, 27 Aug 2012 00:17:44 -0700<br>> From: mika@async.caltech.edu<br>> CC: m3devel@elegosoft.com<br>> Subject: Re: [M3devel] race conditions in lock-free code...<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>&nbsp=3D3B VAR buf: ARRAY [0..0] OF CHAR=3D3B<br>&nbsp=3D=<br>> >3B BEGIN<br>=3D<br>> >> >>&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B IF fromCharCache [c] =3D3D NIL THEN<br>&=<br>> >nbsp=3D3B&nbsp=3D<br>> >> >>=3D3B&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B buf [0] :=3D3D c=3D3B<br>&nbsp=3D3B=<br>> >&nbsp=3D3B&nbsp=3D3B&n=3D<br>> >> >>bsp=3D3B&nbsp=3D3B fromCharCache[c] :=3D3D Text8.New (buf)=3D3B<br>&nbs=<br>> >p=3D3B&nbsp=3D3B=3D<br>> >> >>&nbsp=3D3B END=3D3B<br>&nbsp=3D3B&nbsp=3D3B&nbsp=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>> >> >>&nbsp=3D3B VAR buf: ARRAY [0..0] OF CHAR=3D3B<br>=3D0A=3D<br>> >> >>&nbsp=3D3B BEGIN<br>=3D0A=3D<br>> >> >>&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B IF fromCharCache [c] =3D3D NIL THEN<br>=<br>> >=3D0A=3D<br>> >> >>&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B buf [0] :=3D3D c=3D3=<br>> >B<br>=3D0A=3D<br>> >> >>&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B WITH a =3D3D Text8.N=<br>> >ew (buf) DO<br>&=3D<br>> >> >>nbsp=3D3B&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B M=<br>> >emoryBarrier()=3D3B<=3D<br>> >> >>br>&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B&nbsp=3D=<br>> >3B fromCharCache[c=3D<br>> >> >>] :=3D3D a=3D3B<br>&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B END=3D3B<br=<br>> >>=3D0A=3D<br>> >> >>&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B END=3D3B<br>=3D0A=3D<br>> >> >>&nbsp=3D3B&nbsp=3D3B&nbsp=3D3B RETURN fromCharCache [c]<br>=3D0A=3D<br>> >> >>&nbsp=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>&nbsp=3B- Jay<br><br><br><div><div id=3D"Sk=<br>> >yDrivePlaceholder"></div>&gt=3B To: jay.krell@cornell.edu=3B m3devel@elegos=<br>> >oft.com=3B mika@async.caltech.edu<br>&gt=3B Subject: Re: [M3devel] race con=<br>> >ditions in lock-free code...<br>&gt=3B Date: Sun=2C 26 Aug 2012 22:32:48 -0=<br>> >700<br>&gt=3B From: mika@async.caltech.edu<br>&gt=3B <br>&gt=3B Sorry=2C I =<br>> >can't seem to quote your message.<br>&gt=3B <br>&gt=3B You say that Text8.N=<br>> >ew's result can be assigned to fromCharCache[c]<br>&gt=3B before Text8.New =<br>> >is done running.  How is that possible?  Surely<br>&gt=3B Text8.New has to =<br>> >calculate its result before it can be assigned<br>&gt=3B anywhere.  Yes pos=<br>> >sibly FromChar allocates space for the result of<br>&gt=3B Text8.New but th=<br>> >e assignment of whatever appears in that space can't<br>&gt=3B happen until=<br>> > *after* Text8.New has run.  Unless you are saying that<br>&gt=3B the runni=<br>> >ng of Text8.New and FromChar are intertwined somehow..?<br>&gt=3B I know co=<br>> >mpilers do some odd things but that doesn't sound right...<br>&gt=3B <br>&g=<br>> >t=3B If Text8.New took fromCharCache[c] as a VAR parameter you might be<br>=<br>> >&gt=3B right=2C though.  But it doesn't...<br>&gt=3B <br>&gt=3B Am I missin=<br>> >g something?<br>&gt=3B <br>&gt=3B      Mika<br>&gt=3B <br>&gt=3B Mika Nystr=<br>> >om writes:<br>&gt=3B &gt=3B<br>&gt=3B &gt=3BYeah it's a race condition=2C i=<br>> >n theory.  But is it important?  If you get<br>&gt=3B &gt=3Bthe wrong copy=<br>> >=2C there will be two TEXTs representing one CHAR.  But no<br>&gt=3B &gt=3B=<br>> >one ever said FromChar was guaranteed to return the same pointer when<br>&g=<br>> >t=3B &gt=3Byou call it with the same CHAR...<br>&gt=3B &gt=3B<br>&gt=3B &gt=<br>> >=3B     Mika<br>&gt=3B &gt=3B<br>&gt=3B &gt=3BJay K writes:<br>&gt=3B &gt=<br>> >=3B&gt=3B--_5f23896e-68ee-44da-82dd-311cd8c58979_<br>&gt=3B &gt=3B&gt=3BCon=<br>> >tent-Type: text/plain=3B charset=3D"iso-8859-1"<br>&gt=3B &gt=3B&gt=3BConte=<br>> >nt-Transfer-Encoding: quoted-printable<br>&gt=3B &gt=3B&gt=3B<br>&gt=3B &gt=<br>> >=3B&gt=3BWe have race conditions=3D2C like this=3D2C m3core/src/Text.m3:<br=<br>> >>&gt=3B &gt=3B&gt=3B<br>&gt=3B &gt=3B&gt=3B<br>&gt=3B &gt=3B&gt=3BVAR fromC=<br>> >harCache :=3D3D ARRAY CHAR OF T {NIL=3D2C ..}=3D3B (* 1-char texts *)<br>&g=<br>> >t=3B &gt=3B&gt=3B<br>&gt=3B &gt=3B&gt=3B<br>&gt=3B &gt=3B&gt=3BPROCEDURE Fr=<br>> >omChar (c: CHAR): T =3D3D<br>&gt=3B &gt=3B&gt=3B  VAR buf: ARRAY [0..0] OF =<br>> >CHAR=3D3B<br>&gt=3B &gt=3B&gt=3B  BEGIN<br>&gt=3B &gt=3B&gt=3B    IF fromCh=<br>> >arCache [c] =3D3D NIL THEN<br>&gt=3B &gt=3B&gt=3B      buf [0] :=3D3D c=3D3=<br>> >B<br>&gt=3B &gt=3B&gt=3B      fromCharCache[c] :=3D3D Text8.New (buf)=3D3B<=<br>> >br>&gt=3B &gt=3B&gt=3B    END=3D3B<br>&gt=3B &gt=3B&gt=3B    RETURN fromCha=<br>> >rCache [c]<br>&gt=3B &gt=3B&gt=3B  END FromChar=3D3B<br>&gt=3B &gt=3B&gt=3B=<br>> ><br>&gt=3B &gt=3B&gt=3B<br>&gt=3B &gt=3B&gt=3BIt should be:<br>&gt=3B &gt=<br>> >=3B&gt=3B<br>&gt=3B &gt=3B&gt=3B<br>&gt=3B &gt=3B&gt=3BPROCEDURE FromChar (=<br>> >c: CHAR): T =3D3D<br>&gt=3B &gt=3B&gt=3B=3D0A=3D<br>&gt=3B &gt=3B&gt=3B  VA=<br>> >R buf: ARRAY [0..0] OF CHAR=3D3B<br>&gt=3B &gt=3B&gt=3B=3D0A=3D<br>&gt=3B &=<br>> >gt=3B&gt=3B  BEGIN<br>&gt=3B &gt=3B&gt=3B=3D0A=3D<br>&gt=3B &gt=3B&gt=3B   =<br>> > IF fromCharCache [c] =3D3D NIL THEN<br>&gt=3B &gt=3B&gt=3B=3D0A=3D<br>&gt=<br>> >=3B &gt=3B&gt=3B      buf [0] :=3D3D c=3D3B<br>&gt=3B &gt=3B&gt=3B=3D0A=3D<=<br>> >br>&gt=3B &gt=3B&gt=3B      WITH a =3D3D Text8.New (buf) DO<br>&gt=3B &gt=<br>> >=3B&gt=3B        MemoryBarrier()=3D3B<br>&gt=3B &gt=3B&gt=3B        fromCha=<br>> >rCache[c] :=3D3D a=3D3B<br>&gt=3B &gt=3B&gt=3B     END=3D3B<br>&gt=3B &gt=<br>> >=3B&gt=3B=3D0A=3D<br>&gt=3B &gt=3B&gt=3B    END=3D3B<br>&gt=3B &gt=3B&gt=3B=<br>> >=3D0A=3D<br>&gt=3B &gt=3B&gt=3B    RETURN fromCharCache [c]<br>&gt=3B &gt=<br>> >=3B&gt=3B=3D0A=3D<br>&gt=3B &gt=3B&gt=3B  END FromChar=3D3B<br>&gt=3B &gt=<br>> >=3B&gt=3B=3D0A=3D<br>&gt=3B &gt=3B&gt=3B<br>&gt=3B &gt=3B&gt=3B<br>&gt=3B &=<br>> >gt=3B&gt=3Bto ensure that all of Text8.New() finishes before the assignment=<br>> > to fromCha=3D<br>&gt=3B &gt=3B&gt=3BrCache[c] is made.<br>&gt=3B &gt=3B&gt=<br>> >=3B<br>&gt=3B &gt=3B&gt=3B<br>&gt=3B &gt=3B&gt=3BCan the compiler somehow c=<br>> >atch these?<br>&gt=3B &gt=3B&gt=3BI fear they are a small epidemic.<br>&gt=<br>> >=3B &gt=3B&gt=3BFor a long time people didn't realize where all the compile=<br>> >r and processor =3D<br>&gt=3B &gt=3B&gt=3Bcould reorder.<br>&gt=3B &gt=3B&g=<br>> >t=3B<br>&gt=3B &gt=3B&gt=3B<br>&gt=3B &gt=3B&gt=3BDo we have the right cons=<br>> >tructs by now to fix them?<br>&gt=3B &gt=3B&gt=3BI think we do.<br>&gt=3B &=<br>> >gt=3B&gt=3B<br>&gt=3B &gt=3B&gt=3B<br>&gt=3B &gt=3B&gt=3B - Jay<br>&gt=3B &=<br>> >gt=3B&gt=3B                                      =3D<br>&gt=3B &gt=3B&gt=3B<br>&gt=3B &gt=3B&gt=3B--_=<br>> >5f23896e-68ee-44da-82dd-311cd8c58979_<br>&gt=3B &gt=3B&gt=3BContent-Type: t=<br>> >ext/html=3B charset=3D"iso-8859-1"<br>&gt=3B &gt=3B&gt=3BContent-Transfer-E=<br>> >ncoding: quoted-printable<br>&gt=3B &gt=3B&gt=3B<br>&gt=3B &gt=3B&gt=3B&lt=<br>> >=3Bhtml&gt=3B<br>&gt=3B &gt=3B&gt=3B&lt=3Bhead&gt=3B<br>&gt=3B &gt=3B&gt=3B=<br>> >&lt=3Bstyle&gt=3B&lt=3B!--<br>&gt=3B &gt=3B&gt=3B.hmmessage P<br>&gt=3B &gt=<br>> >=3B&gt=3B{<br>&gt=3B &gt=3B&gt=3Bmargin:0px=3D3B<br>&gt=3B &gt=3B&gt=3Bpadd=<br>> >ing:0px<br>&gt=3B &gt=3B&gt=3B}<br>&gt=3B &gt=3B&gt=3Bbody.hmmessage<br>&gt=<br>> >=3B &gt=3B&gt=3B{<br>&gt=3B &gt=3B&gt=3Bfont-size: 12pt=3D3B<br>&gt=3B &gt=<br>> >=3B&gt=3Bfont-family:Calibri<br>&gt=3B &gt=3B&gt=3B}<br>&gt=3B &gt=3B&gt=3B=<br>> >--&gt=3B&lt=3B/style&gt=3B&lt=3B/head&gt=3B<br>&gt=3B &gt=3B&gt=3B&lt=3Bbod=<br>> >y class=3D3D'hmmessage'&gt=3B&lt=3Bdiv dir=3D3D'ltr'&gt=3BWe have race cond=<br>> >itions=3D2C like =3D<br>&gt=3B &gt=3B&gt=3Bthis=3D2C m3core/src/Text.m3:&lt=<br>> >=3Bbr&gt=3B&lt=3Bbr&gt=3B&lt=3Bbr&gt=3BVAR fromCharCache :=3D3D ARRAY CHAR =<br>> >OF=3D<br>&gt=3B &gt=3B&gt=3B T {NIL=3D2C ..}=3D3B (* 1-char texts *)&lt=3Bb=<br>> >r&gt=3B&lt=3Bbr&gt=3B&lt=3Bbr&gt=3BPROCEDURE FromChar (c: CHAR=3D<br>&gt=3B=<br>> > &gt=3B&gt=3B): T =3D3D&lt=3Bbr&gt=3B&amp=3Bnbsp=3D3B VAR buf: ARRAY [0..0]=<br>> > OF CHAR=3D3B&lt=3Bbr&gt=3B&amp=3Bnbsp=3D3B BEGIN&lt=3Bbr&gt=3B=3D<br>&gt=<br>> >=3B &gt=3B&gt=3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B IF fromCha=<br>> >rCache [c] =3D3D NIL THEN&lt=3Bbr&gt=3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D<br>&g=<br>> >t=3B &gt=3B&gt=3B=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B buf =<br>> >[0] :=3D3D c=3D3B&lt=3Bbr&gt=3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=<br>> >=3D3B&amp=3Bn=3D<br>&gt=3B &gt=3B&gt=3Bbsp=3D3B&amp=3Bnbsp=3D3B fromCharCac=<br>> >he[c] :=3D3D Text8.New (buf)=3D3B&lt=3Bbr&gt=3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=<br>> >=3D3B=3D<br>&gt=3B &gt=3B&gt=3B&amp=3Bnbsp=3D3B END=3D3B&lt=3Bbr&gt=3B&amp=<br>> >=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B RETURN fromCharCache [c]&lt=3B=<br>> >br&gt=3B&amp=3Bnb=3D<br>&gt=3B &gt=3B&gt=3Bsp=3D3B END FromChar=3D3B&lt=3Bb=<br>> >r&gt=3B&lt=3Bbr&gt=3B&lt=3Bbr&gt=3BIt should be:&lt=3Bbr&gt=3B&lt=3Bbr&gt=<br>> >=3B&lt=3Bbr&gt=3BPROCEDURE FromCha=3D<br>&gt=3B &gt=3B&gt=3Br (c: CHAR): T =<br>> >=3D3D&lt=3Bbr&gt=3B=3D0A=3D<br>&gt=3B &gt=3B&gt=3B&amp=3Bnbsp=3D3B VAR buf:=<br>> > ARRAY [0..0] OF CHAR=3D3B&lt=3Bbr&gt=3B=3D0A=3D<br>&gt=3B &gt=3B&gt=3B&amp=<br>> >=3Bnbsp=3D3B BEGIN&lt=3Bbr&gt=3B=3D0A=3D<br>&gt=3B &gt=3B&gt=3B&amp=3Bnbsp=<br>> >=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B IF fromCharCache [c] =3D3D NIL THEN&l=<br>> >t=3Bbr&gt=3B=3D0A=3D<br>&gt=3B &gt=3B&gt=3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B=<br>> >&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B buf [0] :=3D3D c=3D3B&lt=<br>> >=3Bbr&gt=3B=3D0A=3D<br>&gt=3B &gt=3B&gt=3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&=<br>> >amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B WITH a =3D3D Text8.New (buf=<br>> >) DO&lt=3Bbr&gt=3B&amp=3B=3D<br>&gt=3B &gt=3B&gt=3Bnbsp=3D3B&amp=3Bnbsp=3D3=<br>> >B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbs=<br>> >p=3D3B MemoryBarrier()=3D3B&lt=3B=3D<br>&gt=3B &gt=3B&gt=3Bbr&gt=3B&amp=3Bn=<br>> >bsp=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&am=<br>> >p=3Bnbsp=3D3B&amp=3Bnbsp=3D3B fromCharCache[c=3D<br>&gt=3B &gt=3B&gt=3B] :=<br>> >=3D3D a=3D3B&lt=3Bbr&gt=3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&=<br>> >amp=3Bnbsp=3D3B END=3D3B&lt=3Bbr&gt=3B=3D0A=3D<br>&gt=3B &gt=3B&gt=3B&amp=<br>> >=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B END=3D3B&lt=3Bbr&gt=3B=3D0A=3D=<br>> ><br>&gt=3B &gt=3B&gt=3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B&amp=3Bnbsp=3D3B RET=<br>> >URN fromCharCache [c]&lt=3Bbr&gt=3B=3D0A=3D<br>&gt=3B &gt=3B&gt=3B&amp=3Bnb=<br>> >sp=3D3B END FromChar=3D3B&lt=3Bbr&gt=3B=3D0A=3D<br>&gt=3B &gt=3B&gt=3B&lt=<br>> >=3Bbr&gt=3B&lt=3Bbr&gt=3Bto ensure that all of Text8.New() finishes before =<br>> >the assignment to=3D<br>&gt=3B &gt=3B&gt=3B fromCharCache[c] is made.&lt=3B=<br>> >br&gt=3B&lt=3Bbr&gt=3B&lt=3Bbr&gt=3BCan the compiler somehow catch these?=<br>> >=3D<br>&gt=3B &gt=3B&gt=3B&lt=3Bbr&gt=3BI fear they are a small epidemic.&l=<br>> >t=3Bbr&gt=3BFor a long time people didn't real=3D<br>&gt=3B &gt=3B&gt=3Bize=<br>> > where all the compiler and processor could reorder.&lt=3Bbr&gt=3B&lt=3Bbr&=<br>> >gt=3B&lt=3Bbr&gt=3BDo we ha=3D<br>&gt=3B &gt=3B&gt=3Bve the right construct=<br>> >s by now to fix them?&lt=3Bbr&gt=3BI think we do.&lt=3Bbr&gt=3B&lt=3Bbr&gt=<br>> >=3B&lt=3Bbr&gt=3B -=3D<br>&gt=3B &gt=3B&gt=3B Jay&lt=3Bbr&gt=3B                                      =<br>> >&lt=3B/div&gt=3B&lt=3B/body&gt=3B<br>&gt=3B &gt=3B&gt=3B&lt=3B/html&gt=3B=<br>> >=3D<br>&gt=3B &gt=3B&gt=3B<br>&gt=3B &gt=3B&gt=3B--_5f23896e-68ee-44da-82dd=<br>> >-311cd8c58979_--<br></div>                                    </div></body><br>> ></html>=<br>> ><br>> >--_86f22d85-5540-4565-bf73-232aaafdc94b_--<br></div>                                        </div></div>                                        </div></body>
</html>