Couldn't you do a compare and compare and swap? With VarHandles something 
like

if (ACTION.getOpaque(this) != expected) return false;
return compareAndExchange(this, expected, newValue) == expected;

Not sure I got this correct

On Saturday, September 14, 2019 at 11:29:00 AM UTC-7, Vitaly Davidovich 
wrote:
>
> Unlike C++, where you can specify mem ordering for failure and success 
> separately, Java doesn’t allow that.  But, the mem ordering is the same for 
> failure/success there.  Unfortunately it doesn’t look like the javadocs 
> mention that, but I recall Doug Lea saying that’s the case on the 
> concurrency-interest mailing list (btw that’s probably the more appropriate 
> channel for this Java-centric question).
>
> For your case, it seems like an AtomicReference<Runnable> is more 
> appropriate.  terminate() sets it, then checks the count via a volatile 
> load (or maybe it can decrement() itself?); if zero, CAS null into the 
> action field to take/claim the action.  decrement() likewise tries to claim 
> the action via a CAS.  The snippet you have now would allow for concurrent 
> action execution, which is likely unsafe/wrong.
>
> On Fri, Sep 13, 2019 at 3:08 AM Simone Bordet <simone...@gmail.com 
> <javascript:>> wrote:
>
>> Hi,
>>
>> I have an atomic counter that gets incremented and decremented over
>> time (non monotonically).
>> At a certain point, I would like to enter a termination protocol where
>> increments are not possible anymore and I set an action to run if/when
>> the counter reaches zero.
>> Trivial when using synchronized/lock, but I'd like to give it a try
>> without them.
>>
>> class A {
>>   private final AtomicLong counter;
>>   // Non-volatile
>>   private Runnable action;
>>
>>   void terminate(Runnable action) {
>>     this.action = action;
>>     // Volatile write needed here for visibility.
>>     if (counter.addAndGet(0) == 0) {
>>       action.run();
>>     }
>>   }
>>
>>   void decrement() {
>>     // Volatile read required to see this.action.
>>     if (counter.decrementAndGet() == 0) {
>>       Runnable a = this.action;
>>       if (a != null) {
>>         a.run()
>>       }
>>     }
>>   }
>> }
>>
>> Is addAndGet(0) a volatile write? Can the write be optimized away?
>> Similarly (although not relevant for this particular example), a
>> _failed_ compareAndSet() has the semantic of a volatile write even if
>> the set part was not done because the compare part failed?
>>
>> Thanks!
>>
>> -- 
>> Simone Bordet
>> ---
>> Finally, no matter how good the architecture and design are,
>> to deliver bug-free software with optimal performance and reliability,
>> the implementation technique must be flawless.   Victoria Livschitz
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "mechanical-sympathy" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to mechanical-sympathy+unsubscr...@googlegroups.com <javascript:>.
>> To view this discussion on the web, visit 
>> https://groups.google.com/d/msgid/mechanical-sympathy/CAFWmRJ3qGJ_qqrXmAHNDZ6ro01BQwe8czHZP7b-SoZ%2BrULhJAw%40mail.gmail.com
>> .
>>
> -- 
> Sent from my phone
>

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
To view this discussion on the web, visit 
https://groups.google.com/d/msgid/mechanical-sympathy/43729dfa-1e73-4318-b446-e80c81422b6e%40googlegroups.com.

Reply via email to