Method: Futex#open
- Defined in:
- lib/futex.rb
#open(exclusive = true) ⇒ Object
Open the file. By default the file will be locked for exclusive access, which means that absolutely no other process will be able to do the same. This type of access (exclusive) is supposed to be used when you are making changes to the file. However, very often you may need just to read it and it’s OK to let many processes do the reading at the same time, provided none of them do the writing. In that case you should call this method open()
with false
first argument, which will mean “shared” access. Many threads and processes may have shared access to the same lock file, but they all will stop and wait if one of them will require an “exclusive” access. This mechanism is inherited from POSIX, read about it <a href=“man7.org/linux/man-pages/man2/flock.2.html”>here</a>.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/futex.rb', line 95 def open(exclusive = true) FileUtils.mkdir_p(File.dirname(@lock)) step = (1 / @sleep).to_i start = Time.now prefix = exclusive ? '' : 'non-' b = badge(exclusive) Thread.current.thread_variable_set(:futex_lock, @lock) Thread.current.thread_variable_set(:futex_badge, b) open_synchronized(@lock) do |f| cycle = 0 loop do if f.flock((exclusive ? File::LOCK_EX : File::LOCK_SH) | File::LOCK_NB) Thread.current.thread_variable_set(:futex_cycle, nil) Thread.current.thread_variable_set(:futex_time, nil) break end sleep(@sleep) cycle += 1 Thread.current.thread_variable_set(:futex_cycle, cycle) Thread.current.thread_variable_set(:futex_time, Time.now - start) if Time.now - start > @timeout raise CantLock.new("#{b} can't get #{prefix}exclusive access \ to the file #{@path} because of the lock at #{@lock}, after #{age(start)} \ of waiting: #{IO.read(@lock)} (modified #{age(File.mtime(@lock))} ago)", File.mtime(@lock)) end next unless (cycle % step).zero? && Time.now - start > @timeout / 2 debug("#{b} still waiting for #{prefix}exclusive \ access to #{@path}, #{age(start)} already: #{IO.read(@lock)} \ (modified #{age(File.mtime(@lock))} ago)") end debug("Locked by #{b} in #{age(start)}, #{prefix}exclusive: \ #{@path} (attempt no.#{cycle})") IO.write(@lock, b) acq = Time.now res = block_given? ? yield(@path) : nil debug("Unlocked by #{b} in #{age(acq)}, #{prefix}exclusive: #{@path}") res end ensure Thread.current.thread_variable_set(:futex_cycle, nil) Thread.current.thread_variable_set(:futex_time, nil) Thread.current.thread_variable_set(:futex_lock, nil) Thread.current.thread_variable_set(:futex_badge, nil) end |