From: ahoward Date: 2003-01-30T07:40:16+09:00 Subject: suggestion File#lock rubyists- due to whacky behavior exhibited on various platforms regarding flock, i would like to suggest an implementation of a File#lock method similar the following one. any suggestions to improve it welcome. file File_lock.rb ----CUT---- # File#lock - a method for safely locking a file between processes and/or # threads class File require 'thread' private attr_writer :sem public attr_reader :sem def lock sem = Mutex.new unless sem sem.synchronize do catch (:eintr){ begin loop { flock (LOCK_EX | LOCK_NB) and break or Thread.pass} rescue Errno::EINTR throw :eintr end } yield self catch (:eintr){ begin flock LOCK_UN rescue Errno::EINTR throw :eintr end } end end end if $0 == __FILE__ # this program coordinates access to an output file for the purpose of # # inserting a timestamp between multiple threads spawned from within multiple # forked processes. the coordination is considered successful if no # timestamps are inserted non-sequentially require 'thread' require 'ftools' pid = Process.pid n_child = (ARGV.shift or 4).to_i n_thread = (ARGV.shift or 4).to_i n_mark = (ARGV.shift or 2 << 9).to_i outpath = (ARGV.shift or '/tmp/out') sortedpath = (ARGV.shift or '/tmp/sorted') File.rm_f outpath File.rm_f sortedpath n_mark_per_thread = n_mark / n_child / n_thread cids = [] $stdout.sync = true $stdout.puts "================" $stdout.puts "N_CHILD : #{n_child}" $stdout.puts "N_THREAD : #{n_thread}" $stdout.puts "N_MARK : #{n_mark}" $stdout.puts "OUTPATH : #{outpath}" $stdout.puts "================" $stdout.puts "\n#{pid} STARTED" n_child.times { cids << Process.fork { ppid = Process.ppid pid = Process.pid sem = Mutex.new output = "\t#{ppid}.#{pid} STARTED\n" File.open (outpath, 'a+') { |file| threads = [] n_thread.times { threads << Thread.new (threads.size) { |tid| sem.synchronize { output << "\t\t#{ppid}.#{pid}.#{tid} STARTED\n" } n_mark_per_thread.times { file.lock { |f| f.seek IO::SEEK_END f.syswrite "%10.5f\n" % Time.now.to_f } Thread.pass } } } threads.map {|t| t.join} } $stdout.puts output exit! } } cids.map { |cid| Process.waitpid cid } cids.map { |cid| $stdout.puts "\t#{pid}.#{cid} FINISHED" } output = IO.readlines outpath sorted = output.sort {|a,b| a.to_f <=> b.to_f} if output != sorted File.open (sortedpath, 'w') {|f| f.puts sorted } $stdout.puts "\nERROR!" $stdout.puts "SUGGEST 'diff -c #{outpath} #{sortedpath}'" else $stdout.puts "\nSUCCESS!" end end ----CUT---- -a -- ==================================== | Ara Howard | NOAA Forecast Systems Laboratory | Information and Technology Services | Data Systems Group | R/FST 325 Broadway | Boulder, CO 80305-3328 | Email: ahoward@fsl.noaa.gov | Phone: 303-497-7238 | Fax: 303-497-7259 ====================================