Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rubinius/rubinius
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 056ae04f0da0
Choose a base ref
...
head repository: rubinius/rubinius
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 69e843f20bae
Choose a head ref
  • 3 commits
  • 4 files changed
  • 1 contributor

Commits on Oct 1, 2015

  1. Copy the full SHA
    5f9e08d View commit details
  2. Copy the full SHA
    f08dadb View commit details
  3. Copy the full SHA
    69e843f View commit details
Showing with 75 additions and 12 deletions.
  1. +65 −12 kernel/common/io.rb
  2. +3 −0 kernel/platform/posix.rb
  3. +4 −0 vm/builtin/io.cpp
  4. +3 −0 vm/builtin/io.hpp
77 changes: 65 additions & 12 deletions kernel/common/io.rb
Original file line number Diff line number Diff line change
@@ -622,6 +622,8 @@ def sysseek(offset, whence=SEEK_SET)

# Encapsulates all of the logic necessary for handling #select.
class Select
#eval(Rubinius::Config['rbx.platform.timeval.class'])

class FDSet
def self.new
Rubinius.primitive :fdset_allocate
@@ -669,33 +671,84 @@ def self.fd_set_from_array(array)

return [fd_set, highest]
end

def self.collect_set_fds(array, fd_set)
return [] unless fd_set
array.select { |io| fd_set.set?(io.descriptor) || io.descriptor < 0 }
end

def self.make_timeout(time)


def self.timer_add(time1, time2, result)
result[:tv_sec] = time1[:tv_sec] + time2[:tv_sec]
result[:tv_usec] = time1[:tv_usec] + time2[:tv_usec]

if result[:tv_usec] >= 1_000_000
result[:tv_sec] += 1
result[:tv_usec] -= 1_000_000
end
end

def self.reset_timeout(limit, now)


def self.timer_sub(time1, time2, result)
result[:tv_sec] = time1[:tv_sec] - time2[:tv_sec]
result[:tv_usec] = time1[:tv_usec] - time2[:tv_usec]

if result[:tv_usec] < 0
result[:tv_sec] -= 1
result[:tv_usec] += 1_000_000
end
end


def self.make_timeval_timeout(timeout)
limit = Timeval_t.new
future = Timeval_t.new

if timeout
limit[:tv_sec] = (timeout / 1_000_000.0).to_i
limit[:tv_usec] = (timeout % 1_000_000.0)

# Get current time to be used if select is interrupted and we have to recalculate the sleep time
if FFI.call_failed?(FFI::Platform::POSIX.gettimeofday(future, nil))
Errno.handle("gettimeofday(2) failed")
end

timer_add(future, limit, future)
end

[limit, future]
end

def self.reset_timeval_timeout(time_limit, future)
now = Timeval_t.new

if FFI.call_failed?(FFI::Platform::POSIX.gettimeofday(now, nil))
Errno.handle("gettimeofday(2) failed")
end

timer_sub(future, now, time_limit)
end

def self.select(readables, writables, errorables, timeout)
read_set, highest_read_fd = readables.nil? ? [nil, nil] : fd_set_from_array(readables)
write_set, highest_write_fd = writables.nil? ? [nil, nil] : fd_set_from_array(writables)
error_set, highest_err_fd = errorables.nil? ? [nil, nil] : fd_set_from_array(errorables)
max_fd = [highest_read_fd, highest_write_fd, highest_err_fd].compact.max

time_limit, now = make_timeval_timeout(timeout)

unless const_defined?(:Timeval_t)
# This is a complete hack.
IO.class_eval(Rubinius::Config['rbx.platform.timeval.class'])
end

time_limit, future = make_timeval_timeout(timeout)

loop do
if FFI.called_failed?(events = FFI::Platform::POSIX.select(max_fd, read_set, write_set, error_set, time_limit))
if FFI.called_failed?(events = FFI::Platform::POSIX.select(max_fd,
read_set ? read_set.to_set : nil,
write_set ? write_set.to_set : nil,
error_set ? error_set.to_set : nil,
time_limit))

if Errno::EAGAIN::Errno == Errno.errno || Errno::EINTR::Errno == Errno.errno
# return nil if async_interruption?
time_limit, now = reset_timeval_timeout(time_limit, now)
time_limit = reset_timeval_timeout(time_limit, future)
continue
end

3 changes: 3 additions & 0 deletions kernel/platform/posix.rb
Original file line number Diff line number Diff line change
@@ -121,5 +121,8 @@ module FFI::Platform::POSIX
# related to stat()
attach_function :major, 'ffi_major', [:dev_t], :dev_t
attach_function :minor, 'ffi_minor', [:dev_t], :dev_t

# time
attach_function :gettimeofday, [:pointer, :pointer], :int
end
end
4 changes: 4 additions & 0 deletions vm/builtin/io.cpp
Original file line number Diff line number Diff line change
@@ -1560,5 +1560,9 @@ namespace rubinius {
}
}

Object* FDSet::to_set(STATE) {
return ((Object*)&descriptor_set);
}

}; // ends namespace rubinius

3 changes: 3 additions & 0 deletions vm/builtin/io.hpp
Original file line number Diff line number Diff line change
@@ -232,6 +232,9 @@ namespace rubinius {

// Rubinius.primitive :fdset_set
Object* set(STATE, Fixnum* descriptor);

// Rubinius.primitive :fdset_to_set
Object* to_set(STATE);

class Info : public TypeInfo {
public: