require 'thread' # for exclusive require 'fsdb/file-lock' require 'fsdb/modex.rb'; Sync = FSDB::Modex

include File::OpenLock

process_count = 2 thread_count = 2 rep_count = (ARGV.shift || 10000).to_i modex = Sync.new

test_file = '/tmp/test-file-lock.dat' ## also try NFS

File.open(test_file, "w") {|f| Marshal.dump(0, f)}

(0...process_count).each do

fork do

  increments = 0

  threads =
    (0...thread_count).map do
      Thread.new do
        (0...rep_count).each do
          if rand(100) < 50
            modex.synchronize(Sync::SH) do
              open_read_lock(test_file) do |f|
                str = f.read
                data = Marshal.load(str)
              end
            end
          else
            modex.synchronize(Sync::EX) do
              open_write_lock(test_file) do |f|
                str = f.read
                data = Marshal.load(str)
                data += 1
                f.rewind; f.truncate(0)
                Marshal.dump(data, f)
                f.flush
                Thread.exclusive {increments += 1}
              end
            end
          end
        end
      end
    end

  threads.each {|thread| thread.join}

  File.open("#{test_file}#{Process.pid}", "w") do |f|
    Marshal.dump(increments, f)
  end

end

end

Thread.new do

count = 0
loop do
  puts count
  sleep 1
  count += 1
end  

end

increments = 0 (0...process_count).each do

pid = Process.wait
File.open("#{test_file}#{pid}", "r") do |f|
  increments += Marshal.load(f)
end

end

data = File.open(test_file, "r") {|f| Marshal.load(f)}

if data == increments

puts "Equal counts: #{data}"

else

puts "Not equal:"
puts "  increments: #{increments}"
puts "  data      : #{data}"

end