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

Returns a new instance of 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.

Parameters:

  • fp (File)
  • operation (PARAM)

    See File#flock

Returns:

  • see File#flock



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

Returns true if locked by self.

Parameters:

  • fp (File)

Returns:

  • (Boolean)

    true if locked by self



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.

Parameters:

  • fp (File)
  • operation (PARAM)

    See File#flock

Yields:

Returns:

  • (Object)

    the result of block

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

Returns see File#flock.

Parameters:

  • operation (PARAM)

    See File#flock

Returns:

  • see File#flock



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

Returns true if locked by self.

Returns:

  • (Boolean)

    true if locked by self



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.

Parameters:

  • operation (PARAM)

    See File#flock

Yields:

Returns:

  • (Object)

    the result of block

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