lib/sleepy_penguin/epoll.rb in sleepy_penguin-3.1.0.26.g7181 vs lib/sleepy_penguin/epoll.rb in sleepy_penguin-3.2.0
- old
+ new
@@ -1,47 +1,52 @@
require 'thread'
class SleepyPenguin::Epoll
- # Epoll objects may be watched by IO.select and similar methods
- attr_reader :to_io
-
# call-seq:
# SleepyPenguin::Epoll.new([flags]) -> Epoll object
#
# Creates a new Epoll object with an optional +flags+ argument.
# +flags+ may currently be +:CLOEXEC+ or +0+ (or +nil+).
def initialize(create_flags = nil)
- @to_io = SleepyPenguin::Epoll::IO.new(create_flags)
+ @io = SleepyPenguin::Epoll::IO.new(create_flags)
@mtx = Mutex.new
@events = []
@marks = []
@pid = $$
@create_flags = create_flags
- @copies = { @to_io => self }
+ @copies = { @io => self }
end
def __ep_reinit # :nodoc:
@events.clear
@marks.clear
- @to_io = SleepyPenguin::Epoll::IO.new(@create_flags)
+ @io = SleepyPenguin::Epoll::IO.new(@create_flags)
end
# auto-reinitialize the Epoll object after forking
def __ep_check # :nodoc:
return if @pid == $$
- return if @to_io.closed?
+ return if @io.closed?
objects = @copies.values
@copies.each_key { |epio| epio.close }
@copies.clear
__ep_reinit
objects.each do |obj|
- io_dup = @to_io.dup
+ io_dup = @io.dup
@copies[io_dup] = obj
end
@pid = $$
end
+ # Epoll objects may be watched by IO.select and similar methods
+ def to_io
+ @mtx.synchronize do
+ __ep_check
+ @io
+ end
+ end
+
# Calls epoll_wait(2) and yields Integer +events+ and IO objects watched
# for. +maxevents+ is the maximum number of events to process at once,
# lower numbers may prevent starvation when used by epoll_wait in multiple
# threads. Larger +maxevents+ reduces syscall overhead for
# single-threaded applications. +maxevents+ defaults to 64 events.
@@ -57,24 +62,24 @@
end
# we keep a snapshot of @marks around in case another thread closes
# the IO while it is being transferred to userspace. We release mtx
# so another thread may add events to us while we're sleeping.
- @to_io.epoll_wait(maxevents, timeout) { |events, io| yield(events, io) }
+ @io.epoll_wait(maxevents, timeout) { |events, io| yield(events, io) }
ensure
# hopefully Ruby does not optimize this array away...
- snapshot[0]
+ snapshot.clear
end
# Starts watching a given +io+ object with +events+ which may be an Integer
# bitmask or Array representing arrays to watch for.
def add(io, events)
fd = io.to_io.fileno
events = __event_flags(events)
@mtx.synchronize do
__ep_check
- @to_io.epoll_ctl(CTL_ADD, io, events)
+ @io.epoll_ctl(CTL_ADD, io, events)
@events[fd] = events
@marks[fd] = io
end
0
end
@@ -85,11 +90,11 @@
# Disables an IO object from being watched.
def del(io)
fd = io.to_io.fileno
@mtx.synchronize do
__ep_check
- @to_io.epoll_ctl(CTL_DEL, io, 0)
+ @io.epoll_ctl(CTL_DEL, io, 0)
@events[fd] = @marks[fd] = nil
end
0
end
@@ -108,11 +113,11 @@
fd = io.to_io.fileno
@mtx.synchronize do
__ep_check
cur_io = @marks[fd]
return if nil == cur_io || cur_io.to_io.closed?
- @to_io.epoll_ctl(CTL_DEL, io, 0)
+ @io.epoll_ctl(CTL_DEL, io, 0)
@events[fd] = @marks[fd] = nil
end
io
rescue Errno::ENOENT, Errno::EBADF
end
@@ -125,11 +130,11 @@
def mod(io, events)
events = __event_flags(events)
fd = io.to_io.fileno
@mtx.synchronize do
__ep_check
- @to_io.epoll_ctl(CTL_MOD, io, events)
+ @io.epoll_ctl(CTL_MOD, io, events)
@marks[fd] = io # may be a different object with same fd/file
@events[fd] = events
end
end
@@ -157,22 +162,22 @@
cur_io = @marks[fd]
if cur_io == io
cur_events = @events[fd]
return 0 if (cur_events & ONESHOT) == 0 && cur_events == events
begin
- @to_io.epoll_ctl(CTL_MOD, io, events)
+ @io.epoll_ctl(CTL_MOD, io, events)
rescue Errno::ENOENT
warn "epoll event cache failed (mod -> add)"
- @to_io.epoll_ctl(CTL_ADD, io, events)
+ @io.epoll_ctl(CTL_ADD, io, events)
@marks[fd] = io
end
else
begin
- @to_io.epoll_ctl(CTL_ADD, io, events)
+ @io.epoll_ctl(CTL_ADD, io, events)
rescue Errno::EEXIST
warn "epoll event cache failed (add -> mod)"
- @to_io.epoll_ctl(CTL_MOD, io, events)
+ @io.epoll_ctl(CTL_MOD, io, events)
end
@marks[fd] = io
end
@events[fd] = events
end
@@ -184,22 +189,22 @@
#
# Closes an existing Epoll object and returns memory back to the kernel.
# Raises IOError if object is already closed.
def close
@mtx.synchronize do
- @copies.delete(@to_io)
- @to_io.close
+ @copies.delete(@io)
+ @io.close
end
end
# call-seq:
# ep.closed? -> true or false
#
# Returns whether or not an Epoll object is closed.
def closed?
@mtx.synchronize do
- @to_io.closed?
+ @io.closed?
end
end
# we still support integer FDs for some debug functions
def __fileno(io) # :nodoc:
@@ -252,12 +257,12 @@
def initialize_copy(src) # :nodoc:
@mtx.synchronize do
__ep_check
rv = super
- unless @to_io.closed?
- @to_io = @to_io.dup
- @copies[@to_io] = self
+ unless @io.closed?
+ @io = @io.dup
+ @copies[@io] = self
end
rv
end
end
end