#!/usr/bin/env ruby
Original program idea:
Write a ruby program that checks the integrity of all my FLAC music
files,
and that makes use of my MacBooks Core Duo CPU. Since Ruby doesn’t
support
native threadds, I decided to use the Slave library.
Problem:
I start 3 Slave servers:
worker1 and worker2 both query the filename server to get the next
filename
to process.
On Mac OS 10.4.10, ruby 1.8.6 (Locomotive or MacPorts, same problem)
the second
worker server process never starts, it seems to sleep forver, and I
don’t
see my programming mistake.
The same problem occurs on Ubuntu Feisty.
However: IF you start the 2nd worker after the first worker completed
its
work, it runs without problem.
And: If you disable the call to the filename server, both workers run
in parallel, too, without deadlocking.
So the problem has something to do with both workers trying to access
the
same filename server.
Any ideas?
require ‘slave’
require ‘monitor’
require ‘fastthread’
class FlacTestServer
def processFiles(filenameServer)
50.times do |i|
#sleep(0.02)
#Activate this:
#puts(“PID #{ Process.pid }: Iteration #{ i }”)
#and disable this and both workers will run without worker 2
sleeping forever.
puts("#{ Process.pid }: #{ filenameServer.nextFilename() }")
end
end
end
class FilenameServer
include MonitorMixin
def initialize()
super
@counter = 0
end
def nextFilename()
synchronize do
# Return some dummy data
@counter += 1
“#{ Process.pid }, #{ @counter }”
end
end
end
if $0 == FILE
fnServer = Slave.new() { FilenameServer.new() }.object
worker1 = Slave.object({:async => true, :psname => ‘Worker1’}) {
FlacTestServer.new().processFiles(fnServer) }
“Works” if you activate this:
#worker1.join()
worker2 = Slave.object({:async => true, :psname => ‘Worker2’}) {
FlacTestServer.new().processFiles(fnServer) }
If you create the slaves using the following method instead, worker2
sometimes runs, sometimes not
and sometimes it runs only a few internal iterations before it
sleeps forever / deadlocks…?!?
But you can get it to work if you active the sleep call in line 37.
#ftServer1 = Slave.new() { FlacTestServer.new() }.object()
#ftServer2 = Slave.new() { FlacTestServer.new() }.object()
#worker1 = Thread.new() { ftServer1.processFiles(fnServer) }
#worker2 = Thread.new() { ftServer2.processFiles(fnServer) }
worker1.join()
puts(“Worker 1 terminated.”)
#puts(“Worker 2 status: #{ worker2.status() }”) until
worker2.join(0.15)
worker2.join()
puts(“Worker 2 terminated.”)
puts(“End main program: #{Process.pid}”)
end