Re: Are there real use cases with the Java access modes?

Nathan Reynolds via Concurrency-interest <[email protected]> Tue, 27 Jul 2021 13:53:38 -0600
Newsgroups gmane.comp.java.jsr.166-concurrency
Message-ID <CALMUwcp3f6Xz9mb28T4PTLybcC3=SvHF7oQanVkX+bgfaEt8hA@mail.gmail.com>
--===============7346183974866000481==
Content-Type: multipart/alternative; boundary="0000000000008bb9f505c8203abd"

--0000000000008bb9f505c8203abd
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

 I brought up creating a PMD rule that traverses the call tree inside the
loop looking for the non-volatile field condition to change.  One problem
with such a rule is that it wouldn't know how to handle a reflected call or
to say Runnable.run().  In these cases, the PMD rule can ignore these
calls.  In other words, the rule will decide that the call does not change
the condition.

This could result in false positives.  To help the programmer, the PMD rule
can show in the message (and Eclipse tooltip) that the problem might be a
false positive.  The programmer can then decide if it is a false positive
or fix the problem.  These false positives are easily suppressed with a "//
NOPMD" comment or @SuppressWarnings("PMD.*RuleName*").

What percentage of loops have indeterminate calls?

I realize that a non-final method in a non-final class could be an
indeterminate call.  At runtime a new class can be introduced that
overrides the method and prevents the loop condition field from changing.
I consider this case very rare.  Most programs and servlets are
self-contained and all classes are known at build time.

On Tue, Jul 27, 2021 at 8:59 AM Gregg Wonderly via Concurrency-interest <
[email protected]> wrote:

>
>
> On Jul 26, 2021, at 11:46 PM, Alex Otenko <[email protected]>
> wrote:
>
> Well, you made a statement that the hoist of this kind never happens in C=
.
> It's not true. All I did is found a bizarre example where even worse thin=
gs
> happen.
>
>
> You are calling them worse. They are at least debuggable.  You can use cc
> -S to stare at the code generated and see that the loop disappears.
>
> I said this example was not the same because it=E2=80=99s a logic error t=
hat can
> be debugged to understand what is happening.  I'd take a C/C++ program an=
d
> compile it with -g to have symbol and line number information.  This allo=
ws
> you to debug this code. The optimizer disappears from view and the loop
> comes back.  What I stated about C++ specifically is that the loop contro=
l
> expression is not hoisted out of the loop and evaluated once, turning the
> loop into a while(true){} condition that never exits and which a debugger
> can never show you the problem because it=E2=80=99s not a logic or data r=
ace, it=E2=80=99s
> an optimization that invalidates the way the code is written.
>
> If the dev adds logging or other printing debugging, the JIT stops the
> hoist in many cases, and thus it looks like something is happening with t=
he
> =E2=80=9Ccompiler=E2=80=9D breaking the code, which it is.  But, the user=
 has no idea that
> =E2=80=98volatile=E2=80=99 is required unless they=E2=80=99ve had exposur=
e to the details around
> the whole set of optimizations with fences, cache lines and the like.   I
> am contesting that being a precursor to getting working code, plain and
> simple.  Why is understanding hardware ever a consideration for correct
> logic to operate?  Optimization yes, working code, I feel it=E2=80=99s re=
ally a
> detracting =E2=80=98feature=E2=80=99 of the JIT.
>
> Gregg
>
>
> On Mon, 26 Jul 2021, 23:27 Gregg Wonderly, <[email protected]> wrote:
>
>>
>>
>> > On Jul 26, 2021, at 2:06 AM, Alex Otenko via Concurrency-interest <
>> [email protected]> wrote:
>> >
>> > "Don't write the code like that" is what the others said about
>> while(!done), so maybe you can see the point they are making.
>> >
>> > As for this example - please take it as an example of code that may no=
t
>> behave as written.
>> >
>> > As to why it is written like that - well, it is derived from a more
>> elaborate mutually recursive case (with a bug).
>> >
>> > It is perfectly normal to state "zero is even", "x+1 is even, if x is
>> odd", and "x+1 is odd, if x is even". This is a recursive definition tha=
t
>> is derived from a recursive definition of natural numbers. It is not
>> complete, but you can't tell if you don't have the compiler that will te=
ll
>> you that.
>> >
>> > So you have:
>> >
>> > char odd(int x){return even(x-1);}
>> > char even(int x){return !x || odd(x-1);}
>> >
>> > Inline even into odd, do tail call optimization, and you end up with a
>> loop like that (ok, x--, not x++). Both of these steps is what modern
>> clang, gcc and llvm do
>>
>> Yes, but this is broken because you can only call even() on evens and
>> odd() on odds for it to work.  But the tail recursion resolution on a -O
>> compilation never loops and just results in a bogus =E2=80=981=E2=80=99 =
return for all
>> cases.  With -g, you get infinite recursion that crashes with a stack
>> explosion.  You can debug this and see what=E2=80=99s happening.
>>
>> I=E2=80=99m still completely focused on the fact that the hoist of the l=
oop
>> condition makes the code into an infinite loop that you can=E2=80=99t ob=
serve,
>> readily, why a value of done=3Dtrue doesn=E2=80=99t cause the loop to ex=
it.  What you
>> can observe in the value of done should cause the loop to exit.  It=E2=
=80=99s
>> subtly different in my consideration, but it looks like its a bug becaus=
e
>> you can=E2=80=99t see the code that is executing incorrectly.  With this=
 example
