module Einhorn::Event

TODO: set lots of cloexecs

Public Class Methods

break_loop() click to toggle source
# File lib/einhorn/event.rb, line 161
def self.break_loop
  Einhorn.log_debug("Breaking the loop")
  begin
    @@loopbreak_writer.write_nonblock('a')
  rescue Errno::EWOULDBLOCK, Errno::EAGAIN
    Einhorn.log_error("Loop break pipe is full -- probably means that we are quite backlogged")
  end
end
close_all() click to toggle source
# File lib/einhorn/event.rb, line 24
def self.close_all
  @@loopbreak_reader.close
  @@loopbreak_writer.close
  (@@readable.values + @@writeable.values).each do |descriptors|
    descriptors.each do |descriptor|
      descriptor.close
    end
  end
end
close_all_for_worker() click to toggle source
# File lib/einhorn/event.rb, line 34
def self.close_all_for_worker
  close_all
end
connections() click to toggle source
# File lib/einhorn/event.rb, line 98
def self.connections
  @@connections.values
end
default_timeout() click to toggle source
# File lib/einhorn/event.rb, line 174
def self.default_timeout
  @@default_timeout
end
default_timeout=(val) click to toggle source
# File lib/einhorn/event.rb, line 170
def self.default_timeout=(val)
  @@default_timeout = val.to_i == 0 ? nil : val.to_i
end
deregister_connection(fd) click to toggle source
# File lib/einhorn/event.rb, line 94
def self.deregister_connection(fd)
  @@connections.delete(fd)
end
deregister_readable(reader) click to toggle source
# File lib/einhorn/event.rb, line 59
def self.deregister_readable(reader)
  readers = @@readable[reader.to_io]
  readers.delete(reader)
  @@readable.delete(reader.to_io) if readers.length == 0
end
deregister_timer(timer) click to toggle source
# File lib/einhorn/event.rb, line 107
def self.deregister_timer(timer)
  timers = @@timers[timer.expires_at]
  timers.delete(timer)
  @@timers.delete(timer.expires_at) if timers.length == 0
end
deregister_writeable(writer) click to toggle source
# File lib/einhorn/event.rb, line 76
def self.deregister_writeable(writer)
  writers = @@writeable[writer.to_io]
  writers.delete(writer)
  @@writeable.delete(writer.to_io) if writers.length == 0
end
init() click to toggle source
# File lib/einhorn/event.rb, line 14
def self.init
  readable, writeable = Einhorn::Compat.pipe

  @@loopbreak_reader = LoopBreaker.open(readable)
  @@loopbreak_writer = writeable

  Einhorn::Compat.cloexec!(readable, true)
  Einhorn::Compat.cloexec!(writeable, true)
end
loop_once() click to toggle source
# File lib/einhorn/event.rb, line 113
def self.loop_once
  run_signal_actions
  run_selectables
  run_timers
end
persistent_descriptors() click to toggle source
# File lib/einhorn/event.rb, line 38
def self.persistent_descriptors
  descriptor_sets = @@readable.values + @@writeable.values + @@timers.values
  descriptors = descriptor_sets.inject {|a, b| a | b}
  descriptors.select {|descriptor| Einhorn::Event::Persistent.persistent?(descriptor)}
end
readable_fds() click to toggle source
# File lib/einhorn/event.rb, line 65
def self.readable_fds
  readers = @@readable.keys
  Einhorn.log_debug("Readable fds are #{readers.inspect}")
  readers
end
register_connection(connection, fd) click to toggle source
# File lib/einhorn/event.rb, line 90
def self.register_connection(connection, fd)
  @@connections[fd] = connection
end
register_readable(reader) click to toggle source
# File lib/einhorn/event.rb, line 54
def self.register_readable(reader)
  @@readable[reader.to_io] ||= Set.new
  @@readable[reader.to_io] << reader
end
register_signal_action(&blk) click to toggle source
# File lib/einhorn/event.rb, line 50
def self.register_signal_action(&blk)
  @@signal_actions << blk
end
register_timer(timer) click to toggle source
# File lib/einhorn/event.rb, line 102
def self.register_timer(timer)
  @@timers[timer.expires_at] ||= Set.new
  @@timers[timer.expires_at] << timer
end
register_writeable(writer) click to toggle source
# File lib/einhorn/event.rb, line 71
def self.register_writeable(writer)
  @@writeable[writer.to_io] ||= Set.new
  @@writeable[writer.to_io] << writer
end
restore_persistent_descriptors(persistent_descriptors) click to toggle source
# File lib/einhorn/event.rb, line 44
def self.restore_persistent_descriptors(persistent_descriptors)
  persistent_descriptors.each do |descriptor_state|
    Einhorn::Event::Persistent.from_state(descriptor_state)
  end
end
run_selectables() click to toggle source
# File lib/einhorn/event.rb, line 138
def self.run_selectables
  time = timeout
  Einhorn.log_debug("Loop timeout is #{time.inspect}")
  # Time's already up
  return if time && time < 0

  readable, writeable, _ = IO.select(readable_fds, writeable_fds, nil, time)
  (readable || []).each do |io|
    @@readable[io].each {|reader| reader.notify_readable}
  end

  (writeable || []).each do |io|
    @@writeable[io].each {|writer| writer.notify_writeable}
  end
end
run_signal_actions() click to toggle source
# File lib/einhorn/event.rb, line 128
def self.run_signal_actions
  # Note thah @@signal_actions can be mutated in the signal
  # handlers. Since it's just an array we push to/shift from, we
  # can be sure there's no race (such as adding hash keys during
  # iteration.)
  while blk = @@signal_actions.shift
    blk.call
  end
end
run_timers() click to toggle source
# File lib/einhorn/event.rb, line 154
def self.run_timers
  @@timers.select {|expires_at, _| expires_at <= Time.now}.each do |expires_at, timers|
    # Going to be modifying the set, so let's dup it.
    timers.dup.each {|timer| timer.ring!}
  end
end
timeout() click to toggle source
# File lib/einhorn/event.rb, line 119
def self.timeout
  # (expires_at of the next timer) - now
  if expires_at = @@timers.keys.sort[0]
    expires_at - Time.now
  else
    @@default_timeout
  end
end
writeable_fds() click to toggle source
# File lib/einhorn/event.rb, line 82
def self.writeable_fds
  writers = @@writeable.select do |io, writers|
    writers.any? {|writer| writer.write_pending?}
  end.map {|io, writers| io}
  Einhorn.log_debug("Writeable fds are #{writers.inspect}")
  writers
end