Sleepy_penguin 2.0.0 - Linux I/O events for Ruby

sleepy_penguin provides access to newer, Linux-only system calls to wait
on events from traditionally non-I/O sources. Bindings to the eventfd,
timerfd, inotify, signalfd and epoll interfaces are provided.

== Disclaimer

I’ve mainly written this to force myself to learn some of the newer
APIs in Linux 2.6 but maybe someone will find them useful one day.

If you’re writing portable software or want something other people use
in production, consider Cool.io[1] or EventMachine[2] instead.

== Features

  • Thread-safe blocking operations under both Ruby 1.8 and 1.9.

  • IO-like objects are backwards-compatible with IO.select.

  • Epoll interface is fork-safe and GC-safe

  • Unlike portable event frameworks, the Linux-only Epoll interface
    allows using edge-triggered I/O for possibly improved performance

  • Fully-documented and user-friendly API

Changes since 1.4.0:

There are many internal cleanups, bugfixes, and incompatible
API changes. The API will probably be stable from now on.

All the flag passing is less verbose, in the past you had
to do:

  tfd = TimerFD.new(TimerFD::CLOEXEC|TimerFD::NONBLOCK)

Now, you can just do (the old way still works):

  tfd = TimerFD.new([:CLOEXEC, :NONBLOCK])

A SignalFD interface now exists, but is not recommended since
MRI signal handling seems to conflict with it.

Inotify#close no longer holds the GVL while closing the
descriptor since it is an expensive operation.

See git log v1.4.0…v2.0.0 for all the gory details.

[1] - http://coolio.github.com/
[2] - http://rubyeventmachine.com/

Here is an idea, not sure if you’d like to pick it up because it would
mean extra work for you. :slight_smile:

But, I was wondering… this could be a nice small tutorial which could
teach some more people about both ruby and the new Linux API at the same
time. It is all decently documented but it is also the first time I have
heard of it.

It’s just a suggestion though. :slight_smile:

Marc H. [email protected] wrote:

Here is an idea, not sure if you’d like to pick it up because it would
mean extra work for you. :slight_smile:

But, I was wondering… this could be a nice small tutorial which could
teach some more people about both ruby and the new Linux API at the same
time. It is all decently documented but it is also the first time I have
heard of it.

Heh, I haven’t used it myself much (nor most of the things I publish).

I suppose most of the test cases are reasonable, maybe I’ll use TimerFD
in an upcoming release of raindrops[1] somewhere…

Thanks for the interest!

[1] http://raindrops.bogomips.org/ , git://bogomips.org/raindrops

Eric W. [email protected] wrote:

I suppose most of the test cases are reasonable, maybe I’ll use TimerFD
in an upcoming release of raindrops[1] somewhere…

I just pushed the following change out to raindrops.git. Not the
most useful example, but I like timerfd much more than timer_*
in POSIX (not sure if there are Ruby bindings for those, but in
many cases Kernel#sleep is perfectly adequate :slight_smile:

[1] http://raindrops.bogomips.org/ , git://bogomips.org/raindrops

From b0be66c37bb7080b0f06ab76b0e7d3404e2f9059 Mon Sep 17 00:00:00 2001
From: Eric W. [email protected]
Date: Mon, 14 Mar 2011 14:58:40 -0700
Subject: [PATCH] linux-listener-stats: use timerfd if available

It is more accurate than sleep and doesn’t require calculating
times

examples/linux-listener-stats.rb | 16 ++++++++++++++±
1 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/examples/linux-listener-stats.rb
b/examples/linux-listener-stats.rb
index 3494dff…ed58d27 100755
— a/examples/linux-listener-stats.rb
+++ b/examples/linux-listener-stats.rb
@@ -8,6 +8,10 @@ require ‘raindrops’
require ‘optparse’
require ‘ipaddr’
require ‘time’
+begin

  • require ‘sleepy_penguin’
    +rescue LoadError
    +end
    usage = “Usage: #$0 [-d DELAY] [-t QUEUED_THRESHOLD] ADDR…”
    ARGV.size > 0 or abort usage
    delay = false
    @@ -31,6 +35,16 @@ rescue LoadError
    $stderr.puts “Aggregate missing, USR1 and USR2 handlers unavailable”
    end if delay

+if delay && defined?(SleepyPenguin::TimerFD)

  • @tfd = SleepyPenguin::TimerFD.new
  • @tfd.settime nil, delay, delay
  • def delay_for(seconds)
  • @tfd.expirations
  • end
    +else
  • alias delay_for sleep
    +end

agg_active = agg_queued = nil
if delay && defined?(Aggregate)
agg_active = Aggregate.new
@@ -109,4 +123,4 @@ begin
next if queued < queued_thresh
printf fmt, now ||= Time.now.utc.iso8601, addr, active, queued
end
-end while delay && sleep(delay)
+end while delay && delay_for(delay)

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs