Search code examples
rubymultithreadingsasscompass-sasscompass

How do you iterate over ARGV and create a Thread for each value in the array in Ruby


I'm trying to create a Ruby script that launches a separate thread for each of the arguments passed in ARGV, but I can't figure out how to iterate over them and pass them in the thread as constants (or thread-safe). Something like:

compile.rb

require 'rubygems'
require 'compass'
require 'compass/exec'

threads = []
ARGV.each do |arg|
  threads << Thread.new { Compass::Exec::SubCommandUI.new(["compile", arg]).run! }
end
threads.each { |thr| thr.join }

The result is that it will create the expected number of threads, but each thread will run on the same arg value (the loop doesn't work as expected).

I'm trying to run it from Ant, like this:

build.xml

<java fork="true" failonerror="true" classpathref="jruby.classpath" classname="org.jruby.Main">
    <arg path="${ext.path}\compile.rb"></arg>
    <arg line="${config.rb.dirs.str}"></arg>
</java>

where "config.rb.dirs.str" contains my paths to multiple Sass projects, space separated.

I'm a newbie in Ruby, so please don't judge. Thanks!


Solution

  • Can you run following and tell us the output? You can run it with args or use the default args that are specified in the script. It is just two ways of passing variables (i prefer the second one). I think this is a minimal sample that does not require anything extra.

    args = ARGV.size > 0 ? ARGV : ['arg1', 'arg2', 'arg3']
    
    puts "args is #{args} and has size #{args.size}"
    threads = args.map do |arg|
      Thread.new do
        sleep 1
        print "Arg is: #{arg}\n"
      end
    end
    
    threads.each(&:join)
    
    puts "--"
    
    
    threads = args.map do |arg|
      Thread.new(arg) do |value|
        sleep 1
        print "Arg is: #{value}\n"
      end
    end
    
    threads.each(&:join)