bruteSourceBruteQueueFileMutationQueueself

class << self

Definitions

def serialize(path, &block)

Serialize a block of work for a given file path.

Concurrent calls targeting the same canonical path will execute sequentially in FIFO order. Calls targeting different paths proceed in parallel with zero contention.

Signature

parameter path String

The file path to serialize on.

yields {block}

The mutation work to perform (snapshot, read, write, etc.)

Implementation

def serialize(path, &block)
  key = canonical_path(path)
  mutex = acquire_mutex(key)

  mutex.synchronize(&block)
ensure
  release_mutex(key)
end

def clear!

Clear all tracked mutexes. Used in tests and session resets.

Implementation

def clear!
  @guard.synchronize do
    @mutexes.clear
    @waiters.clear
  end
end

def size

Number of file paths currently tracked (for diagnostics).

Implementation

def size
  @guard.synchronize { @mutexes.size }
end

def canonical_path(path)

Resolve a file path to a canonical key. Uses File.realpath to follow symlinks so that aliases to the same underlying file share one mutex. Falls back to File.expand_path for files that don't exist yet (e.g., new writes).

Implementation

def canonical_path(path)
  resolved = File.expand_path(path)
  begin
    File.realpath(resolved)
  rescue Errno::ENOENT
    resolved
  end
end

def acquire_mutex(key)

Get (or create) a mutex for a file path and increment the waiter count.

Implementation

def acquire_mutex(key)
  @guard.synchronize do
    @mutexes[key] ||= Mutex.new
    @waiters[key] += 1
    @mutexes[key]
  end
end

def release_mutex(key)

Decrement the waiter count and clean up the mutex if no one else needs it.

Implementation

def release_mutex(key)
  @guard.synchronize do
    @waiters[key] -= 1
    if @waiters[key] <= 0
      @mutexes.delete(key)
      @waiters.delete(key)
    end
  end
end