>> you show, you can put printf in even() and odd(), see the values of x, a=
nd
>> notice how you end up in odd() with x=3D=3D0 when you call even() with a=
n odd
>> value or odd() with an even value and thus the bug occurs.
>>
>> Gregg Wonderly
>>
>>
>>
>>
> _______________________________________________
> Concurrency-interest mailing list
> [email protected]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>

--0000000000008bb9f505c8203abd
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">
<div dir=3D"ltr"><div>I brought up creating a PMD rule that traverses the c=
all tree inside the loop looking for the non-volatile field condition to ch=
ange.=C2=A0 One problem with such a rule is that it wouldn&#39;t know how t=
o handle a reflected call or to say Runnable.run().=C2=A0 In these cases, t=
he PMD rule can ignore these calls.=C2=A0 In other words, the rule will dec=
ide that the call does not change the condition.<br></div><div><br></div><d=
iv>This could result in false positives.=C2=A0 To help the programmer, the =
PMD rule can show in the message (and Eclipse tooltip) that the problem mig=
ht be a false positive.=C2=A0 The programmer can then decide if it is a fal=
se positive or fix the problem.=C2=A0 These false positives are easily supp=
ressed with a &quot;// NOPMD&quot; comment or @SuppressWarnings(&quot;PMD.<=
i>RuleName</i>&quot;).</div><div><br></div><div>What percentage of loops ha=
ve indeterminate calls?</div><div><br></div><div>I realize that a non-final=
 method in a non-final class could be an indeterminate call.=C2=A0 At runti=
me a new class can be introduced that overrides the method and prevents the=
 loop condition field from changing.=C2=A0 I consider this case very rare.=
=C2=A0 Most programs and servlets are self-contained and all classes are kn=
own at build time.<br></div></div>

</div><br><div class=3D"gmail_quote"><div dir=3D"ltr" class=3D"gmail_attr">=
On Tue, Jul 27, 2021 at 8:59 AM Gregg Wonderly via Concurrency-interest &lt=
;<a href=3D"mailto:[email protected]">concurrency-interest=
@cs.oswego.edu</a>&gt; wrote:<br></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padd=
ing-left:1ex"><div style=3D"overflow-wrap: break-word;"><br><div><br><block=
quote type=3D"cite"><div>On Jul 26, 2021, at 11:46 PM, Alex Otenko &lt;<a h=
ref=3D"mailto:[email protected]" target=3D"_blank">oleksandr.otenk=
[email protected]</a>&gt; wrote:</div><br><div><div dir=3D"auto">Well, you made a=
 statement that the hoist of this kind never happens in C. It&#39;s not tru=
e. All I did is found a bizarre example where even worse things happen.</di=
v></div></blockquote><div><br></div><div>You are calling them worse. They a=
re at least debuggable.=C2=A0 You can use cc -S to stare at the code genera=
ted and see that the loop disappears.</div><div><br></div><div>I said this =
example was not the same because it=E2=80=99s a logic error that can be deb=
ugged to understand what is happening.=C2=A0 I&#39;d take a C/C++ program a=
nd compile it with -g to have symbol and line number information.=C2=A0 Thi=
s allows you to debug this code. The optimizer disappears from view and the=
 loop comes back.=C2=A0 What I stated about C++ specifically is that the lo=
op control expression is not hoisted out of the loop and evaluated once, tu=
rning the loop into a while(true){} condition that never exits and which a =
debugger can never show you the problem because it=E2=80=99s not a logic or=
 data race, it=E2=80=99s an optimization that invalidates the way the code =
