30: def do_once(file)
31: need_to_execute = synchronize do
32: case @state[file]
33: when :doing
34: if @thread[file] != Thread.current
35: @cond_var[file].wait
36: end
37: false
38: when :done
39: false
40: else
41: @state[file] = :doing
42: @thread[file] = Thread.current
43: @cond_var[file] = new_cond
44: true
45: end
46: end
47: if need_to_execute
48: begin
49: yield
50: ensure
51: synchronize do
52: @state[file] = :done
53: @thread.delete(file)
54: @cond_var.delete(file).broadcast
55: end
56: end
57: end
58: end