Class: ReentrantFlock

Inherits:
Object
  • Object
show all
Defined in:
lib/reentrant_flock.rb,
lib/reentrant_flock.rb,
lib/reentrant_flock.rb,
lib/reentrant_flock/version.rb

Overview

Please note that:

“` fp = File.open('a', 'w') fp.flock(File::LOCK_EX) fp.flock(File::LOCK_EX) # does not block fp = File.open('a', 'w') fp.flock(File::LOCK_EX) # block “`

That is, File#flock is orginally reentrant for the same file object. On linux, file lock is associated with file descriptor, so another file descriptor is required to get blocked. This version holds the same file object, so might be useless. I may delete this. Using flock directly should be enough.

Defined Under Namespace

Classes: AlreadyLocked

Constant Summary collapse

VERSION =
"0.1.1"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(fp) ⇒ ReentrantFlock


110
111
112
113
114
# File 'lib/reentrant_flock.rb', line 110

def initialize(fp)
  @fp = fp
  @mutex = Mutex.new
  @counts = Hash.new(0)
end

Instance Attribute Details

#fpObject (readonly)

Returns the value of attribute fp


108
109
110
# File 'lib/reentrant_flock.rb', line 108

def fp
  @fp
end

Class Method Details

.flock(fp, operation) ⇒ Object

Note that File#flock is automatically unlocked when a file is closed, but ReentrantFlock.flock cannot automatically reset internal counts when a file is closed. Use ReentrantFlock.synchronize to assure decrementing internal counts.


17
18
19
20
21
22
23
# File 'lib/reentrant_flock.rb', line 17

def flock(fp, operation)
  if (operation & File::LOCK_UN) > 0
    unlock(fp)
  else
    lock(fp, operation)
  end
end

.self_locked?(fp) ⇒ Boolean


43
44
45
46
# File 'lib/reentrant_flock.rb', line 43

def self_locked?(fp)
  k = key(fp)
  Thread.current.key?(k) and Thread.current[k] >= 1
end

.synchronize(fp, operation) { ... } ⇒ Object

Returns the result of block.

Yields:

Raises:

  • (AlreadyLocked)

    if already locked and LOCK_NB operation is specified


30
31
32
33
34
35
36
37
38
39
# File 'lib/reentrant_flock.rb', line 30

def synchronize(fp, operation)
  raise 'Must be called with a block' unless block_given?

  begin
    raise AlreadyLocked if lock(fp, operation) == false
    yield
  ensure
    unlock(fp)
  end
end

Instance Method Details

#flock(operation) ⇒ Object


118
119
120
121
122
123
124
# File 'lib/reentrant_flock.rb', line 118

def flock(operation)
  if (operation & File::LOCK_UN) > 0
    unlock
  else
    lock(operation)
  end
end

#self_locked?Boolean


142
143
144
# File 'lib/reentrant_flock.rb', line 142

def self_locked?
  @mutex.synchronize { @counts[Thread.current] >= 1 }
end

#synchronize(operation) { ... } ⇒ Object

Returns the result of block.

Yields:

Raises:

  • (AlreadyLocked)

    if already locked and LOCK_NB operation is specified


130
131
132
133
134
135
136
137
138
139
# File 'lib/reentrant_flock.rb', line 130

def synchronize(operation)
  raise 'Must be called with a block' unless block_given?

  begin
    raise AlreadyLocked if lock(operation) == false
    yield
  ensure
    unlock
  end
end