is written.</div><div><br></div><div>If the dev adds logging or other print=
ing debugging, the JIT stops the hoist in many cases, and thus it looks lik=
e something is happening with the =E2=80=9Ccompiler=E2=80=9D breaking the c=
ode, which it is.=C2=A0 But, the user has no idea that =E2=80=98volatile=E2=
=80=99 is required unless they=E2=80=99ve had exposure to the details aroun=
d the whole set of optimizations with fences, cache lines and the like. =C2=
=A0 I am contesting that being a precursor to getting working code, plain a=
nd simple.=C2=A0 Why is understanding hardware ever a consideration for cor=
rect logic to operate?=C2=A0 Optimization yes, working code, I feel it=E2=
=80=99s really a detracting =E2=80=98feature=E2=80=99 of the JIT.</div><div=
><br></div><div>Gregg</div><div><br></div><blockquote type=3D"cite"><div><b=
r><div class=3D"gmail_quote"><div dir=3D"ltr" class=3D"gmail_attr">On Mon, =
26 Jul 2021, 23:27 Gregg Wonderly, &lt;<a href=3D"mailto:[email protected]" tar=
get=3D"_blank">[email protected]</a>&gt; wrote:<br></div><blockquote class=3D"g=
mail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204=
,204,204);padding-left:1ex"><br>
<br>
&gt; On Jul 26, 2021, at 2:06 AM, Alex Otenko via Concurrency-interest &lt;=
<a href=3D"mailto:[email protected]" rel=3D"noreferrer" ta=
rget=3D"_blank">[email protected]</a>&gt; wrote:<br>
&gt; <br>
&gt; &quot;Don&#39;t write the code like that&quot; is what the others said=
 about while(!done), so maybe you can see the point they are making.<br>
&gt; <br>
&gt; As for this example - please take it as an example of code that may no=
t behave as written.<br>
&gt; <br>
&gt; As to why it is written like that - well, it is derived from a more el=
aborate mutually recursive case (with a bug).<br>
&gt; <br>
&gt; It is perfectly normal to state &quot;zero is even&quot;, &quot;x+1 is=
 even, if x is odd&quot;, and &quot;x+1 is odd, if x is even&quot;. This is=
 a recursive definition that is derived from a recursive definition of natu=
ral numbers. It is not complete, but you can&#39;t tell if you don&#39;t ha=
ve the compiler that will tell you that.<br>
&gt; <br>
&gt; So you have:<br>
&gt; <br>
&gt; char odd(int x){return even(x-1);}<br>
&gt; char even(int x){return !x || odd(x-1);}<br>
&gt; <br>
&gt; Inline even into odd, do tail call optimization, and you end up with a=
 loop like that (ok, x--, not x++). Both of these steps is what modern clan=
g, gcc and llvm do<br>
<br>
Yes, but this is broken because you can only call even() on evens and odd()=
 on odds for it to work.=C2=A0 But the tail recursion resolution on a -O co=
mpilation never loops and just results in a bogus =E2=80=981=E2=80=99 retur=
n for all cases.=C2=A0 With -g, you get infinite recursion that crashes wit=
h a stack explosion.=C2=A0 You can debug this and see what=E2=80=99s happen=
ing.<br>
<br>
I=E2=80=99m still completely focused on the fact that the hoist of the loop=
 condition makes the code into an infinite loop that you can=E2=80=99t obse=
rve, readily, why a value of done=3Dtrue doesn=E2=80=99t cause the loop to =
exit.=C2=A0 What you can observe in the value of done should cause the loop=
 to exit.=C2=A0 It=E2=80=99s subtly different in my consideration, but it l=
ooks like its a bug because you can=E2=80=99t see the code that is executin=
g incorrectly.=C2=A0 With this example you show, you can put printf in even=
() and odd(), see the values of x, and notice how you end up in odd() with =
x=3D=3D0 when you call even() with an odd value or odd() with an even value=
 and thus the bug occurs.<br>
<br>
Gregg Wonderly<br>
<br>
<br>
<br>
</blockquote></div>
</div></blockquote></div><br></div>________________________________________=
_______<br>
Concurrency-interest mailing list<br>
<a href=3D"mailto:[email protected]" target=3D"_blank">Con=
[email protected]</a><br>
<a href=3D"http://cs.oswego.edu/mailman/listinfo/concurrency-interest" rel=
=3D"noreferrer" target=3D"_blank">http://cs.oswego.edu/mailman/listinfo/con=
currency-interest</a><br>
</blockquote></div>

--0000000000008bb9f505c8203abd--

--===============7346183974866000481==
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: inline

X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KQ29uY3VycmVu
Y3ktaW50ZXJlc3QgbWFpbGluZyBsaXN0CkNvbmN1cnJlbmN5LWludGVyZXN0QGNzLm9zd2Vnby5l
ZHUKaHR0cDovL2NzLm9zd2Vnby5lZHUvbWFpbG1hbi9saXN0aW5mby9jb25jdXJyZW5jeS1pbnRl
cmVzdAo=

--===============7346183974866000481==--