ruby-concurrency / concurrent-ruby

Modern concurrency tools including agents, futures, promises, thread pools, supervisors, and more. Inspired by Erlang, Clojure, Scala, Go, Java, JavaScript, and classic concurrency patterns.
https://ruby-concurrency.github.io/concurrent-ruby/
Other
5.7k stars 419 forks source link

AtomicBoolean: add compare_and_set API #540

Open vemv opened 8 years ago

vemv commented 8 years ago

Compare-and-set is a useful functionality (that's why it exists in the Java API). It can save one from race conditions, as explained below.

Use case

if !LOCKED.value
  LOCKED.value = true
  # do something ....
  LOCKED.value = false
end

In this scenario, concurrent threads can read a false in if !LOCKED.value, and enter the if block. That defeats the purpose of an atomicboolean-backed lock.

If there was a CAS API, the fixed code would look like this:

if LOCKED.compare_and_set(false, true)

Furthermore

Ruby has no "tryLock" either. So it's not immediately obvious how to create non-blocking synchronized code. Boolean CAS would offer a nice alternative which Java programmers (and others) already are familiar with.

What do you think?

Cheers - Victor

vemv commented 8 years ago

Correction: Ruby does have try_lock, but no try_lock do ... end which would be more useful.

jdantonio commented 8 years ago

@vemv Thank you for sharing your thoughts. I think this is a great idea and I'd love more of your input.

There are inconsistencies in the APIs of our atomic classes. They originally came from different places. AtomicReference was merged in from the atomic gem whereas AtomicFixnum and AtomicBoolean were created for specific internal needs. Ultimately the APIs should be as consistent as possible.

We've recently begun discussing concurrent-ruby 2.0. One of our goals will be more consistent APIs. Would you be interested in helping define what the API for the atomics should look like? If so, please feel free to create an issue with a proposal as a starting point for that discussion. I know that's a lot for me to ask but it would be of great help to us if you are interested and have time.

vemv commented 8 years ago

Would you be interested in helping define what the API for the atomics should look like?

Personally I would be fine with most possible reasonable designs, as long as the operations are there.

Just note that at least in Java there's no AtomicDouble/AtomicFloat so implementing CAS for your AtomicFixnum might or might not fully make sense.

jdantonio commented 8 years ago

Certain operations might not make sense on all atomic classes, but we should be consistent with as much as possible across all atomic classes. That will be our goal.

pitr-ch commented 8 years ago

@vemv have a look at make_true, it's a CAS operation with different naming.

vemv commented 8 years ago

It might be CAS as an implementation detail, but for the user it's not CAS as it doesn't accept a comparison argument (see the Java API for compareAndSet)

pitr-ch commented 8 years ago

Ah, you are proposing to add the missing compare_and_set, not looking for a way how to fix the example, sorry I've focused on the latter. It definitely makes sense to add the missing CAS method. Noting that the current make_true and make_false are fully replacing it:

even though 2 different methods have be inconveniently called.