P
Peter Lichten
#!/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, sname => 'Worker1'}) {
FlacTestServer.new().processFiles(fnServer) }
# "Works" if you activate this:
#worker1.join()
worker2 = Slave.object({:async => true, sname => '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
# 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, sname => 'Worker1'}) {
FlacTestServer.new().processFiles(fnServer) }
# "Works" if you activate this:
#worker1.join()
worker2 = Slave.object({:async => true, sname => '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