def read_events
      size = Native::Event.size + Native.fpathconf(fd, Native::Flags::PC_NAME_MAX) + 1
      tries = 1

      begin
        data = readpartial(size)
      rescue SystemCallError => er
        # EINVAL means that there's more data to be read
        # than will fit in the buffer size
        raise er unless er.errno == Errno::EINVAL::Errno && tries < 5
        size *= 2
        tries += 1
        retry
      end
      return [] if data.nil?

      events = []
      cookies = {}
      while event = Event.consume(data, self)
        events << event
        next if event.cookie == 0
        cookies[event.cookie] ||= []
        cookies[event.cookie] << event
      end
      cookies.each {|c, evs| evs.each {|ev| ev.related.replace(evs - [ev]).freeze}}
      events
    end
def read_events
      size = Native::Event.size + Native.fpathconf(fd, Native::Flags::PC_NAME_MAX) + 1
      tries = 1

      begin
        data = readpartial(size)
      rescue SystemCallError => er
        # EINVAL means that there's more data to be read
        # than will fit in the buffer size
        raise er unless er.errno == Errno::EINVAL::Errno && tries < 5
        size *= 2
        tries += 1
        retry
      end
      return [] if data.nil?

      events = []
      cookies = {}
      while event = Event.consume(data, self)
        events << event
        next if event.cookie == 0
        cookies[event.cookie] ||= []
        cookies[event.cookie] << event
      end
      cookies.each {|c, evs| evs.each {|ev| ev.related.replace(evs - [ev]).freeze}}
      events
    end
Blocks until there are one or more filesystem events that this notifier
 has watchers registered for. Once there are events, returns their {Event}
 objects.

 This can return an empty list if the watcher was closed elsewhere.

 {#run} or {#process} are ususally preferable to calling this directly.