class Spring::Watcher::Abstract

watcher.stale? # => true<br>IO.select() # watcher is running in background
watcher = MyWatcher.new(root, latency)
A user of a watcher can use IO.select to wait for changes:

def add(*items)

def add(*items)
  debug { "watcher: add: #{items.inspect}" }
  items = items.flatten.map do |item|
    item = Pathname.new(item)
    if item.relative?
      Pathname.new("#{root}/#{item}")
    else
      item
    end
  end
  items = items.select do |item|
    if item.symlink?
      item.readlink.exist?.tap do |exists|
        if !exists
          debug { "add: ignoring dangling symlink: #{item.inspect} -> #{item.readlink.inspect}" }
        end
      end
    else
      item.exist?
    end
  end
  synchronize {
    items.each do |item|
      if item.directory?
        directories << item.realpath.to_s
      else
        begin
          files << item.realpath.to_s
        rescue Errno::ENOENT
          # Race condition. Ignore symlinks whose target was removed
          # since the check above, or are deeply chained.
          debug { "add: ignoring now-dangling symlink: #{item.inspect} -> #{item.readlink.inspect}" }
        end
      end
    end
    subjects_changed
  }
end

def debug

def debug
  @on_debug.call(yield) if @on_debug
end

def initialize(root, latency)

def initialize(root, latency)
  super()
  @root        = File.realpath(root)
  @latency     = latency
  @files       = Set.new
  @directories = Set.new
  @stale       = false
  @listeners   = []
  @on_debug    = nil
end

def mark_stale

def mark_stale
  return if stale?
  @stale = true
  debug { "marked stale, calling listeners: listeners=#{@listeners.inspect}" }
  @listeners.each(&:call)
end

def on_debug(&block)

def on_debug(&block)
  @on_debug = block
end

def on_stale(&block)

def on_stale(&block)
  debug { "added listener: #{block.inspect}" }
  @listeners << block
end

def restart

def restart
  debug { "restarting" }
  stop
  start
end

def stale?

def stale?
  @stale
end

def start

def start
  raise NotImplementedError
end

def stop

def stop
  raise NotImplementedError
end

def subjects_changed

def subjects_changed
  raise NotImplementedError
end