<div dir="ltr">Yeah, we previously also tried split counting, but reverted it because we observed some weird rare issues, and got suspicious of it.</div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Wed, Dec 10, 2025 at 8:21 AM Maurizio Cimadamore <<a href="mailto:maurizio.cimadamore@oracle.com">maurizio.cimadamore@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">What I like (a lot) about this is that now we're back to using the same <br>
"bit" of information for both liveness and acquire count (IIUC). If <br>
that's the case, it would be much simpler to convince ourselves this is <br>
correct.<br>
<br>
Thanks<br>
Maurizio<br>
<br>
On 10/12/2025 14:48, Stuart Monteith wrote:<br>
> Thanks Chris,<br>
> I've taken a look and implemented SharedSession with something <br>
> similar to your RefCnt. One of the differences with SharedSession is <br>
> that we have a separate close method. I can implement acquire0 with <br>
> getAndAdd(2), release0 with getAndAdd(-2) and close with <br>
> compareAndSwap(0, 1). With the additional tests against 0x80000001 for <br>
> acquire0 and release0, I have something that passes the unit tests for <br>
> java/foreign.<br>
><br>
> The benchmarking is quite promising, but I'll need to look more <br>
> closely at it - it doesn't scale better on all platforms.<br>
><br>
> Thanks,<br>
> Stuart<br>
><br>
><br>
><br>
><br>
> On 08/12/2025 19:45, Chris Vest wrote:<br>
>> For what it's worth, in Netty we implement our reference counting <br>
>> with incrementing by 2 instead of 1, and use the low odd bit to <br>
>> indicate the released state.<br>
>> This allows us to acquire using getAndAdd, which scales much better <br>
>> than a CAS loop.<br>
>> Unfortunately we still need to use a CAS loop when implementing <br>
>> release, so that still has contention problems.<br>
>><br>
>> For reference: <br>
>> <a href="https://urldefense.com/v3/__https://github.com/netty/netty/blob/2b29b5e87656203fecd1732ffb472a366a1918cc/common/src/main/java/io/__;!!ACWV5N9M2RV99hQ!JMRywug9hgGI_tWR1jAjiE8gIGbCfu9ZYKUrgzQiG8A3Woj6cYJa4S-ZKJ-IteJDrpe0GexRIhlFIKg6zUpWV3sr6DvTDI0$" rel="noreferrer" target="_blank">https://urldefense.com/v3/__https://github.com/netty/netty/blob/2b29b5e87656203fecd1732ffb472a366a1918cc/common/src/main/java/io/__;!!ACWV5N9M2RV99hQ!JMRywug9hgGI_tWR1jAjiE8gIGbCfu9ZYKUrgzQiG8A3Woj6cYJa4S-ZKJ-IteJDrpe0GexRIhlFIKg6zUpWV3sr6DvTDI0$</a> <br>
>> netty/util/internal/RefCnt.java#L258-L295 <br>
>> <<a href="https://urldefense.com/v3/__https://github.com/netty/netty/blob/2b29b5e87656203fecd1732ffb472a366a1918cc/__;!!ACWV5N9M2RV99hQ!JMRywug9hgGI_tWR1jAjiE8gIGbCfu9ZYKUrgzQiG8A3Woj6cYJa4S-ZKJ-IteJDrpe0GexRIhlFIKg6zUpWV3sr9MgkwZk$" rel="noreferrer" target="_blank">https://urldefense.com/v3/__https://github.com/netty/netty/blob/2b29b5e87656203fecd1732ffb472a366a1918cc/__;!!ACWV5N9M2RV99hQ!JMRywug9hgGI_tWR1jAjiE8gIGbCfu9ZYKUrgzQiG8A3Woj6cYJa4S-ZKJ-IteJDrpe0GexRIhlFIKg6zUpWV3sr9MgkwZk$</a> <br>
>> common/src/main/java/io/netty/util/internal/RefCnt.java#L258-L295><br>
>><br>
>> On Mon, Dec 8, 2025 at 10:42 AM Maurizio Cimadamore <br>
>> <<a href="mailto:maurizio.cimadamore@oracle.com" target="_blank">maurizio.cimadamore@oracle.com</a> <br>
>> <mailto:<a href="mailto:maurizio.cimadamore@oracle.com" target="_blank">maurizio.cimadamore@oracle.com</a>>> wrote:<br>
>><br>
>><br>
>> > sum() is really just a snapshot, it adds up the counters <br>
>> (Cells), so<br>
>> > it wouldn't ensure the counter was at zero. Immediately after<br>
>> > returning zero a thread could have already incremented it.<br>
>> Yes. What I mean is: you can check if close() should throw <br>
>> because of<br>
>> pending acquires. But, as I said, we can use that in any way to <br>
>> "block"<br>
>> other acquires from happening in case we _do_ want to close. Which<br>
>> leaves us exposed.<br>
>> ><br>
>> ><br>
>> >> For the purpose of implementation clarity -- would it be <br>
>> useful to<br>
>> >> wrap the various counters plus logic to acquire/ release (and<br>
>> >> "closing" state) into a separate abstraction, which is then <br>
>> used by<br>
>> >> SharedMemorySession? A sort of "atomic" LongAdder, if you <br>
>> will :-)<br>
>> >><br>
>> >> That might make it easier to verify the correctness of the<br>
>> >> implementation, by validating each aspect (the atomic long <br>
>> adder, and<br>
>> >> its use from SharedMemorySession) separately.<br>
>> ><br>
>> > Sure, that would be a bit cleaner, thanks.<br>
>><br>
>> Thanks.<br>
>><br>
>><br>
>> Maurizio<br>
>><br>
><br>
</blockquote></div>