-
-
Save jjsanderson/050c3a38da050acbb724 to your computer and use it in GitHub Desktop.
for i in 0..( p_count -1 ) do | |
in_thread(name: i) do | |
loop do | |
chime p_freq[i], dur | |
sleep p_sleep[i] | |
end | |
end | |
end |
This is a classic "mutable state vs threads" issue. If I had my way, I'd get rid of all mutation/variables in Sonic Pi. Unfortunately, they're on the curriculum and they're everywhere in Ruby, so I'm working on ways to make alternatives easier and better!
First up, you rarely ever see the for i in ...
pattern in Ruby. It's much more idiomatic to use iteration:
p_count = 5
(0..(p_count -1)).each do |i|
in_thread(name: i) do
loop do
puts i
# chime p_freq[i], dur
sleep 1
end
end
end
Interestingly, this doesn't suffer from the same problem as your code. Clearly, the for
comprehension uses mutable state so that all the i
's in the threads are actually the same i
not distinct i
s. The .each
version appears to give distinct i
s.
However, you should always be wary of passing in variables into threads. The approach you're taking treats the variables as so-called free variables which in an Object Oriented world means free references as different references can refer to the same object.
Essentially, mutable state and Objects are often bad news when combined with concurrency. We need to move to a more immutable and functional world (which is where I'm slowly pushing Sonic Pi).
Hope this helps in some way.
I'd expect this snippet to spawn p_count threads, with each passing the ith element of the (previously-populated) arrays into the called functions.
What actually happens: I get p_count threads, but each passes the last value of the arrays into the called functions.