Ruby and Threading Fun

So here is a class I wrote in ruby.

class LimitedThreads
    def initialize max
        @group = ThreadGroup.new
        @maxthreads = max
        @lock = Mutex.new
        @slot = ConditionVariable.new
    end

    def to_s
        "max threads: %s; current threads: %s;" % [@maxthreads, @group.list.size]
    end

    def newthread *args
        if @maxthreads <= @group.list.size
            #delay until a thread ends
            @lock.synchronize { @slot.wait(@lock) }
        end
        nt = Thread.new do
            yield *args #this allows operation like Thread.new for passing in args to thread
            @lock.synchronize { @slot.signal }
        end
        @group.add nt
        nt
    end
end

You create an object from this with the maximum amount of threads you want it to allow to run at any given time. You use LimitedThreads#newthread with a block representing the thread you want to run. If the instance has a spot free for that thread, it will run it. Otherwise, it will wait until a already running thread finishes to start up the new thread. Now, this code probably has no real use, but it was an interesting exercise for me. Ruby is interesting in that it uses blocks for threads, not methods. The comment inside the Thread.new call is on the subject of passing arguments into the block that LimitedThreads#newthread takes. Anyway, here is an example of how to use it.

lt=LimitedThreads.new 3
sleep_time = 2
12.times do |count|
    message = "hello from pass number %s" % count
    lt.newthread(message, sleep_time) do |msg, st|
        sleep st
        puts msg
    end
end

On my system, this consistently prints:

hello from pass number 1
hello from pass number 0
hello from pass number 2
hello from pass number 4
hello from pass number 3
hello from pass number 5
hello from pass number 7
hello from pass number 6
hello from pass number 8

Printing each group of three at 2 second interval bursts (all in group appear). Try it on other systems; it might do something else. If you can find a use for it, please, tell me.

Leave a Reply